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/cam/scsi/scsi_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 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1997 Justin T. Gibbs.
    5  * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Kenneth D. Merry.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions, and the following disclaimer,
   13  *    without modification, immediately at the beginning of the file.
   14  * 2. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 /*-
   31  * Portions of this driver taken from the original FreeBSD cd driver.
   32  * Written by Julian Elischer (julian@tfs.com)
   33  * for TRW Financial Systems for use under the MACH(2.5) operating system.
   34  *
   35  * TRW Financial Systems, in accordance with their agreement with Carnegie
   36  * Mellon University, makes this software available to CMU to distribute
   37  * or use in any manner that they see fit as long as this message is kept with
   38  * the software. For this reason TFS also grants any other persons or
   39  * organisations permission to use or modify this software.
   40  *
   41  * TFS supplies this software to be publicly redistributed
   42  * on the understanding that TFS is not responsible for the correct
   43  * functioning of this software in any circumstances.
   44  *
   45  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
   46  *
   47  *      from: cd.c,v 1.83 1997/05/04 15:24:22 joerg Exp $
   48  */
   49 
   50 #include <sys/cdefs.h>
   51 __FBSDID("$FreeBSD$");
   52 
   53 #include "opt_cd.h"
   54 
   55 #include <sys/param.h>
   56 #include <sys/systm.h>
   57 #include <sys/kernel.h>
   58 #include <sys/bio.h>
   59 #include <sys/conf.h>
   60 #include <sys/disk.h>
   61 #include <sys/malloc.h>
   62 #include <sys/cdio.h>
   63 #include <sys/cdrio.h>
   64 #include <sys/dvdio.h>
   65 #include <sys/devicestat.h>
   66 #include <sys/proc.h>
   67 #include <sys/sbuf.h>
   68 #include <sys/sysctl.h>
   69 #include <sys/taskqueue.h>
   70 #include <geom/geom_disk.h>
   71 
   72 #include <cam/cam.h>
   73 #include <cam/cam_ccb.h>
   74 #include <cam/cam_periph.h>
   75 #include <cam/cam_xpt_periph.h>
   76 #include <cam/cam_queue.h>
   77 #include <cam/cam_sim.h>
   78 
   79 #include <cam/scsi/scsi_message.h>
   80 #include <cam/scsi/scsi_da.h>
   81 #include <cam/scsi/scsi_cd.h>
   82 
   83 #define LEADOUT         0xaa            /* leadout toc entry */
   84 
   85 struct cd_params {
   86         u_int32_t blksize;
   87         u_long    disksize;
   88 };
   89 
   90 typedef enum {
   91         CD_Q_NONE               = 0x00,
   92         CD_Q_NO_TOUCH           = 0x01,
   93         CD_Q_BCD_TRACKS         = 0x02,
   94         CD_Q_10_BYTE_ONLY       = 0x10,
   95         CD_Q_RETRY_BUSY         = 0x40
   96 } cd_quirks;
   97 
   98 #define CD_Q_BIT_STRING         \
   99         "\020"                  \
  100         "\001NO_TOUCH"          \
  101         "\002BCD_TRACKS"        \
  102         "\00510_BYTE_ONLY"      \
  103         "\007RETRY_BUSY"
  104 
  105 typedef enum {
  106         CD_FLAG_INVALID         = 0x0001,
  107         CD_FLAG_NEW_DISC        = 0x0002,
  108         CD_FLAG_DISC_LOCKED     = 0x0004,
  109         CD_FLAG_DISC_REMOVABLE  = 0x0008,
  110         CD_FLAG_SAW_MEDIA       = 0x0010,
  111         CD_FLAG_ACTIVE          = 0x0080,
  112         CD_FLAG_SCHED_ON_COMP   = 0x0100,
  113         CD_FLAG_RETRY_UA        = 0x0200,
  114         CD_FLAG_VALID_MEDIA     = 0x0400,
  115         CD_FLAG_VALID_TOC       = 0x0800,
  116         CD_FLAG_SCTX_INIT       = 0x1000,
  117         CD_FLAG_MEDIA_WAIT      = 0x2000,
  118         CD_FLAG_MEDIA_SCAN_ACT  = 0x4000
  119 } cd_flags;
  120 
  121 typedef enum {
  122         CD_CCB_PROBE            = 0x01,
  123         CD_CCB_BUFFER_IO        = 0x02,
  124         CD_CCB_TUR              = 0x03,
  125         CD_CCB_MEDIA_PREVENT    = 0x04,
  126         CD_CCB_MEDIA_ALLOW      = 0x05,
  127         CD_CCB_MEDIA_SIZE       = 0x06,
  128         CD_CCB_MEDIA_TOC_HDR    = 0x07,
  129         CD_CCB_MEDIA_TOC_FULL   = 0x08,
  130         CD_CCB_MEDIA_TOC_LEAD   = 0x09,
  131         CD_CCB_TYPE_MASK        = 0x0F,
  132         CD_CCB_RETRY_UA         = 0x10
  133 } cd_ccb_state;
  134 
  135 #define ccb_state ppriv_field0
  136 #define ccb_bp ppriv_ptr1
  137 
  138 /*
  139  * According to the MMC-6 spec, 6.25.3.2.11, the lead-out is reported by
  140  * READ_TOC as logical track 170, so at most 169 tracks may be reported.
  141  */
  142 struct cd_tocdata {
  143         struct ioc_toc_header header;
  144         struct cd_toc_entry entries[170];
  145 };
  146 
  147 struct cd_toc_single {
  148         struct ioc_toc_header header;
  149         struct cd_toc_entry entry;
  150 };
  151 
  152 typedef enum {
  153         CD_STATE_PROBE,
  154         CD_STATE_NORMAL,
  155         CD_STATE_MEDIA_PREVENT,
  156         CD_STATE_MEDIA_ALLOW,
  157         CD_STATE_MEDIA_SIZE,
  158         CD_STATE_MEDIA_TOC_HDR,
  159         CD_STATE_MEDIA_TOC_FULL,
  160         CD_STATE_MEDIA_TOC_LEAD
  161 } cd_state;
  162 
  163 struct cd_softc {
  164         cam_pinfo               pinfo;
  165         cd_state                state;
  166         volatile cd_flags       flags;
  167         struct bio_queue_head   bio_queue;
  168         LIST_HEAD(, ccb_hdr)    pending_ccbs;
  169         struct cd_params        params;
  170         cd_quirks               quirks;
  171         struct cam_periph       *periph;
  172         int                     minimum_command_size;
  173         int                     outstanding_cmds;
  174         int                     tur;
  175         struct task             sysctl_task;
  176         struct sysctl_ctx_list  sysctl_ctx;
  177         struct sysctl_oid       *sysctl_tree;
  178         STAILQ_HEAD(, cd_mode_params)   mode_queue;
  179         struct cd_tocdata       toc;
  180         int                     toc_read_len;
  181         struct cd_toc_single    leadout;
  182         struct disk             *disk;
  183         struct callout          mediapoll_c;
  184 
  185 #define CD_ANNOUNCETMP_SZ 120
  186         char                    announce_temp[CD_ANNOUNCETMP_SZ];
  187 #define CD_ANNOUNCE_SZ 400
  188         char                    announce_buf[CD_ANNOUNCE_SZ];
  189 };
  190 
  191 struct cd_page_sizes {
  192         int page;
  193         int page_size;
  194 };
  195 
  196 static struct cd_page_sizes cd_page_size_table[] =
  197 {
  198         { AUDIO_PAGE, sizeof(struct cd_audio_page)}
  199 };
  200 
  201 struct cd_quirk_entry {
  202         struct scsi_inquiry_pattern inq_pat;
  203         cd_quirks quirks;
  204 };
  205 
  206 /*
  207  * NOTE ON 10_BYTE_ONLY quirks:  Any 10_BYTE_ONLY quirks MUST be because
  208  * your device hangs when it gets a 10 byte command.  Adding a quirk just
  209  * to get rid of the informative diagnostic message is not acceptable.  All
  210  * 10_BYTE_ONLY quirks must be documented in full in a PR (which should be
  211  * referenced in a comment along with the quirk) , and must be approved by
  212  * ken@FreeBSD.org.  Any quirks added that don't adhere to this policy may
  213  * be removed until the submitter can explain why they are needed.
  214  * 10_BYTE_ONLY quirks will be removed (as they will no longer be necessary)
  215  * when the CAM_NEW_TRAN_CODE work is done.
  216  */
  217 static struct cd_quirk_entry cd_quirk_table[] =
  218 {
  219         {
  220                 { T_CDROM, SIP_MEDIA_REMOVABLE, "CHINON", "CD-ROM CDS-535","*"},
  221                 /* quirks */ CD_Q_BCD_TRACKS
  222         },
  223         {
  224                 /*
  225                  * VMware returns BUSY status when storage has transient
  226                  * connectivity problems, so better wait.
  227                  */
  228                 {T_CDROM, SIP_MEDIA_REMOVABLE, "NECVMWar", "VMware IDE CDR10", "*"},
  229                 /*quirks*/ CD_Q_RETRY_BUSY
  230         }
  231 };
  232 
  233 #ifdef COMPAT_FREEBSD32
  234 struct ioc_read_toc_entry32 {
  235         u_char  address_format;
  236         u_char  starting_track;
  237         u_short data_len;
  238         uint32_t data;  /* (struct cd_toc_entry *) */
  239 };
  240 #define CDIOREADTOCENTRYS_32    \
  241     _IOC_NEWTYPE(CDIOREADTOCENTRYS, struct ioc_read_toc_entry32)
  242 #endif
  243 
  244 static  disk_open_t     cdopen;
  245 static  disk_close_t    cdclose;
  246 static  disk_ioctl_t    cdioctl;
  247 static  disk_strategy_t cdstrategy;
  248 
  249 static  periph_init_t   cdinit;
  250 static  periph_ctor_t   cdregister;
  251 static  periph_dtor_t   cdcleanup;
  252 static  periph_start_t  cdstart;
  253 static  periph_oninv_t  cdoninvalidate;
  254 static  void            cdasync(void *callback_arg, u_int32_t code,
  255                                 struct cam_path *path, void *arg);
  256 static  int             cdcmdsizesysctl(SYSCTL_HANDLER_ARGS);
  257 static  int             cdrunccb(union ccb *ccb,
  258                                  int (*error_routine)(union ccb *ccb,
  259                                                       u_int32_t cam_flags,
  260                                                       u_int32_t sense_flags),
  261                                  u_int32_t cam_flags, u_int32_t sense_flags);
  262 static  void            cddone(struct cam_periph *periph,
  263                                union ccb *start_ccb);
  264 static  union cd_pages  *cdgetpage(struct cd_mode_params *mode_params);
  265 static  int             cdgetpagesize(int page_num);
  266 static  void            cdprevent(struct cam_periph *periph, int action);
  267 static  void            cdmediaprobedone(struct cam_periph *periph);
  268 static  int             cdcheckmedia(struct cam_periph *periph, int do_wait);
  269 #if 0
  270 static  int             cdsize(struct cam_periph *periph, u_int32_t *size);
  271 #endif
  272 static  int             cd6byteworkaround(union ccb *ccb);
  273 static  int             cderror(union ccb *ccb, u_int32_t cam_flags,
  274                                 u_int32_t sense_flags);
  275 static  int             cdreadtoc(struct cam_periph *periph, u_int32_t mode,
  276                                   u_int32_t start, u_int8_t *data,
  277                                   u_int32_t len, u_int32_t sense_flags);
  278 static  int             cdgetmode(struct cam_periph *periph,
  279                                   struct cd_mode_params *data, u_int32_t page);
  280 static  int             cdsetmode(struct cam_periph *periph,
  281                                   struct cd_mode_params *data);
  282 static  int             cdplay(struct cam_periph *periph, u_int32_t blk,
  283                                u_int32_t len);
  284 static  int             cdreadsubchannel(struct cam_periph *periph,
  285                                          u_int32_t mode, u_int32_t format,
  286                                          int track,
  287                                          struct cd_sub_channel_info *data,
  288                                          u_int32_t len);
  289 static  int             cdplaymsf(struct cam_periph *periph, u_int32_t startm,
  290                                   u_int32_t starts, u_int32_t startf,
  291                                   u_int32_t endm, u_int32_t ends,
  292                                   u_int32_t endf);
  293 static  int             cdplaytracks(struct cam_periph *periph,
  294                                      u_int32_t strack, u_int32_t sindex,
  295                                      u_int32_t etrack, u_int32_t eindex);
  296 static  int             cdpause(struct cam_periph *periph, u_int32_t go);
  297 static  int             cdstopunit(struct cam_periph *periph, u_int32_t eject);
  298 static  int             cdstartunit(struct cam_periph *periph, int load);
  299 static  int             cdsetspeed(struct cam_periph *periph,
  300                                    u_int32_t rdspeed, u_int32_t wrspeed);
  301 static  int             cdreportkey(struct cam_periph *periph,
  302                                     struct dvd_authinfo *authinfo);
  303 static  int             cdsendkey(struct cam_periph *periph,
  304                                   struct dvd_authinfo *authinfo);
  305 static  int             cdreaddvdstructure(struct cam_periph *periph,
  306                                            struct dvd_struct *dvdstruct);
  307 static  callout_func_t  cdmediapoll;
  308 
  309 static struct periph_driver cddriver =
  310 {
  311         cdinit, "cd",
  312         TAILQ_HEAD_INITIALIZER(cddriver.units), /* generation */ 0
  313 };
  314 
  315 PERIPHDRIVER_DECLARE(cd, cddriver);
  316 
  317 #ifndef CD_DEFAULT_POLL_PERIOD
  318 #define CD_DEFAULT_POLL_PERIOD  3
  319 #endif
  320 #ifndef CD_DEFAULT_RETRY
  321 #define CD_DEFAULT_RETRY        4
  322 #endif
  323 #ifndef CD_DEFAULT_TIMEOUT
  324 #define CD_DEFAULT_TIMEOUT      30000
  325 #endif
  326 
  327 static int cd_poll_period = CD_DEFAULT_POLL_PERIOD;
  328 static int cd_retry_count = CD_DEFAULT_RETRY;
  329 static int cd_timeout = CD_DEFAULT_TIMEOUT;
  330 
  331 static SYSCTL_NODE(_kern_cam, OID_AUTO, cd, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  332     "CAM CDROM driver");
  333 SYSCTL_INT(_kern_cam_cd, OID_AUTO, poll_period, CTLFLAG_RWTUN,
  334            &cd_poll_period, 0, "Media polling period in seconds");
  335 SYSCTL_INT(_kern_cam_cd, OID_AUTO, retry_count, CTLFLAG_RWTUN,
  336            &cd_retry_count, 0, "Normal I/O retry count");
  337 SYSCTL_INT(_kern_cam_cd, OID_AUTO, timeout, CTLFLAG_RWTUN,
  338            &cd_timeout, 0, "Timeout, in us, for read operations");
  339 
  340 static MALLOC_DEFINE(M_SCSICD, "scsi_cd", "scsi_cd buffers");
  341 
  342 static void
  343 cdinit(void)
  344 {
  345         cam_status status;
  346 
  347         /*
  348          * Install a global async callback.  This callback will
  349          * receive async callbacks like "new device found".
  350          */
  351         status = xpt_register_async(AC_FOUND_DEVICE, cdasync, NULL, NULL);
  352 
  353         if (status != CAM_REQ_CMP) {
  354                 printf("cd: Failed to attach master async callback "
  355                        "due to status 0x%x!\n", status);
  356         }
  357 }
  358 
  359 /*
  360  * Callback from GEOM, called when it has finished cleaning up its
  361  * resources.
  362  */
  363 static void
  364 cddiskgonecb(struct disk *dp)
  365 {
  366         struct cam_periph *periph;
  367 
  368         periph = (struct cam_periph *)dp->d_drv1;
  369         cam_periph_release(periph);
  370 }
  371 
  372 static void
  373 cdoninvalidate(struct cam_periph *periph)
  374 {
  375         struct cd_softc *softc;
  376 
  377         cam_periph_assert(periph, MA_OWNED);
  378         softc = (struct cd_softc *)periph->softc;
  379 
  380         /*
  381          * De-register any async callbacks.
  382          */
  383         xpt_register_async(0, cdasync, periph, periph->path);
  384 
  385         softc->flags |= CD_FLAG_INVALID;
  386 
  387         /*
  388          * Return all queued I/O with ENXIO.
  389          * XXX Handle any transactions queued to the card
  390          *     with XPT_ABORT_CCB.
  391          */
  392         bioq_flush(&softc->bio_queue, NULL, ENXIO);
  393 
  394         disk_gone(softc->disk);
  395 }
  396 
  397 static void
  398 cdcleanup(struct cam_periph *periph)
  399 {
  400         struct cd_softc *softc;
  401 
  402         softc = (struct cd_softc *)periph->softc;
  403 
  404         cam_periph_unlock(periph);
  405         if ((softc->flags & CD_FLAG_SCTX_INIT) != 0
  406             && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
  407                 xpt_print(periph->path, "can't remove sysctl context\n");
  408         }
  409 
  410         callout_drain(&softc->mediapoll_c);
  411         disk_destroy(softc->disk);
  412         free(softc, M_DEVBUF);
  413         cam_periph_lock(periph);
  414 }
  415 
  416 static void
  417 cdasync(void *callback_arg, u_int32_t code,
  418         struct cam_path *path, void *arg)
  419 {
  420         struct cam_periph *periph;
  421         struct cd_softc *softc;
  422 
  423         periph = (struct cam_periph *)callback_arg;
  424         switch (code) {
  425         case AC_FOUND_DEVICE:
  426         {
  427                 struct ccb_getdev *cgd;
  428                 cam_status status;
  429 
  430                 cgd = (struct ccb_getdev *)arg;
  431                 if (cgd == NULL)
  432                         break;
  433 
  434                 if (cgd->protocol != PROTO_SCSI)
  435                         break;
  436                 if (SID_QUAL(&cgd->inq_data) != SID_QUAL_LU_CONNECTED)
  437                         break;
  438                 if (SID_TYPE(&cgd->inq_data) != T_CDROM
  439                     && SID_TYPE(&cgd->inq_data) != T_WORM)
  440                         break;
  441 
  442                 /*
  443                  * Allocate a peripheral instance for
  444                  * this device and start the probe
  445                  * process.
  446                  */
  447                 status = cam_periph_alloc(cdregister, cdoninvalidate,
  448                                           cdcleanup, cdstart,
  449                                           "cd", CAM_PERIPH_BIO,
  450                                           path, cdasync,
  451                                           AC_FOUND_DEVICE, cgd);
  452 
  453                 if (status != CAM_REQ_CMP
  454                  && status != CAM_REQ_INPROG)
  455                         printf("cdasync: Unable to attach new device "
  456                                "due to status 0x%x\n", status);
  457 
  458                 return;
  459         }
  460         case AC_UNIT_ATTENTION:
  461         {
  462                 union ccb *ccb;
  463                 int error_code, sense_key, asc, ascq;
  464 
  465                 softc = (struct cd_softc *)periph->softc;
  466                 ccb = (union ccb *)arg;
  467 
  468                 /*
  469                  * Handle all media change UNIT ATTENTIONs except
  470                  * our own, as they will be handled by cderror().
  471                  */
  472                 if (xpt_path_periph(ccb->ccb_h.path) != periph &&
  473                     scsi_extract_sense_ccb(ccb,
  474                      &error_code, &sense_key, &asc, &ascq)) {
  475                         if (asc == 0x28 && ascq == 0x00)
  476                                 disk_media_changed(softc->disk, M_NOWAIT);
  477                 }
  478                 break;
  479         }
  480         case AC_SCSI_AEN:
  481                 cam_periph_assert(periph, MA_OWNED);
  482                 softc = (struct cd_softc *)periph->softc;
  483                 if (softc->state == CD_STATE_NORMAL && !softc->tur) {
  484                         if (cam_periph_acquire(periph) == 0) {
  485                                 softc->tur = 1;
  486                                 xpt_schedule(periph, CAM_PRIORITY_NORMAL);
  487                         }
  488                 }
  489                 /* FALLTHROUGH */
  490         case AC_SENT_BDR:
  491         case AC_BUS_RESET:
  492         {
  493                 struct ccb_hdr *ccbh;
  494 
  495                 cam_periph_assert(periph, MA_OWNED);
  496                 softc = (struct cd_softc *)periph->softc;
  497                 /*
  498                  * Don't fail on the expected unit attention
  499                  * that will occur.
  500                  */
  501                 softc->flags |= CD_FLAG_RETRY_UA;
  502                 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
  503                         ccbh->ccb_state |= CD_CCB_RETRY_UA;
  504                 break;
  505         }
  506         default:
  507                 break;
  508         }
  509 
  510         cam_periph_async(periph, code, path, arg);
  511 }
  512 
  513 static void
  514 cdsysctlinit(void *context, int pending)
  515 {
  516         struct cam_periph *periph;
  517         struct cd_softc *softc;
  518         char tmpstr[32], tmpstr2[16];
  519 
  520         periph = (struct cam_periph *)context;
  521         if (cam_periph_acquire(periph) != 0)
  522                 return;
  523 
  524         softc = (struct cd_softc *)periph->softc;
  525         snprintf(tmpstr, sizeof(tmpstr), "CAM CD unit %d", periph->unit_number);
  526         snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
  527 
  528         sysctl_ctx_init(&softc->sysctl_ctx);
  529         cam_periph_lock(periph);
  530         softc->flags |= CD_FLAG_SCTX_INIT;
  531         cam_periph_unlock(periph);
  532         softc->sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&softc->sysctl_ctx,
  533                 SYSCTL_STATIC_CHILDREN(_kern_cam_cd), OID_AUTO,
  534                 tmpstr2, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, tmpstr,
  535                 "device_index");
  536 
  537         if (softc->sysctl_tree == NULL) {
  538                 printf("cdsysctlinit: unable to allocate sysctl tree\n");
  539                 cam_periph_release(periph);
  540                 return;
  541         }
  542 
  543         /*
  544          * Now register the sysctl handler, so the user can the value on
  545          * the fly.
  546          */
  547         SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
  548                 OID_AUTO, "minimum_cmd_size",
  549                 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
  550                 &softc->minimum_command_size, 0, cdcmdsizesysctl, "I",
  551                 "Minimum CDB size");
  552 
  553         cam_periph_release(periph);
  554 }
  555 
  556 /*
  557  * We have a handler function for this so we can check the values when the
  558  * user sets them, instead of every time we look at them.
  559  */
  560 static int
  561 cdcmdsizesysctl(SYSCTL_HANDLER_ARGS)
  562 {
  563         int error, value;
  564 
  565         value = *(int *)arg1;
  566 
  567         error = sysctl_handle_int(oidp, &value, 0, req);
  568 
  569         if ((error != 0)
  570          || (req->newptr == NULL))
  571                 return (error);
  572 
  573         /*
  574          * The only real values we can have here are 6 or 10.  I don't
  575          * really forsee having 12 be an option at any time in the future.
  576          * So if the user sets something less than or equal to 6, we'll set
  577          * it to 6.  If he sets something greater than 6, we'll set it to 10.
  578          *
  579          * I suppose we could just return an error here for the wrong values,
  580          * but I don't think it's necessary to do so, as long as we can
  581          * determine the user's intent without too much trouble.
  582          */
  583         if (value < 6)
  584                 value = 6;
  585         else if (value > 6)
  586                 value = 10;
  587 
  588         *(int *)arg1 = value;
  589 
  590         return (0);
  591 }
  592 
  593 static cam_status
  594 cdregister(struct cam_periph *periph, void *arg)
  595 {
  596         struct cd_softc *softc;
  597         struct ccb_pathinq cpi;
  598         struct ccb_getdev *cgd;
  599         char tmpstr[80];
  600         caddr_t match;
  601 
  602         cgd = (struct ccb_getdev *)arg;
  603         if (cgd == NULL) {
  604                 printf("cdregister: no getdev CCB, can't register device\n");
  605                 return(CAM_REQ_CMP_ERR);
  606         }
  607 
  608         softc = (struct cd_softc *)malloc(sizeof(*softc),M_DEVBUF,
  609             M_NOWAIT | M_ZERO);
  610         if (softc == NULL) {
  611                 printf("cdregister: Unable to probe new device. "
  612                        "Unable to allocate softc\n");
  613                 return(CAM_REQ_CMP_ERR);
  614         }
  615 
  616         LIST_INIT(&softc->pending_ccbs);
  617         STAILQ_INIT(&softc->mode_queue);
  618         softc->state = CD_STATE_PROBE;
  619         bioq_init(&softc->bio_queue);
  620         if (SID_IS_REMOVABLE(&cgd->inq_data))
  621                 softc->flags |= CD_FLAG_DISC_REMOVABLE;
  622 
  623         periph->softc = softc;
  624         softc->periph = periph;
  625 
  626         /*
  627          * See if this device has any quirks.
  628          */
  629         match = cam_quirkmatch((caddr_t)&cgd->inq_data,
  630                                (caddr_t)cd_quirk_table,
  631                                nitems(cd_quirk_table),
  632                                sizeof(*cd_quirk_table), scsi_inquiry_match);
  633 
  634         if (match != NULL)
  635                 softc->quirks = ((struct cd_quirk_entry *)match)->quirks;
  636         else
  637                 softc->quirks = CD_Q_NONE;
  638 
  639         /* Check if the SIM does not want 6 byte commands */
  640         xpt_path_inq(&cpi, periph->path);
  641         if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
  642                 softc->quirks |= CD_Q_10_BYTE_ONLY;
  643 
  644         TASK_INIT(&softc->sysctl_task, 0, cdsysctlinit, periph);
  645 
  646         /* The default is 6 byte commands, unless quirked otherwise */
  647         if (softc->quirks & CD_Q_10_BYTE_ONLY)
  648                 softc->minimum_command_size = 10;
  649         else
  650                 softc->minimum_command_size = 6;
  651 
  652         /*
  653          * Take a reference on the periph while cdstart is called to finish the
  654          * probe.  The reference will be dropped in cddone at the end of probe.
  655          */
  656         (void)cam_periph_acquire(periph);
  657         cam_periph_unlock(periph);
  658         /*
  659          * Load the user's default, if any.
  660          */
  661         snprintf(tmpstr, sizeof(tmpstr), "kern.cam.cd.%d.minimum_cmd_size",
  662                  periph->unit_number);
  663         TUNABLE_INT_FETCH(tmpstr, &softc->minimum_command_size);
  664 
  665         /* 6 and 10 are the only permissible values here. */
  666         if (softc->minimum_command_size < 6)
  667                 softc->minimum_command_size = 6;
  668         else if (softc->minimum_command_size > 6)
  669                 softc->minimum_command_size = 10;
  670 
  671         /*
  672          * We need to register the statistics structure for this device,
  673          * but we don't have the blocksize yet for it.  So, we register
  674          * the structure and indicate that we don't have the blocksize
  675          * yet.  Unlike other SCSI peripheral drivers, we explicitly set
  676          * the device type here to be CDROM, rather than just ORing in
  677          * the device type.  This is because this driver can attach to either
  678          * CDROM or WORM devices, and we want this peripheral driver to
  679          * show up in the devstat list as a CD peripheral driver, not a
  680          * WORM peripheral driver.  WORM drives will also have the WORM
  681          * driver attached to them.
  682          */
  683         softc->disk = disk_alloc();
  684         softc->disk->d_devstat = devstat_new_entry("cd",
  685                           periph->unit_number, 0,
  686                           DEVSTAT_BS_UNAVAILABLE,
  687                           DEVSTAT_TYPE_CDROM |
  688                           XPORT_DEVSTAT_TYPE(cpi.transport),
  689                           DEVSTAT_PRIORITY_CD);
  690         softc->disk->d_open = cdopen;
  691         softc->disk->d_close = cdclose;
  692         softc->disk->d_strategy = cdstrategy;
  693         softc->disk->d_gone = cddiskgonecb;
  694         softc->disk->d_ioctl = cdioctl;
  695         softc->disk->d_name = "cd";
  696         cam_strvis(softc->disk->d_descr, cgd->inq_data.vendor,
  697             sizeof(cgd->inq_data.vendor), sizeof(softc->disk->d_descr));
  698         strlcat(softc->disk->d_descr, " ", sizeof(softc->disk->d_descr));
  699         cam_strvis(&softc->disk->d_descr[strlen(softc->disk->d_descr)],
  700             cgd->inq_data.product, sizeof(cgd->inq_data.product),
  701             sizeof(softc->disk->d_descr) - strlen(softc->disk->d_descr));
  702         softc->disk->d_unit = periph->unit_number;
  703         softc->disk->d_drv1 = periph;
  704         if (cpi.maxio == 0)
  705                 softc->disk->d_maxsize = DFLTPHYS;      /* traditional default */
  706         else if (cpi.maxio > maxphys)
  707                 softc->disk->d_maxsize = maxphys;       /* for safety */
  708         else
  709                 softc->disk->d_maxsize = cpi.maxio;
  710         softc->disk->d_flags = 0;
  711         softc->disk->d_hba_vendor = cpi.hba_vendor;
  712         softc->disk->d_hba_device = cpi.hba_device;
  713         softc->disk->d_hba_subvendor = cpi.hba_subvendor;
  714         softc->disk->d_hba_subdevice = cpi.hba_subdevice;
  715         snprintf(softc->disk->d_attachment, sizeof(softc->disk->d_attachment),
  716             "%s%d", cpi.dev_name, cpi.unit_number);
  717         cam_periph_lock(periph);
  718 
  719         /*
  720          * Add an async callback so that we get
  721          * notified if this device goes away.
  722          */
  723         xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE |
  724             AC_SCSI_AEN | AC_UNIT_ATTENTION, cdasync, periph, periph->path);
  725 
  726         /*
  727          * Schedule a periodic media polling events.
  728          */
  729         callout_init_mtx(&softc->mediapoll_c, cam_periph_mtx(periph), 0);
  730         if ((softc->flags & CD_FLAG_DISC_REMOVABLE) &&
  731             (cgd->inq_flags & SID_AEN) == 0 &&
  732             cd_poll_period != 0) {
  733                 callout_reset_sbt(&softc->mediapoll_c, cd_poll_period * SBT_1S,
  734                     0, cdmediapoll, periph, C_PREL(1));
  735         }
  736 
  737         /* Released after probe when disk_create() call pass it to GEOM. */
  738         cam_periph_hold_boot(periph);
  739 
  740         xpt_schedule(periph, CAM_PRIORITY_DEV);
  741         return(CAM_REQ_CMP);
  742 }
  743 
  744 static int
  745 cdopen(struct disk *dp)
  746 {
  747         struct cam_periph *periph;
  748         struct cd_softc *softc;
  749         int error;
  750 
  751         periph = (struct cam_periph *)dp->d_drv1;
  752         softc = (struct cd_softc *)periph->softc;
  753 
  754         if (cam_periph_acquire(periph) != 0)
  755                 return(ENXIO);
  756 
  757         cam_periph_lock(periph);
  758 
  759         if (softc->flags & CD_FLAG_INVALID) {
  760                 cam_periph_release_locked(periph);
  761                 cam_periph_unlock(periph);
  762                 return(ENXIO);
  763         }
  764 
  765         if ((error = cam_periph_hold(periph, PRIBIO | PCATCH)) != 0) {
  766                 cam_periph_release_locked(periph);
  767                 cam_periph_unlock(periph);
  768                 return (error);
  769         }
  770 
  771         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
  772             ("cdopen\n"));
  773 
  774         /*
  775          * Check for media, and set the appropriate flags.  We don't bail
  776          * if we don't have media, but then we don't allow anything but the
  777          * CDIOCEJECT/CDIOCCLOSE ioctls if there is no media.
  778          */
  779         cdcheckmedia(periph, /*do_wait*/ 1);
  780 
  781         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n"));
  782         cam_periph_unhold(periph);
  783 
  784         cam_periph_unlock(periph);
  785 
  786         return (0);
  787 }
  788 
  789 static int
  790 cdclose(struct disk *dp)
  791 {
  792         struct  cam_periph *periph;
  793         struct  cd_softc *softc;
  794 
  795         periph = (struct cam_periph *)dp->d_drv1;
  796         softc = (struct cd_softc *)periph->softc;
  797 
  798         cam_periph_lock(periph);
  799         if (cam_periph_hold(periph, PRIBIO) != 0) {
  800                 cam_periph_unlock(periph);
  801                 cam_periph_release(periph);
  802                 return (0);
  803         }
  804 
  805         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
  806             ("cdclose\n"));
  807 
  808         if ((softc->flags & CD_FLAG_DISC_REMOVABLE) != 0)
  809                 cdprevent(periph, PR_ALLOW);
  810 
  811         /*
  812          * Since we're closing this CD, mark the blocksize as unavailable.
  813          * It will be marked as available when the CD is opened again.
  814          */
  815         softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
  816 
  817         /*
  818          * We'll check the media and toc again at the next open().
  819          */
  820         softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC);
  821 
  822         cam_periph_unhold(periph);
  823         cam_periph_release_locked(periph);
  824         cam_periph_unlock(periph);
  825 
  826         return (0);
  827 }
  828 
  829 static int
  830 cdrunccb(union ccb *ccb, int (*error_routine)(union ccb *ccb,
  831                                               u_int32_t cam_flags,
  832                                               u_int32_t sense_flags),
  833          u_int32_t cam_flags, u_int32_t sense_flags)
  834 {
  835         struct cd_softc *softc;
  836         struct cam_periph *periph;
  837         int error;
  838 
  839         periph = xpt_path_periph(ccb->ccb_h.path);
  840         softc = (struct cd_softc *)periph->softc;
  841 
  842         error = cam_periph_runccb(ccb, error_routine, cam_flags, sense_flags,
  843                                   softc->disk->d_devstat);
  844 
  845         return(error);
  846 }
  847 
  848 /*
  849  * Actually translate the requested transfer into one the physical driver
  850  * can understand.  The transfer is described by a buf and will include
  851  * only one physical transfer.
  852  */
  853 static void
  854 cdstrategy(struct bio *bp)
  855 {
  856         struct cam_periph *periph;
  857         struct cd_softc *softc;
  858 
  859         periph = (struct cam_periph *)bp->bio_disk->d_drv1;
  860         cam_periph_lock(periph);
  861         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
  862             ("cdstrategy(%p)\n", bp));
  863 
  864         softc = (struct cd_softc *)periph->softc;
  865 
  866         /*
  867          * If the device has been made invalid, error out
  868          */
  869         if ((softc->flags & CD_FLAG_INVALID)) {
  870                 cam_periph_unlock(periph);
  871                 biofinish(bp, NULL, ENXIO);
  872                 return;
  873         }
  874 
  875         /*
  876          * Place it in the queue of disk activities for this disk
  877          */
  878         bioq_disksort(&softc->bio_queue, bp);
  879 
  880         /*
  881          * If we don't know that we have valid media, schedule the media
  882          * check first.  The I/O will get executed after the media check.
  883          */
  884         if ((softc->flags & CD_FLAG_VALID_MEDIA) == 0)
  885                 cdcheckmedia(periph, /*do_wait*/ 0);
  886         else
  887                 xpt_schedule(periph, CAM_PRIORITY_NORMAL);
  888 
  889         cam_periph_unlock(periph);
  890         return;
  891 }
  892 
  893 static void
  894 cdstart(struct cam_periph *periph, union ccb *start_ccb)
  895 {
  896         struct cd_softc *softc;
  897         struct bio *bp;
  898         struct ccb_scsiio *csio;
  899 
  900         cam_periph_assert(periph, MA_OWNED);
  901         softc = (struct cd_softc *)periph->softc;
  902 
  903         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdstart\n"));
  904 
  905         switch (softc->state) {
  906         case CD_STATE_NORMAL:
  907         {
  908                 bp = bioq_first(&softc->bio_queue);
  909                 if (bp == NULL) {
  910                         if (softc->tur) {
  911                                 softc->tur = 0;
  912                                 csio = &start_ccb->csio;
  913                                 scsi_test_unit_ready(csio,
  914                                      /*retries*/ cd_retry_count,
  915                                      cddone,
  916                                      MSG_SIMPLE_Q_TAG,
  917                                      SSD_FULL_SIZE,
  918                                      cd_timeout);
  919                                 start_ccb->ccb_h.ccb_bp = NULL;
  920                                 start_ccb->ccb_h.ccb_state = CD_CCB_TUR;
  921                                 xpt_action(start_ccb);
  922                         } else
  923                                 xpt_release_ccb(start_ccb);
  924                 } else {
  925                         if (softc->tur) {
  926                                 softc->tur = 0;
  927                                 cam_periph_release_locked(periph);
  928                         }
  929                         bioq_remove(&softc->bio_queue, bp);
  930 
  931                         if ((bp->bio_cmd != BIO_READ) &&
  932                             (bp->bio_cmd != BIO_WRITE)) {
  933                                 biofinish(bp, NULL, EOPNOTSUPP);
  934                                 xpt_release_ccb(start_ccb);
  935                                 return;
  936                         }
  937 
  938                         scsi_read_write(&start_ccb->csio,
  939                                         /*retries*/ cd_retry_count,
  940                                         /* cbfcnp */ cddone,
  941                                         MSG_SIMPLE_Q_TAG,
  942                                         /* read */bp->bio_cmd == BIO_READ ?
  943                                         SCSI_RW_READ : SCSI_RW_WRITE,
  944                                         /* byte2 */ 0,
  945                                         /* minimum_cmd_size */ 10,
  946                                         /* lba */ bp->bio_offset /
  947                                           softc->params.blksize,
  948                                         bp->bio_bcount / softc->params.blksize,
  949                                         /* data_ptr */ bp->bio_data,
  950                                         /* dxfer_len */ bp->bio_bcount,
  951                                         /* sense_len */ cd_retry_count ?
  952                                           SSD_FULL_SIZE : SF_NO_PRINT,
  953                                         /* timeout */ cd_timeout);
  954                         /* Use READ CD command for audio tracks. */
  955                         if (softc->params.blksize == 2352) {
  956                                 start_ccb->csio.cdb_io.cdb_bytes[0] = READ_CD;
  957                                 start_ccb->csio.cdb_io.cdb_bytes[9] = 0xf8;
  958                                 start_ccb->csio.cdb_io.cdb_bytes[10] = 0;
  959                                 start_ccb->csio.cdb_io.cdb_bytes[11] = 0;
  960                                 start_ccb->csio.cdb_len = 12;
  961                         }
  962                         start_ccb->ccb_h.ccb_state = CD_CCB_BUFFER_IO;
  963 
  964                         LIST_INSERT_HEAD(&softc->pending_ccbs,
  965                                          &start_ccb->ccb_h, periph_links.le);
  966                         softc->outstanding_cmds++;
  967 
  968                         /* We expect a unit attention from this device */
  969                         if ((softc->flags & CD_FLAG_RETRY_UA) != 0) {
  970                                 start_ccb->ccb_h.ccb_state |= CD_CCB_RETRY_UA;
  971                                 softc->flags &= ~CD_FLAG_RETRY_UA;
  972                         }
  973 
  974                         start_ccb->ccb_h.ccb_bp = bp;
  975                         bp = bioq_first(&softc->bio_queue);
  976 
  977                         xpt_action(start_ccb);
  978                 }
  979                 if (bp != NULL || softc->tur) {
  980                         /* Have more work to do, so ensure we stay scheduled */
  981                         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
  982                 }
  983                 break;
  984         }
  985         case CD_STATE_PROBE:
  986         case CD_STATE_MEDIA_SIZE:
  987         {
  988                 struct scsi_read_capacity_data *rcap;
  989 
  990                 rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap),
  991                     M_SCSICD, M_NOWAIT | M_ZERO);
  992                 if (rcap == NULL) {
  993                         xpt_print(periph->path,
  994                             "%s: Couldn't malloc read_capacity data\n",
  995                             __func__);
  996                         xpt_release_ccb(start_ccb);
  997                         /*
  998                          * We can't probe because we can't allocate memory,
  999                          * so invalidate the peripheral.  The system probably
 1000                          * has larger problems at this stage.  If we've
 1001                          * already probed (and are re-probing capacity), we
 1002                          * don't need to invalidate.
 1003                          *
 1004                          * XXX KDM need to reset probe state and kick out
 1005                          * pending I/O.
 1006                          */
 1007                         if (softc->state == CD_STATE_PROBE)
 1008                                 cam_periph_invalidate(periph);
 1009                         break;
 1010                 }
 1011 
 1012                 /*
 1013                  * Set the default capacity and sector size to something that
 1014                  * GEOM can handle.  This will get reset when a read capacity
 1015                  * completes successfully.
 1016                  */
 1017                 softc->disk->d_sectorsize = 2048;
 1018                 softc->disk->d_mediasize = 0;
 1019 
 1020                 csio = &start_ccb->csio;
 1021                 scsi_read_capacity(csio,
 1022                                    /*retries*/ cd_retry_count,
 1023                                    cddone,
 1024                                    MSG_SIMPLE_Q_TAG,
 1025                                    rcap,
 1026                                    SSD_FULL_SIZE,
 1027                                    /*timeout*/20000);
 1028                 start_ccb->ccb_h.ccb_bp = NULL;
 1029                 if (softc->state == CD_STATE_PROBE)
 1030                         start_ccb->ccb_h.ccb_state = CD_CCB_PROBE;
 1031                 else
 1032                         start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_SIZE;
 1033                 xpt_action(start_ccb);
 1034                 break;
 1035         }
 1036         case CD_STATE_MEDIA_ALLOW:
 1037         case CD_STATE_MEDIA_PREVENT:
 1038         {
 1039                 /*
 1040                  * If the CD is already locked, we don't need to do this.
 1041                  * Move on to the capacity check.
 1042                  */
 1043                 if (softc->state == CD_STATE_MEDIA_PREVENT
 1044                  && (softc->flags & CD_FLAG_DISC_LOCKED) != 0) {
 1045                         softc->state = CD_STATE_MEDIA_SIZE;
 1046                         xpt_release_ccb(start_ccb);
 1047                         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 1048                         break;
 1049                 }
 1050 
 1051                 scsi_prevent(&start_ccb->csio,
 1052                              /*retries*/ cd_retry_count,
 1053                              /*cbfcnp*/ cddone,
 1054                              /*tag_action*/ MSG_SIMPLE_Q_TAG,
 1055                              /*action*/ (softc->state == CD_STATE_MEDIA_ALLOW) ?
 1056                                         PR_ALLOW : PR_PREVENT,
 1057                              /*sense_len*/ SSD_FULL_SIZE,
 1058                              /*timeout*/ 60000);
 1059 
 1060                 start_ccb->ccb_h.ccb_bp = NULL;
 1061                 if (softc->state == CD_STATE_MEDIA_ALLOW)
 1062                         start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_ALLOW;
 1063                 else
 1064                         start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_PREVENT;
 1065                 xpt_action(start_ccb);
 1066                 break;
 1067         }
 1068         case CD_STATE_MEDIA_TOC_HDR: {
 1069                 struct ioc_toc_header *toch;
 1070 
 1071                 bzero(&softc->toc, sizeof(softc->toc));
 1072 
 1073                 toch = &softc->toc.header;
 1074 
 1075                 scsi_read_toc(&start_ccb->csio,
 1076                               /*retries*/ cd_retry_count,
 1077                               /*cbfcnp*/ cddone,
 1078                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
 1079                               /*byte1_flags*/ 0,
 1080                               /*format*/ SRTOC_FORMAT_TOC,
 1081                               /*track*/ 0,
 1082                               /*data_ptr*/ (uint8_t *)toch,
 1083                               /*dxfer_len*/ sizeof(*toch),
 1084                               /*sense_len*/ SSD_FULL_SIZE,
 1085                               /*timeout*/ 50000);
 1086                 start_ccb->ccb_h.ccb_bp = NULL;
 1087                 start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_TOC_HDR;
 1088                 xpt_action(start_ccb);
 1089                 break;
 1090         }
 1091         case CD_STATE_MEDIA_TOC_FULL: {
 1092                 bzero(&softc->toc, sizeof(softc->toc));
 1093 
 1094                 scsi_read_toc(&start_ccb->csio,
 1095                               /*retries*/ cd_retry_count,
 1096                               /*cbfcnp*/ cddone,
 1097                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
 1098                               /*byte1_flags*/ 0,
 1099                               /*format*/ SRTOC_FORMAT_TOC,
 1100                               /*track*/ 0,
 1101                               /*data_ptr*/ (uint8_t *)&softc->toc,
 1102                               /*dxfer_len*/ softc->toc_read_len ?
 1103                                             softc->toc_read_len :
 1104                                             sizeof(softc->toc),
 1105                               /*sense_len*/ SSD_FULL_SIZE,
 1106                               /*timeout*/ 50000);
 1107                 start_ccb->ccb_h.ccb_bp = NULL;
 1108                 start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_TOC_FULL;
 1109                 xpt_action(start_ccb);
 1110                 break;
 1111         }
 1112         case CD_STATE_MEDIA_TOC_LEAD: {
 1113                 struct cd_toc_single *leadout;
 1114 
 1115                 leadout = &softc->leadout;
 1116                 bzero(leadout, sizeof(*leadout));
 1117 
 1118                 scsi_read_toc(&start_ccb->csio,
 1119                               /*retries*/ cd_retry_count,
 1120                               /*cbfcnp*/ cddone,
 1121                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
 1122                               /*byte1_flags*/ CD_MSF,
 1123                               /*format*/ SRTOC_FORMAT_TOC,
 1124                               /*track*/ LEADOUT,
 1125                               /*data_ptr*/ (uint8_t *)leadout,
 1126                               /*dxfer_len*/ sizeof(*leadout),
 1127                               /*sense_len*/ SSD_FULL_SIZE,
 1128                               /*timeout*/ 50000);
 1129                 start_ccb->ccb_h.ccb_bp = NULL;
 1130                 start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_TOC_LEAD;
 1131                 xpt_action(start_ccb);
 1132                 break;
 1133         }
 1134         }
 1135 }
 1136 
 1137 static void
 1138 cddone(struct cam_periph *periph, union ccb *done_ccb)
 1139 {
 1140         struct cd_softc *softc;
 1141         struct ccb_scsiio *csio;
 1142 
 1143         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cddone\n"));
 1144 
 1145         cam_periph_assert(periph, MA_OWNED);
 1146         softc = (struct cd_softc *)periph->softc;
 1147         csio = &done_ccb->csio;
 1148 
 1149         switch (csio->ccb_h.ccb_state & CD_CCB_TYPE_MASK) {
 1150         case CD_CCB_BUFFER_IO:
 1151         {
 1152                 struct bio      *bp;
 1153                 int             error;
 1154 
 1155                 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
 1156                 error = 0;
 1157 
 1158                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1159                         int sf;
 1160 
 1161                         if ((done_ccb->ccb_h.ccb_state & CD_CCB_RETRY_UA) != 0)
 1162                                 sf = SF_RETRY_UA;
 1163                         else
 1164                                 sf = 0;
 1165 
 1166                         error = cderror(done_ccb, CAM_RETRY_SELTO, sf);
 1167                         if (error == ERESTART) {
 1168                                 /*
 1169                                  * A retry was scheuled, so
 1170                                  * just return.
 1171                                  */
 1172                                 return;
 1173                         }
 1174                 }
 1175 
 1176                 if (error != 0) {
 1177                         xpt_print(periph->path,
 1178                             "cddone: got error %#x back\n", error);
 1179                         bioq_flush(&softc->bio_queue, NULL, EIO);
 1180                         bp->bio_resid = bp->bio_bcount;
 1181                         bp->bio_error = error;
 1182                         bp->bio_flags |= BIO_ERROR;
 1183                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1184                                 cam_release_devq(done_ccb->ccb_h.path,
 1185                                          /*relsim_flags*/0,
 1186                                          /*reduction*/0,
 1187                                          /*timeout*/0,
 1188                                          /*getcount_only*/0);
 1189 
 1190                 } else {
 1191                         bp->bio_resid = csio->resid;
 1192                         bp->bio_error = 0;
 1193                         if (bp->bio_resid != 0) {
 1194                                 /*
 1195                                  * Short transfer ???
 1196                                  * XXX: not sure this is correct for partial
 1197                                  * transfers at EOM
 1198                                  */
 1199                                 bp->bio_flags |= BIO_ERROR;
 1200                         }
 1201                 }
 1202 
 1203                 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
 1204                 softc->outstanding_cmds--;
 1205 
 1206                 biofinish(bp, NULL, 0);
 1207                 break;
 1208         }
 1209         case CD_CCB_PROBE:
 1210         {
 1211                 struct     scsi_read_capacity_data *rdcap;
 1212                 char       *announce_buf;
 1213                 struct     cd_params *cdp;
 1214                 int error;
 1215 
 1216                 cdp = &softc->params;
 1217                 announce_buf = softc->announce_temp;
 1218                 bzero(announce_buf, CD_ANNOUNCETMP_SZ);
 1219 
 1220                 rdcap = (struct scsi_read_capacity_data *)csio->data_ptr;
 1221 
 1222                 cdp->disksize = scsi_4btoul (rdcap->addr) + 1;
 1223                 cdp->blksize = scsi_4btoul (rdcap->length);
 1224 
 1225                 /*
 1226                  * Retry any UNIT ATTENTION type errors.  They
 1227                  * are expected at boot.
 1228                  */
 1229                 if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP ||
 1230                     (error = cderror(done_ccb, CAM_RETRY_SELTO,
 1231                                 SF_RETRY_UA | SF_NO_PRINT)) == 0) {
 1232                         snprintf(announce_buf, CD_ANNOUNCETMP_SZ,
 1233                             "%juMB (%ju %u byte sectors)",
 1234                             ((uintmax_t)cdp->disksize * cdp->blksize) /
 1235                              (1024 * 1024),
 1236                             (uintmax_t)cdp->disksize, cdp->blksize);
 1237                 } else {
 1238                         if (error == ERESTART) {
 1239                                 /*
 1240                                  * A retry was scheuled, so
 1241                                  * just return.
 1242                                  */
 1243                                 return;
 1244                         } else {
 1245                                 int asc, ascq;
 1246                                 int sense_key, error_code;
 1247                                 int have_sense;
 1248                                 cam_status status;
 1249                                 struct ccb_getdev cgd;
 1250 
 1251                                 /* Don't wedge this device's queue */
 1252                                 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1253                                         cam_release_devq(done_ccb->ccb_h.path,
 1254                                                  /*relsim_flags*/0,
 1255                                                  /*reduction*/0,
 1256                                                  /*timeout*/0,
 1257                                                  /*getcount_only*/0);
 1258 
 1259                                 status = done_ccb->ccb_h.status;
 1260 
 1261                                 bzero(&cgd, sizeof(cgd));
 1262                                 xpt_setup_ccb(&cgd.ccb_h,
 1263                                               done_ccb->ccb_h.path,
 1264                                               CAM_PRIORITY_NORMAL);
 1265                                 cgd.ccb_h.func_code = XPT_GDEV_TYPE;
 1266                                 xpt_action((union ccb *)&cgd);
 1267 
 1268                                 if (scsi_extract_sense_ccb(done_ccb,
 1269                                     &error_code, &sense_key, &asc, &ascq))
 1270                                         have_sense = TRUE;
 1271                                 else
 1272                                         have_sense = FALSE;
 1273 
 1274                                 /*
 1275                                  * Attach to anything that claims to be a
 1276                                  * CDROM or WORM device, as long as it
 1277                                  * doesn't return a "Logical unit not
 1278                                  * supported" (0x25) error.
 1279                                  */
 1280                                 if ((have_sense) && (asc != 0x25)
 1281                                  && (error_code == SSD_CURRENT_ERROR
 1282                                   || error_code == SSD_DESC_CURRENT_ERROR)) {
 1283                                         const char *sense_key_desc;
 1284                                         const char *asc_desc;
 1285 
 1286                                         scsi_sense_desc(sense_key, asc, ascq,
 1287                                                         &cgd.inq_data,
 1288                                                         &sense_key_desc,
 1289                                                         &asc_desc);
 1290                                         snprintf(announce_buf,
 1291                                             CD_ANNOUNCETMP_SZ,
 1292                                                 "Attempt to query device "
 1293                                                 "size failed: %s, %s",
 1294                                                 sense_key_desc,
 1295                                                 asc_desc);
 1296                                 } else if ((have_sense == 0)
 1297                                       && ((status & CAM_STATUS_MASK) ==
 1298                                            CAM_SCSI_STATUS_ERROR)
 1299                                       && (csio->scsi_status ==
 1300                                           SCSI_STATUS_BUSY)) {
 1301                                         snprintf(announce_buf,
 1302                                             CD_ANNOUNCETMP_SZ,
 1303                                             "Attempt to query device "
 1304                                             "size failed: SCSI Status: %s",
 1305                                             scsi_status_string(csio));
 1306                                 } else if (SID_TYPE(&cgd.inq_data) == T_CDROM) {
 1307                                         /*
 1308                                          * We only print out an error for
 1309                                          * CDROM type devices.  For WORM
 1310                                          * devices, we don't print out an
 1311                                          * error since a few WORM devices
 1312                                          * don't support CDROM commands.
 1313                                          * If we have sense information, go
 1314                                          * ahead and print it out.
 1315                                          * Otherwise, just say that we
 1316                                          * couldn't attach.
 1317                                          */
 1318 
 1319                                         /*
 1320                                          * Just print out the error, not
 1321                                          * the full probe message, when we
 1322                                          * don't attach.
 1323                                          */
 1324                                         if (have_sense)
 1325                                                 scsi_sense_print(
 1326                                                         &done_ccb->csio);
 1327                                         else {
 1328                                                 xpt_print(periph->path,
 1329                                                     "got CAM status %#x\n",
 1330                                                     done_ccb->ccb_h.status);
 1331                                         }
 1332                                         xpt_print(periph->path, "fatal error, "
 1333                                             "failed to attach to device\n");
 1334                                         /*
 1335                                          * Invalidate this peripheral.
 1336                                          */
 1337                                         cam_periph_invalidate(periph);
 1338 
 1339                                         announce_buf = NULL;
 1340                                 } else {
 1341                                         /*
 1342                                          * Invalidate this peripheral.
 1343                                          */
 1344                                         cam_periph_invalidate(periph);
 1345                                         announce_buf = NULL;
 1346                                 }
 1347                         }
 1348                 }
 1349                 free(rdcap, M_SCSICD);
 1350                 if (announce_buf != NULL) {
 1351                         struct sbuf sb;
 1352 
 1353                         sbuf_new(&sb, softc->announce_buf, CD_ANNOUNCE_SZ,
 1354                             SBUF_FIXEDLEN);
 1355                         xpt_announce_periph_sbuf(periph, &sb, announce_buf);
 1356                         xpt_announce_quirks_sbuf(periph, &sb, softc->quirks,
 1357                             CD_Q_BIT_STRING);
 1358                         sbuf_finish(&sb);
 1359                         sbuf_putbuf(&sb);
 1360 
 1361                         /*
 1362                          * Create our sysctl variables, now that we know
 1363                          * we have successfully attached.
 1364                          */
 1365                         taskqueue_enqueue(taskqueue_thread,&softc->sysctl_task);
 1366                 }
 1367                 softc->state = CD_STATE_NORMAL;
 1368                 /*
 1369                  * Since our peripheral may be invalidated by an error
 1370                  * above or an external event, we must release our CCB
 1371                  * before releasing the probe lock on the peripheral.
 1372                  * The peripheral will only go away once the last lock
 1373                  * is removed, and we need it around for the CCB release
 1374                  * operation.
 1375                  */
 1376                 xpt_release_ccb(done_ccb);
 1377 
 1378                 /*
 1379                  * We'll release this reference once GEOM calls us back via
 1380                  * cddiskgonecb(), telling us that our provider has been freed.
 1381                  */
 1382                 if (cam_periph_acquire(periph) == 0)
 1383                         disk_create(softc->disk, DISK_VERSION);
 1384 
 1385                 cam_periph_release_boot(periph);
 1386                 cam_periph_release_locked(periph);
 1387                 return;
 1388         }
 1389         case CD_CCB_TUR:
 1390         {
 1391                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1392                         if (cderror(done_ccb, CAM_RETRY_SELTO,
 1393                             SF_RETRY_UA | SF_NO_RECOVERY | SF_NO_PRINT) ==
 1394                             ERESTART)
 1395                                 return;
 1396                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1397                                 cam_release_devq(done_ccb->ccb_h.path,
 1398                                                  /*relsim_flags*/0,
 1399                                                  /*reduction*/0,
 1400                                                  /*timeout*/0,
 1401                                                  /*getcount_only*/0);
 1402                 }
 1403                 xpt_release_ccb(done_ccb);
 1404                 cam_periph_release_locked(periph);
 1405                 return;
 1406         }
 1407         case CD_CCB_MEDIA_ALLOW:
 1408         case CD_CCB_MEDIA_PREVENT:
 1409         {
 1410                 int error;
 1411                 int is_prevent;
 1412 
 1413                 error = 0;
 1414 
 1415                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1416                         error = cderror(done_ccb, CAM_RETRY_SELTO,
 1417                             SF_RETRY_UA | SF_NO_PRINT);
 1418                 }
 1419                 if (error == ERESTART)
 1420                         return;
 1421                 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1422                         cam_release_devq(done_ccb->ccb_h.path,
 1423                                          /*relsim_flags*/0,
 1424                                          /*reduction*/0,
 1425                                          /*timeout*/0,
 1426                                          /*getcount_only*/0);
 1427 
 1428                 /*
 1429                  * Note that just like the original cdcheckmedia(), we do
 1430                  * a prevent without failing the whole operation if the
 1431                  * prevent fails.  We try, but keep going if it doesn't
 1432                  * work.
 1433                  */
 1434 
 1435                 if ((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) ==
 1436                      CD_CCB_MEDIA_PREVENT)
 1437                         is_prevent = 1;
 1438                 else
 1439                         is_prevent = 0;
 1440 
 1441                 xpt_release_ccb(done_ccb);
 1442 
 1443                 if (is_prevent != 0) {
 1444                         if (error == 0)
 1445                                 softc->flags |= CD_FLAG_DISC_LOCKED;
 1446                         else
 1447                                 softc->flags &= ~CD_FLAG_DISC_LOCKED;
 1448                         softc->state = CD_STATE_MEDIA_SIZE;
 1449                         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 1450                 } else {
 1451                         if (error == 0)
 1452                                 softc->flags &= ~CD_FLAG_DISC_LOCKED;
 1453                         softc->state = CD_STATE_NORMAL;
 1454                         if (bioq_first(&softc->bio_queue) != NULL)
 1455                                 xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 1456                 }
 1457                 return;
 1458         }
 1459         case CD_CCB_MEDIA_SIZE:
 1460         {
 1461                 struct scsi_read_capacity_data *rdcap;
 1462                 int error;
 1463 
 1464                 error = 0;
 1465                 if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1466                         error = cderror(done_ccb, CAM_RETRY_SELTO,
 1467                             SF_RETRY_UA | SF_NO_PRINT);
 1468                 }
 1469                 if (error == ERESTART)
 1470                         return;
 1471                 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1472                         cam_release_devq(done_ccb->ccb_h.path,
 1473                                          /*relsim_flags*/0,
 1474                                          /*reduction*/0,
 1475                                          /*timeout*/0,
 1476                                          /*getcount_only*/0);
 1477                 rdcap = (struct scsi_read_capacity_data *)csio->data_ptr;
 1478 
 1479                 if (error == 0) {
 1480                         softc->params.disksize =scsi_4btoul(rdcap->addr) + 1;
 1481                         softc->params.blksize  = scsi_4btoul(rdcap->length);
 1482 
 1483                         /* Make sure we got at least some block size. */
 1484                         if (softc->params.blksize == 0)
 1485                                 error = EIO;
 1486                         /*
 1487                          * SCSI-3 mandates that the reported blocksize shall be
 1488                          * 2048.  Older drives sometimes report funny values,
 1489                          * trim it down to 2048, or other parts of the kernel
 1490                          * will get confused.
 1491                          *
 1492                          * XXX we leave drives alone that might report 512
 1493                          * bytes, as well as drives reporting more weird
 1494                          * sizes like perhaps 4K.
 1495                          */
 1496                         if (softc->params.blksize > 2048
 1497                          && softc->params.blksize <= 2352)
 1498                                 softc->params.blksize = 2048;
 1499                 }
 1500                 free(rdcap, M_SCSICD);
 1501 
 1502                 if (error == 0) {
 1503                         softc->disk->d_sectorsize = softc->params.blksize;
 1504                         softc->disk->d_mediasize =
 1505                             (off_t)softc->params.blksize *
 1506                             softc->params.disksize;
 1507                         softc->flags |= CD_FLAG_SAW_MEDIA | CD_FLAG_VALID_MEDIA;
 1508                         softc->state = CD_STATE_MEDIA_TOC_HDR;
 1509                 } else {
 1510                         softc->flags &= ~(CD_FLAG_VALID_MEDIA |
 1511                                           CD_FLAG_VALID_TOC);
 1512                         bioq_flush(&softc->bio_queue, NULL, EINVAL);
 1513                         softc->state = CD_STATE_MEDIA_ALLOW;
 1514                         cdmediaprobedone(periph);
 1515                 }
 1516                 xpt_release_ccb(done_ccb);
 1517                 xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 1518                 return;
 1519         }
 1520         case CD_CCB_MEDIA_TOC_HDR:
 1521         case CD_CCB_MEDIA_TOC_FULL:
 1522         case CD_CCB_MEDIA_TOC_LEAD:
 1523         {
 1524                 int error;
 1525                 struct ioc_toc_header *toch;
 1526                 int num_entries;
 1527                 int cdindex;
 1528 
 1529                 error = 0;
 1530 
 1531                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 1532                         error = cderror(done_ccb, CAM_RETRY_SELTO,
 1533                             SF_RETRY_UA | SF_NO_PRINT);
 1534                 }
 1535                 if (error == ERESTART)
 1536                         return;
 1537 
 1538                 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
 1539                         cam_release_devq(done_ccb->ccb_h.path,
 1540                                          /*relsim_flags*/0,
 1541                                          /*reduction*/0,
 1542                                          /*timeout*/0,
 1543                                          /*getcount_only*/0);
 1544 
 1545                 /*
 1546                  * We will get errors here for media that doesn't have a table
 1547                  * of contents.  According to the MMC-3 spec: "When a Read
 1548                  * TOC/PMA/ATIP command is presented for a DDCD/CD-R/RW media,
 1549                  * where the first TOC has not been recorded (no complete
 1550                  * session) and the Format codes 0000b, 0001b, or 0010b are
 1551                  * specified, this command shall be rejected with an INVALID
 1552                  * FIELD IN CDB.  Devices that are not capable of reading an
 1553                  * incomplete session on DDC/CD-R/RW media shall report
 1554                  * CANNOT READ MEDIUM - INCOMPATIBLE FORMAT."
 1555                  *
 1556                  * So this isn't fatal if we can't read the table of contents,
 1557                  * it just means that the user won't be able to issue the
 1558                  * play tracks ioctl, and likely lots of other stuff won't
 1559                  * work either.  They need to burn the CD before we can do
 1560                  * a whole lot with it.  So we don't print anything here if
 1561                  * we get an error back.
 1562                  *
 1563                  * We also bail out if the drive doesn't at least give us
 1564                  * the full TOC header.
 1565                  */
 1566                 if ((error != 0)
 1567                  || ((csio->dxfer_len - csio->resid) <
 1568                       sizeof(struct ioc_toc_header))) {
 1569                         softc->flags &= ~CD_FLAG_VALID_TOC;
 1570                         bzero(&softc->toc, sizeof(softc->toc));
 1571                         /*
 1572                          * Failing the TOC read is not an error.
 1573                          */
 1574                         softc->state = CD_STATE_NORMAL;
 1575                         xpt_release_ccb(done_ccb);
 1576 
 1577                         cdmediaprobedone(periph);
 1578 
 1579                         /*
 1580                          * Go ahead and schedule I/O execution if there is
 1581                          * anything in the queue.  It'll probably get
 1582                          * kicked out with an error.
 1583                          */
 1584                         if (bioq_first(&softc->bio_queue) != NULL)
 1585                                 xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 1586                         return;
 1587                 }
 1588 
 1589                 /*
 1590                  * Note that this is NOT the storage location used for the
 1591                  * leadout!
 1592                  */
 1593                 toch = &softc->toc.header;
 1594 
 1595                 if (softc->quirks & CD_Q_BCD_TRACKS) {
 1596                         toch->starting_track = bcd2bin(toch->starting_track);
 1597                         toch->ending_track = bcd2bin(toch->ending_track);
 1598                 }
 1599 
 1600                 /* Number of TOC entries, plus leadout */
 1601                 num_entries = toch->ending_track - toch->starting_track + 2;
 1602                 cdindex = toch->starting_track + num_entries - 1;
 1603 
 1604                 if ((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) ==
 1605                      CD_CCB_MEDIA_TOC_HDR) {
 1606                         if (num_entries <= 0 ||
 1607                             num_entries > nitems(softc->toc.entries)) {
 1608                                 softc->flags &= ~CD_FLAG_VALID_TOC;
 1609                                 bzero(&softc->toc, sizeof(softc->toc));
 1610                                 /*
 1611                                  * Failing the TOC read is not an error.
 1612                                  */
 1613                                 softc->state = CD_STATE_NORMAL;
 1614                                 xpt_release_ccb(done_ccb);
 1615 
 1616                                 cdmediaprobedone(periph);
 1617 
 1618                                 /*
 1619                                  * Go ahead and schedule I/O execution if
 1620                                  * there is anything in the queue.  It'll
 1621                                  * probably get kicked out with an error.
 1622                                  */
 1623                                 if (bioq_first(&softc->bio_queue) != NULL)
 1624                                         xpt_schedule(periph,
 1625                                             CAM_PRIORITY_NORMAL);
 1626                         } else {
 1627                                 softc->toc_read_len = num_entries *
 1628                                     sizeof(struct cd_toc_entry);
 1629                                 softc->toc_read_len += sizeof(*toch);
 1630 
 1631                                 softc->state = CD_STATE_MEDIA_TOC_FULL;
 1632                                 xpt_release_ccb(done_ccb);
 1633                                 xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 1634                         }
 1635 
 1636                         return;
 1637                 } else if ((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) ==
 1638                             CD_CCB_MEDIA_TOC_LEAD) {
 1639                         struct cd_toc_single *leadout;
 1640 
 1641                         leadout = (struct cd_toc_single *)csio->data_ptr;
 1642                         softc->toc.entries[cdindex - toch->starting_track] =
 1643                             leadout->entry;
 1644                 } else if (((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) ==
 1645                             CD_CCB_MEDIA_TOC_FULL)
 1646                         && (cdindex == toch->ending_track + 1)) {
 1647                         /*
 1648                          * XXX KDM is this necessary?  Probably only if the
 1649                          * drive doesn't return leadout information with the
 1650                          * table of contents.
 1651                          */
 1652                         softc->state = CD_STATE_MEDIA_TOC_LEAD;
 1653                         xpt_release_ccb(done_ccb);
 1654                         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 1655                         return;
 1656                 }
 1657 
 1658                 if (softc->quirks & CD_Q_BCD_TRACKS) {
 1659                         for (cdindex = 0; cdindex < num_entries - 1; cdindex++){
 1660                                 softc->toc.entries[cdindex].track =
 1661                                     bcd2bin(softc->toc.entries[cdindex].track);
 1662                         }
 1663                 }
 1664 
 1665                 softc->flags |= CD_FLAG_VALID_TOC;
 1666                 /* If the first track is audio, correct sector size. */
 1667                 if ((softc->toc.entries[0].control & 4) == 0) {
 1668                         softc->disk->d_sectorsize =softc->params.blksize = 2352;
 1669                         softc->disk->d_mediasize =
 1670                             (off_t)softc->params.blksize *
 1671                             softc->params.disksize;
 1672                 }
 1673                 softc->state = CD_STATE_NORMAL;
 1674 
 1675                 /*
 1676                  * We unconditionally (re)set the blocksize each time the
 1677                  * CD device is opened.  This is because the CD can change,
 1678                  * and therefore the blocksize might change.
 1679                  * XXX problems here if some slice or partition is still
 1680                  * open with the old size?
 1681                  */
 1682                 if ((softc->disk->d_devstat->flags & DEVSTAT_BS_UNAVAILABLE)!=0)
 1683                         softc->disk->d_devstat->flags &=
 1684                             ~DEVSTAT_BS_UNAVAILABLE;
 1685                 softc->disk->d_devstat->block_size = softc->params.blksize;
 1686 
 1687                 xpt_release_ccb(done_ccb);
 1688 
 1689                 cdmediaprobedone(periph);
 1690 
 1691                 if (bioq_first(&softc->bio_queue) != NULL)
 1692                         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 1693                 return;
 1694         }
 1695         default:
 1696                 break;
 1697         }
 1698         xpt_release_ccb(done_ccb);
 1699 }
 1700 
 1701 static union cd_pages *
 1702 cdgetpage(struct cd_mode_params *mode_params)
 1703 {
 1704         union cd_pages *page;
 1705 
 1706         if (mode_params->cdb_size == 10)
 1707                 page = (union cd_pages *)find_mode_page_10(
 1708                         (struct scsi_mode_header_10 *)mode_params->mode_buf);
 1709         else
 1710                 page = (union cd_pages *)find_mode_page_6(
 1711                         (struct scsi_mode_header_6 *)mode_params->mode_buf);
 1712 
 1713         return (page);
 1714 }
 1715 
 1716 static int
 1717 cdgetpagesize(int page_num)
 1718 {
 1719         u_int i;
 1720 
 1721         for (i = 0; i < nitems(cd_page_size_table); i++) {
 1722                 if (cd_page_size_table[i].page == page_num)
 1723                         return (cd_page_size_table[i].page_size);
 1724         }
 1725 
 1726         return (-1);
 1727 }
 1728 
 1729 static struct cd_toc_entry *
 1730 te_data_get_ptr(void *irtep, u_long cmd)
 1731 {
 1732         union {
 1733                 struct ioc_read_toc_entry irte;
 1734 #ifdef COMPAT_FREEBSD32
 1735                 struct ioc_read_toc_entry32 irte32;
 1736 #endif
 1737         } *irteup;
 1738 
 1739         irteup = irtep;
 1740         switch (IOCPARM_LEN(cmd)) {
 1741         case sizeof(irteup->irte):
 1742                 return (irteup->irte.data);
 1743 #ifdef COMPAT_FREEBSD32
 1744         case sizeof(irteup->irte32):
 1745                 return ((struct cd_toc_entry *)(uintptr_t)irteup->irte32.data);
 1746 #endif
 1747         default:
 1748                 panic("Unhandled ioctl command %ld", cmd);
 1749         }
 1750 }
 1751 
 1752 static int
 1753 cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
 1754 {
 1755 
 1756         struct  cam_periph *periph;
 1757         struct  cd_softc *softc;
 1758         int     error = 0;
 1759 
 1760         periph = (struct cam_periph *)dp->d_drv1;
 1761         cam_periph_lock(periph);
 1762 
 1763         softc = (struct cd_softc *)periph->softc;
 1764 
 1765         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
 1766             ("cdioctl(%#lx)\n", cmd));
 1767 
 1768         if ((error = cam_periph_hold(periph, PRIBIO | PCATCH)) != 0) {
 1769                 cam_periph_unlock(periph);
 1770                 cam_periph_release(periph);
 1771                 return (error);
 1772         }
 1773 
 1774         /*
 1775          * If we don't have media loaded, check for it.  If still don't
 1776          * have media loaded, we can only do a load or eject.
 1777          *
 1778          * We only care whether media is loaded if this is a cd-specific ioctl
 1779          * (thus the IOCGROUP check below).  Note that this will break if
 1780          * anyone adds any ioctls into the switch statement below that don't
 1781          * have their ioctl group set to 'c'.
 1782          */
 1783         if (((softc->flags & CD_FLAG_VALID_MEDIA) == 0)
 1784          && ((cmd != CDIOCCLOSE)
 1785           && (cmd != CDIOCEJECT))
 1786          && (IOCGROUP(cmd) == 'c')) {
 1787                 error = cdcheckmedia(periph, /*do_wait*/ 1);
 1788                 if (error != 0) {
 1789                         cam_periph_unhold(periph);
 1790                         cam_periph_unlock(periph);
 1791                         return (error);
 1792                 }
 1793         }
 1794         /*
 1795          * Drop the lock here so later mallocs can use WAITOK.  The periph
 1796          * is essentially locked still with the cam_periph_hold call above.
 1797          */
 1798         cam_periph_unlock(periph);
 1799 
 1800         switch (cmd) {
 1801         case CDIOCPLAYTRACKS:
 1802                 {
 1803                         struct ioc_play_track *args
 1804                             = (struct ioc_play_track *) addr;
 1805                         struct cd_mode_params params;
 1806                         union cd_pages *page;
 1807 
 1808                         params.alloc_len = sizeof(union cd_mode_data_6_10);
 1809                         params.mode_buf = malloc(params.alloc_len, M_SCSICD,
 1810                                                  M_WAITOK | M_ZERO);
 1811 
 1812                         cam_periph_lock(periph);
 1813                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 1814                                   ("trying to do CDIOCPLAYTRACKS\n"));
 1815 
 1816                         error = cdgetmode(periph, &params, AUDIO_PAGE);
 1817                         if (error) {
 1818                                 free(params.mode_buf, M_SCSICD);
 1819                                 cam_periph_unlock(periph);
 1820                                 break;
 1821                         }
 1822                         page = cdgetpage(&params);
 1823 
 1824                         page->audio.flags &= ~CD_PA_SOTC;
 1825                         page->audio.flags |= CD_PA_IMMED;
 1826                         error = cdsetmode(periph, &params);
 1827                         free(params.mode_buf, M_SCSICD);
 1828                         if (error) {
 1829                                 cam_periph_unlock(periph);
 1830                                 break;
 1831                         }
 1832 
 1833                         /*
 1834                          * This was originally implemented with the PLAY
 1835                          * AUDIO TRACK INDEX command, but that command was
 1836                          * deprecated after SCSI-2.  Most (all?) SCSI CDROM
 1837                          * drives support it but ATAPI and ATAPI-derivative
 1838                          * drives don't seem to support it.  So we keep a
 1839                          * cache of the table of contents and translate
 1840                          * track numbers to MSF format.
 1841                          */
 1842                         if (softc->flags & CD_FLAG_VALID_TOC) {
 1843                                 union msf_lba *sentry, *eentry;
 1844                                 struct ioc_toc_header *th;
 1845                                 int st, et;
 1846 
 1847                                 th = &softc->toc.header;
 1848                                 if (args->end_track < th->ending_track + 1)
 1849                                         args->end_track++;
 1850                                 if (args->end_track > th->ending_track + 1)
 1851                                         args->end_track = th->ending_track + 1;
 1852                                 st = args->start_track - th->starting_track;
 1853                                 et = args->end_track - th->starting_track;
 1854                                 if (st < 0 || et < 0 ||
 1855                                     st > th->ending_track - th->starting_track ||
 1856                                     et > th->ending_track - th->starting_track) {
 1857                                         error = EINVAL;
 1858                                         cam_periph_unlock(periph);
 1859                                         break;
 1860                                 }
 1861                                 sentry = &softc->toc.entries[st].addr;
 1862                                 eentry = &softc->toc.entries[et].addr;
 1863                                 error = cdplaymsf(periph,
 1864                                                   sentry->msf.minute,
 1865                                                   sentry->msf.second,
 1866                                                   sentry->msf.frame,
 1867                                                   eentry->msf.minute,
 1868                                                   eentry->msf.second,
 1869                                                   eentry->msf.frame);
 1870                         } else {
 1871                                 /*
 1872                                  * If we don't have a valid TOC, try the
 1873                                  * play track index command.  It is part of
 1874                                  * the SCSI-2 spec, but was removed in the
 1875                                  * MMC specs.  ATAPI and ATAPI-derived
 1876                                  * drives don't support it.
 1877                                  */
 1878                                 if (softc->quirks & CD_Q_BCD_TRACKS) {
 1879                                         args->start_track =
 1880                                                 bin2bcd(args->start_track);
 1881                                         args->end_track =
 1882                                                 bin2bcd(args->end_track);
 1883                                 }
 1884                                 error = cdplaytracks(periph,
 1885                                                      args->start_track,
 1886                                                      args->start_index,
 1887                                                      args->end_track,
 1888                                                      args->end_index);
 1889                         }
 1890                         cam_periph_unlock(periph);
 1891                 }
 1892                 break;
 1893         case CDIOCPLAYMSF:
 1894                 {
 1895                         struct ioc_play_msf *args
 1896                                 = (struct ioc_play_msf *) addr;
 1897                         struct cd_mode_params params;
 1898                         union cd_pages *page;
 1899 
 1900                         params.alloc_len = sizeof(union cd_mode_data_6_10);
 1901                         params.mode_buf = malloc(params.alloc_len, M_SCSICD,
 1902                                                  M_WAITOK | M_ZERO);
 1903 
 1904                         cam_periph_lock(periph);
 1905                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 1906                                   ("trying to do CDIOCPLAYMSF\n"));
 1907 
 1908                         error = cdgetmode(periph, &params, AUDIO_PAGE);
 1909                         if (error) {
 1910                                 free(params.mode_buf, M_SCSICD);
 1911                                 cam_periph_unlock(periph);
 1912                                 break;
 1913                         }
 1914                         page = cdgetpage(&params);
 1915 
 1916                         page->audio.flags &= ~CD_PA_SOTC;
 1917                         page->audio.flags |= CD_PA_IMMED;
 1918                         error = cdsetmode(periph, &params);
 1919                         free(params.mode_buf, M_SCSICD);
 1920                         if (error) {
 1921                                 cam_periph_unlock(periph);
 1922                                 break;
 1923                         }
 1924                         error = cdplaymsf(periph,
 1925                                           args->start_m,
 1926                                           args->start_s,
 1927                                           args->start_f,
 1928                                           args->end_m,
 1929                                           args->end_s,
 1930                                           args->end_f);
 1931                         cam_periph_unlock(periph);
 1932                 }
 1933                 break;
 1934         case CDIOCPLAYBLOCKS:
 1935                 {
 1936                         struct ioc_play_blocks *args
 1937                                 = (struct ioc_play_blocks *) addr;
 1938                         struct cd_mode_params params;
 1939                         union cd_pages *page;
 1940 
 1941                         params.alloc_len = sizeof(union cd_mode_data_6_10);
 1942                         params.mode_buf = malloc(params.alloc_len, M_SCSICD,
 1943                                                  M_WAITOK | M_ZERO);
 1944 
 1945                         cam_periph_lock(periph);
 1946                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 1947                                   ("trying to do CDIOCPLAYBLOCKS\n"));
 1948 
 1949                         error = cdgetmode(periph, &params, AUDIO_PAGE);
 1950                         if (error) {
 1951                                 free(params.mode_buf, M_SCSICD);
 1952                                 cam_periph_unlock(periph);
 1953                                 break;
 1954                         }
 1955                         page = cdgetpage(&params);
 1956 
 1957                         page->audio.flags &= ~CD_PA_SOTC;
 1958                         page->audio.flags |= CD_PA_IMMED;
 1959                         error = cdsetmode(periph, &params);
 1960                         free(params.mode_buf, M_SCSICD);
 1961                         if (error) {
 1962                                 cam_periph_unlock(periph);
 1963                                 break;
 1964                         }
 1965                         error = cdplay(periph, args->blk, args->len);
 1966                         cam_periph_unlock(periph);
 1967                 }
 1968                 break;
 1969         case CDIOCREADSUBCHANNEL:
 1970                 {
 1971                         struct ioc_read_subchannel *args
 1972                                 = (struct ioc_read_subchannel *) addr;
 1973                         struct cd_sub_channel_info *data;
 1974                         u_int32_t len = args->data_len;
 1975 
 1976                         data = malloc(sizeof(struct cd_sub_channel_info),
 1977                                       M_SCSICD, M_WAITOK | M_ZERO);
 1978 
 1979                         cam_periph_lock(periph);
 1980                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 1981                                   ("trying to do CDIOCREADSUBCHANNEL\n"));
 1982 
 1983                         if ((len > sizeof(struct cd_sub_channel_info)) ||
 1984                             (len < sizeof(struct cd_sub_channel_header))) {
 1985                                 printf(
 1986                                         "scsi_cd: cdioctl: "
 1987                                         "cdioreadsubchannel: error, len=%d\n",
 1988                                         len);
 1989                                 error = EINVAL;
 1990                                 free(data, M_SCSICD);
 1991                                 cam_periph_unlock(periph);
 1992                                 break;
 1993                         }
 1994 
 1995                         if (softc->quirks & CD_Q_BCD_TRACKS)
 1996                                 args->track = bin2bcd(args->track);
 1997 
 1998                         error = cdreadsubchannel(periph, args->address_format,
 1999                                 args->data_format, args->track, data, len);
 2000 
 2001                         if (error) {
 2002                                 free(data, M_SCSICD);
 2003                                 cam_periph_unlock(periph);
 2004                                 break;
 2005                         }
 2006                         if (softc->quirks & CD_Q_BCD_TRACKS)
 2007                                 data->what.track_info.track_number =
 2008                                     bcd2bin(data->what.track_info.track_number);
 2009                         len = min(len, ((data->header.data_len[0] << 8) +
 2010                                 data->header.data_len[1] +
 2011                                 sizeof(struct cd_sub_channel_header)));
 2012                         cam_periph_unlock(periph);
 2013                         error = copyout(data, args->data, len);
 2014                         free(data, M_SCSICD);
 2015                 }
 2016                 break;
 2017 
 2018         case CDIOREADTOCHEADER:
 2019                 {
 2020                         struct ioc_toc_header *th;
 2021 
 2022                         th = malloc(sizeof(struct ioc_toc_header), M_SCSICD,
 2023                                     M_WAITOK | M_ZERO);
 2024 
 2025                         cam_periph_lock(periph);
 2026                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 2027                                   ("trying to do CDIOREADTOCHEADER\n"));
 2028 
 2029                         error = cdreadtoc(periph, 0, 0, (u_int8_t *)th,
 2030                                           sizeof (*th), /*sense_flags*/SF_NO_PRINT);
 2031                         if (error) {
 2032                                 free(th, M_SCSICD);
 2033                                 cam_periph_unlock(periph);
 2034                                 break;
 2035                         }
 2036                         if (softc->quirks & CD_Q_BCD_TRACKS) {
 2037                                 /* we are going to have to convert the BCD
 2038                                  * encoding on the cd to what is expected
 2039                                  */
 2040                                 th->starting_track =
 2041                                         bcd2bin(th->starting_track);
 2042                                 th->ending_track = bcd2bin(th->ending_track);
 2043                         }
 2044                         th->len = ntohs(th->len);
 2045                         bcopy(th, addr, sizeof(*th));
 2046                         free(th, M_SCSICD);
 2047                         cam_periph_unlock(periph);
 2048                 }
 2049                 break;
 2050         case CDIOREADTOCENTRYS:
 2051 #ifdef COMPAT_FREEBSD32
 2052         case CDIOREADTOCENTRYS_32:
 2053 #endif
 2054                 {
 2055                         struct cd_tocdata *data;
 2056                         struct cd_toc_single *lead;
 2057                         struct ioc_read_toc_entry *te =
 2058                                 (struct ioc_read_toc_entry *) addr;
 2059                         struct ioc_toc_header *th;
 2060                         u_int32_t len, readlen, idx, num;
 2061                         u_int32_t starting_track = te->starting_track;
 2062 
 2063                         data = malloc(sizeof(*data), M_SCSICD, M_WAITOK | M_ZERO);
 2064                         lead = malloc(sizeof(*lead), M_SCSICD, M_WAITOK | M_ZERO);
 2065 
 2066                         cam_periph_lock(periph);
 2067                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 2068                                   ("trying to do CDIOREADTOCENTRYS\n"));
 2069 
 2070                         if (te->data_len < sizeof(struct cd_toc_entry)
 2071                          || (te->data_len % sizeof(struct cd_toc_entry)) != 0
 2072                          || (te->address_format != CD_MSF_FORMAT
 2073                           && te->address_format != CD_LBA_FORMAT)) {
 2074                                 error = EINVAL;
 2075                                 printf("scsi_cd: error in readtocentries, "
 2076                                        "returning EINVAL\n");
 2077                                 free(data, M_SCSICD);
 2078                                 free(lead, M_SCSICD);
 2079                                 cam_periph_unlock(periph);
 2080                                 break;
 2081                         }
 2082 
 2083                         th = &data->header;
 2084                         error = cdreadtoc(periph, 0, 0, (u_int8_t *)th,
 2085                                           sizeof (*th), /*sense_flags*/0);
 2086                         if (error) {
 2087                                 free(data, M_SCSICD);
 2088                                 free(lead, M_SCSICD);
 2089                                 cam_periph_unlock(periph);
 2090                                 break;
 2091                         }
 2092 
 2093                         if (softc->quirks & CD_Q_BCD_TRACKS) {
 2094                                 /* we are going to have to convert the BCD
 2095                                  * encoding on the cd to what is expected
 2096                                  */
 2097                                 th->starting_track =
 2098                                     bcd2bin(th->starting_track);
 2099                                 th->ending_track = bcd2bin(th->ending_track);
 2100                         }
 2101 
 2102                         if (starting_track == 0)
 2103                                 starting_track = th->starting_track;
 2104                         else if (starting_track == LEADOUT)
 2105                                 starting_track = th->ending_track + 1;
 2106                         else if (starting_track < th->starting_track ||
 2107                                  starting_track > th->ending_track + 1) {
 2108                                 printf("scsi_cd: error in readtocentries, "
 2109                                        "returning EINVAL\n");
 2110                                 free(data, M_SCSICD);
 2111                                 free(lead, M_SCSICD);
 2112                                 cam_periph_unlock(periph);
 2113                                 error = EINVAL;
 2114                                 break;
 2115                         }
 2116 
 2117                         /* calculate reading length without leadout entry */
 2118                         readlen = (th->ending_track - starting_track + 1) *
 2119                                   sizeof(struct cd_toc_entry);
 2120 
 2121                         /* and with leadout entry */
 2122                         len = readlen + sizeof(struct cd_toc_entry);
 2123                         if (te->data_len < len) {
 2124                                 len = te->data_len;
 2125                                 if (readlen > len)
 2126                                         readlen = len;
 2127                         }
 2128                         if (len > sizeof(data->entries)) {
 2129                                 printf("scsi_cd: error in readtocentries, "
 2130                                        "returning EINVAL\n");
 2131                                 error = EINVAL;
 2132                                 free(data, M_SCSICD);
 2133                                 free(lead, M_SCSICD);
 2134                                 cam_periph_unlock(periph);
 2135                                 break;
 2136                         }
 2137                         num = len / sizeof(struct cd_toc_entry);
 2138 
 2139                         if (readlen > 0) {
 2140                                 error = cdreadtoc(periph, te->address_format,
 2141                                                   starting_track,
 2142                                                   (u_int8_t *)data,
 2143                                                   readlen + sizeof (*th),
 2144                                                   /*sense_flags*/0);
 2145                                 if (error) {
 2146                                         free(data, M_SCSICD);
 2147                                         free(lead, M_SCSICD);
 2148                                         cam_periph_unlock(periph);
 2149                                         break;
 2150                                 }
 2151                         }
 2152 
 2153                         /* make leadout entry if needed */
 2154                         idx = starting_track + num - 1;
 2155                         if (softc->quirks & CD_Q_BCD_TRACKS)
 2156                                 th->ending_track = bcd2bin(th->ending_track);
 2157                         if (idx == th->ending_track + 1) {
 2158                                 error = cdreadtoc(periph, te->address_format,
 2159                                                   LEADOUT, (u_int8_t *)lead,
 2160                                                   sizeof(*lead),
 2161                                                   /*sense_flags*/0);
 2162                                 if (error) {
 2163                                         free(data, M_SCSICD);
 2164                                         free(lead, M_SCSICD);
 2165                                         cam_periph_unlock(periph);
 2166                                         break;
 2167                                 }
 2168                                 data->entries[idx - starting_track] =
 2169                                         lead->entry;
 2170                         }
 2171                         if (softc->quirks & CD_Q_BCD_TRACKS) {
 2172                                 for (idx = 0; idx < num - 1; idx++) {
 2173                                         data->entries[idx].track =
 2174                                             bcd2bin(data->entries[idx].track);
 2175                                 }
 2176                         }
 2177 
 2178                         cam_periph_unlock(periph);
 2179                         error = copyout(data->entries, te_data_get_ptr(te, cmd),
 2180                             len);
 2181                         free(data, M_SCSICD);
 2182                         free(lead, M_SCSICD);
 2183                 }
 2184                 break;
 2185         case CDIOREADTOCENTRY:
 2186                 {
 2187                         struct cd_toc_single *data;
 2188                         struct ioc_read_toc_single_entry *te =
 2189                                 (struct ioc_read_toc_single_entry *) addr;
 2190                         struct ioc_toc_header *th;
 2191                         u_int32_t track;
 2192 
 2193                         data = malloc(sizeof(*data), M_SCSICD, M_WAITOK | M_ZERO);
 2194 
 2195                         cam_periph_lock(periph);
 2196                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 2197                                   ("trying to do CDIOREADTOCENTRY\n"));
 2198 
 2199                         if (te->address_format != CD_MSF_FORMAT
 2200                             && te->address_format != CD_LBA_FORMAT) {
 2201                                 printf("error in readtocentry, "
 2202                                        " returning EINVAL\n");
 2203                                 free(data, M_SCSICD);
 2204                                 error = EINVAL;
 2205                                 cam_periph_unlock(periph);
 2206                                 break;
 2207                         }
 2208 
 2209                         th = &data->header;
 2210                         error = cdreadtoc(periph, 0, 0, (u_int8_t *)th,
 2211                                           sizeof (*th), /*sense_flags*/0);
 2212                         if (error) {
 2213                                 free(data, M_SCSICD);
 2214                                 cam_periph_unlock(periph);
 2215                                 break;
 2216                         }
 2217 
 2218                         if (softc->quirks & CD_Q_BCD_TRACKS) {
 2219                                 /* we are going to have to convert the BCD
 2220                                  * encoding on the cd to what is expected
 2221                                  */
 2222                                 th->starting_track =
 2223                                     bcd2bin(th->starting_track);
 2224                                 th->ending_track = bcd2bin(th->ending_track);
 2225                         }
 2226                         track = te->track;
 2227                         if (track == 0)
 2228                                 track = th->starting_track;
 2229                         else if (track == LEADOUT)
 2230                                 /* OK */;
 2231                         else if (track < th->starting_track ||
 2232                                  track > th->ending_track + 1) {
 2233                                 printf("error in readtocentry, "
 2234                                        " returning EINVAL\n");
 2235                                 free(data, M_SCSICD);
 2236                                 error = EINVAL;
 2237                                 cam_periph_unlock(periph);
 2238                                 break;
 2239                         }
 2240 
 2241                         error = cdreadtoc(periph, te->address_format, track,
 2242                                           (u_int8_t *)data, sizeof(*data),
 2243                                           /*sense_flags*/0);
 2244                         if (error) {
 2245                                 free(data, M_SCSICD);
 2246                                 cam_periph_unlock(periph);
 2247                                 break;
 2248                         }
 2249 
 2250                         if (softc->quirks & CD_Q_BCD_TRACKS)
 2251                                 data->entry.track = bcd2bin(data->entry.track);
 2252                         bcopy(&data->entry, &te->entry,
 2253                               sizeof(struct cd_toc_entry));
 2254                         free(data, M_SCSICD);
 2255                         cam_periph_unlock(periph);
 2256                 }
 2257                 break;
 2258         case CDIOCSETPATCH:
 2259                 {
 2260                         struct ioc_patch *arg = (struct ioc_patch *)addr;
 2261                         struct cd_mode_params params;
 2262                         union cd_pages *page;
 2263 
 2264                         params.alloc_len = sizeof(union cd_mode_data_6_10);
 2265                         params.mode_buf = malloc(params.alloc_len, M_SCSICD,
 2266                                                  M_WAITOK | M_ZERO);
 2267 
 2268                         cam_periph_lock(periph);
 2269                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 2270                                   ("trying to do CDIOCSETPATCH\n"));
 2271 
 2272                         error = cdgetmode(periph, &params, AUDIO_PAGE);
 2273                         if (error) {
 2274                                 free(params.mode_buf, M_SCSICD);
 2275                                 cam_periph_unlock(periph);
 2276                                 break;
 2277                         }
 2278                         page = cdgetpage(&params);
 2279 
 2280                         page->audio.port[LEFT_PORT].channels =
 2281                                 arg->patch[0];
 2282                         page->audio.port[RIGHT_PORT].channels =
 2283                                 arg->patch[1];
 2284                         page->audio.port[2].channels = arg->patch[2];
 2285                         page->audio.port[3].channels = arg->patch[3];
 2286                         error = cdsetmode(periph, &params);
 2287                         free(params.mode_buf, M_SCSICD);
 2288                         cam_periph_unlock(periph);
 2289                 }
 2290                 break;
 2291         case CDIOCGETVOL:
 2292                 {
 2293                         struct ioc_vol *arg = (struct ioc_vol *) addr;
 2294                         struct cd_mode_params params;
 2295                         union cd_pages *page;
 2296 
 2297                         params.alloc_len = sizeof(union cd_mode_data_6_10);
 2298                         params.mode_buf = malloc(params.alloc_len, M_SCSICD,
 2299                                                  M_WAITOK | M_ZERO);
 2300 
 2301                         cam_periph_lock(periph);
 2302                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 2303                                   ("trying to do CDIOCGETVOL\n"));
 2304 
 2305                         error = cdgetmode(periph, &params, AUDIO_PAGE);
 2306                         if (error) {
 2307                                 free(params.mode_buf, M_SCSICD);
 2308                                 cam_periph_unlock(periph);
 2309                                 break;
 2310                         }
 2311                         page = cdgetpage(&params);
 2312 
 2313                         arg->vol[LEFT_PORT] =
 2314                                 page->audio.port[LEFT_PORT].volume;
 2315                         arg->vol[RIGHT_PORT] =
 2316                                 page->audio.port[RIGHT_PORT].volume;
 2317                         arg->vol[2] = page->audio.port[2].volume;
 2318                         arg->vol[3] = page->audio.port[3].volume;
 2319                         free(params.mode_buf, M_SCSICD);
 2320                         cam_periph_unlock(periph);
 2321                 }
 2322                 break;
 2323         case CDIOCSETVOL:
 2324                 {
 2325                         struct ioc_vol *arg = (struct ioc_vol *) addr;
 2326                         struct cd_mode_params params;
 2327                         union cd_pages *page;
 2328 
 2329                         params.alloc_len = sizeof(union cd_mode_data_6_10);
 2330                         params.mode_buf = malloc(params.alloc_len, M_SCSICD,
 2331                                                  M_WAITOK | M_ZERO);
 2332 
 2333                         cam_periph_lock(periph);
 2334                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 2335                                   ("trying to do CDIOCSETVOL\n"));
 2336 
 2337                         error = cdgetmode(periph, &params, AUDIO_PAGE);
 2338                         if (error) {
 2339                                 free(params.mode_buf, M_SCSICD);
 2340                                 cam_periph_unlock(periph);
 2341                                 break;
 2342                         }
 2343                         page = cdgetpage(&params);
 2344 
 2345                         page->audio.port[LEFT_PORT].channels = CHANNEL_0;
 2346                         page->audio.port[LEFT_PORT].volume =
 2347                                 arg->vol[LEFT_PORT];
 2348                         page->audio.port[RIGHT_PORT].channels = CHANNEL_1;
 2349                         page->audio.port[RIGHT_PORT].volume =
 2350                                 arg->vol[RIGHT_PORT];
 2351                         page->audio.port[2].volume = arg->vol[2];
 2352                         page->audio.port[3].volume = arg->vol[3];
 2353                         error = cdsetmode(periph, &params);
 2354                         cam_periph_unlock(periph);
 2355                         free(params.mode_buf, M_SCSICD);
 2356                 }
 2357                 break;
 2358         case CDIOCSETMONO:
 2359                 {
 2360                         struct cd_mode_params params;
 2361                         union cd_pages *page;
 2362 
 2363                         params.alloc_len = sizeof(union cd_mode_data_6_10);
 2364                         params.mode_buf = malloc(params.alloc_len, M_SCSICD,
 2365                                                  M_WAITOK | M_ZERO);
 2366 
 2367                         cam_periph_lock(periph);
 2368                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 2369                                   ("trying to do CDIOCSETMONO\n"));
 2370 
 2371                         error = cdgetmode(periph, &params, AUDIO_PAGE);
 2372                         if (error) {
 2373                                 free(params.mode_buf, M_SCSICD);
 2374                                 cam_periph_unlock(periph);
 2375                                 break;
 2376                         }
 2377                         page = cdgetpage(&params);
 2378 
 2379                         page->audio.port[LEFT_PORT].channels =
 2380                                 LEFT_CHANNEL | RIGHT_CHANNEL;
 2381                         page->audio.port[RIGHT_PORT].channels =
 2382                                 LEFT_CHANNEL | RIGHT_CHANNEL;
 2383                         page->audio.port[2].channels = 0;
 2384                         page->audio.port[3].channels = 0;
 2385                         error = cdsetmode(periph, &params);
 2386                         cam_periph_unlock(periph);
 2387                         free(params.mode_buf, M_SCSICD);
 2388                 }
 2389                 break;
 2390         case CDIOCSETSTEREO:
 2391                 {
 2392                         struct cd_mode_params params;
 2393                         union cd_pages *page;
 2394 
 2395                         params.alloc_len = sizeof(union cd_mode_data_6_10);
 2396                         params.mode_buf = malloc(params.alloc_len, M_SCSICD,
 2397                                                  M_WAITOK | M_ZERO);
 2398 
 2399                         cam_periph_lock(periph);
 2400                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 2401                                   ("trying to do CDIOCSETSTEREO\n"));
 2402 
 2403                         error = cdgetmode(periph, &params, AUDIO_PAGE);
 2404                         if (error) {
 2405                                 free(params.mode_buf, M_SCSICD);
 2406                                 cam_periph_unlock(periph);
 2407                                 break;
 2408                         }
 2409                         page = cdgetpage(&params);
 2410 
 2411                         page->audio.port[LEFT_PORT].channels =
 2412                                 LEFT_CHANNEL;
 2413                         page->audio.port[RIGHT_PORT].channels =
 2414                                 RIGHT_CHANNEL;
 2415                         page->audio.port[2].channels = 0;
 2416                         page->audio.port[3].channels = 0;
 2417                         error = cdsetmode(periph, &params);
 2418                         free(params.mode_buf, M_SCSICD);
 2419                         cam_periph_unlock(periph);
 2420                 }
 2421                 break;
 2422         case CDIOCSETMUTE:
 2423                 {
 2424                         struct cd_mode_params params;
 2425                         union cd_pages *page;
 2426 
 2427                         params.alloc_len = sizeof(union cd_mode_data_6_10);
 2428                         params.mode_buf = malloc(params.alloc_len, M_SCSICD,
 2429                                                  M_WAITOK | M_ZERO);
 2430 
 2431                         cam_periph_lock(periph);
 2432                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 2433                                   ("trying to do CDIOCSETMUTE\n"));
 2434 
 2435                         error = cdgetmode(periph, &params, AUDIO_PAGE);
 2436                         if (error) {
 2437                                 free(params.mode_buf, M_SCSICD);
 2438                                 cam_periph_unlock(periph);
 2439                                 break;
 2440                         }
 2441                         page = cdgetpage(&params);
 2442 
 2443                         page->audio.port[LEFT_PORT].channels = 0;
 2444                         page->audio.port[RIGHT_PORT].channels = 0;
 2445                         page->audio.port[2].channels = 0;
 2446                         page->audio.port[3].channels = 0;
 2447                         error = cdsetmode(periph, &params);
 2448                         free(params.mode_buf, M_SCSICD);
 2449                         cam_periph_unlock(periph);
 2450                 }
 2451                 break;
 2452         case CDIOCSETLEFT:
 2453                 {
 2454                         struct cd_mode_params params;
 2455                         union cd_pages *page;
 2456 
 2457                         params.alloc_len = sizeof(union cd_mode_data_6_10);
 2458                         params.mode_buf = malloc(params.alloc_len, M_SCSICD,
 2459                                                  M_WAITOK | M_ZERO);
 2460 
 2461                         cam_periph_lock(periph);
 2462                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 2463                                   ("trying to do CDIOCSETLEFT\n"));
 2464 
 2465                         error = cdgetmode(periph, &params, AUDIO_PAGE);
 2466                         if (error) {
 2467                                 free(params.mode_buf, M_SCSICD);
 2468                                 cam_periph_unlock(periph);
 2469                                 break;
 2470                         }
 2471                         page = cdgetpage(&params);
 2472 
 2473                         page->audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
 2474                         page->audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
 2475                         page->audio.port[2].channels = 0;
 2476                         page->audio.port[3].channels = 0;
 2477                         error = cdsetmode(periph, &params);
 2478                         free(params.mode_buf, M_SCSICD);
 2479                         cam_periph_unlock(periph);
 2480                 }
 2481                 break;
 2482         case CDIOCSETRIGHT:
 2483                 {
 2484                         struct cd_mode_params params;
 2485                         union cd_pages *page;
 2486 
 2487                         params.alloc_len = sizeof(union cd_mode_data_6_10);
 2488                         params.mode_buf = malloc(params.alloc_len, M_SCSICD,
 2489                                                  M_WAITOK | M_ZERO);
 2490 
 2491                         cam_periph_lock(periph);
 2492                         CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
 2493                                   ("trying to do CDIOCSETRIGHT\n"));
 2494 
 2495                         error = cdgetmode(periph, &params, AUDIO_PAGE);
 2496                         if (error) {
 2497                                 free(params.mode_buf, M_SCSICD);
 2498                                 cam_periph_unlock(periph);
 2499                                 break;
 2500                         }
 2501                         page = cdgetpage(&params);
 2502 
 2503                         page->audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
 2504                         page->audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
 2505                         page->audio.port[2].channels = 0;
 2506                         page->audio.port[3].channels = 0;
 2507                         error = cdsetmode(periph, &params);
 2508                         free(params.mode_buf, M_SCSICD);
 2509                         cam_periph_unlock(periph);
 2510                 }
 2511                 break;
 2512         case CDIOCRESUME:
 2513                 cam_periph_lock(periph);
 2514                 error = cdpause(periph, 1);
 2515                 cam_periph_unlock(periph);
 2516                 break;
 2517         case CDIOCPAUSE:
 2518                 cam_periph_lock(periph);
 2519                 error = cdpause(periph, 0);
 2520                 cam_periph_unlock(periph);
 2521                 break;
 2522         case CDIOCSTART:
 2523                 cam_periph_lock(periph);
 2524                 error = cdstartunit(periph, 0);
 2525                 cam_periph_unlock(periph);
 2526                 break;
 2527         case CDIOCCLOSE:
 2528                 cam_periph_lock(periph);
 2529                 error = cdstartunit(periph, 1);
 2530                 cam_periph_unlock(periph);
 2531                 break;
 2532         case CDIOCSTOP:
 2533                 cam_periph_lock(periph);
 2534                 error = cdstopunit(periph, 0);
 2535                 cam_periph_unlock(periph);
 2536                 break;
 2537         case CDIOCEJECT:
 2538                 cam_periph_lock(periph);
 2539                 error = cdstopunit(periph, 1);
 2540                 cam_periph_unlock(periph);
 2541                 break;
 2542         case CDIOCALLOW:
 2543                 cam_periph_lock(periph);
 2544                 cdprevent(periph, PR_ALLOW);
 2545                 cam_periph_unlock(periph);
 2546                 break;
 2547         case CDIOCPREVENT:
 2548                 cam_periph_lock(periph);
 2549                 cdprevent(periph, PR_PREVENT);
 2550                 cam_periph_unlock(periph);
 2551                 break;
 2552         case CDIOCSETDEBUG:
 2553                 /* sc_link->flags |= (SDEV_DB1 | SDEV_DB2); */
 2554                 error = ENOTTY;
 2555                 break;
 2556         case CDIOCCLRDEBUG:
 2557                 /* sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2); */
 2558                 error = ENOTTY;
 2559                 break;
 2560         case CDIOCRESET:
 2561                 /* return (cd_reset(periph)); */
 2562                 error = ENOTTY;
 2563                 break;
 2564         case CDRIOCREADSPEED:
 2565                 cam_periph_lock(periph);
 2566                 error = cdsetspeed(periph, *(u_int32_t *)addr, CDR_MAX_SPEED);
 2567                 cam_periph_unlock(periph);
 2568                 break;
 2569         case CDRIOCWRITESPEED:
 2570                 cam_periph_lock(periph);
 2571                 error = cdsetspeed(periph, CDR_MAX_SPEED, *(u_int32_t *)addr);
 2572                 cam_periph_unlock(periph);
 2573                 break;
 2574         case CDRIOCGETBLOCKSIZE:
 2575                 *(int *)addr = softc->params.blksize;
 2576                 break;
 2577         case CDRIOCSETBLOCKSIZE:
 2578                 if (*(int *)addr <= 0) {
 2579                         error = EINVAL;
 2580                         break;
 2581                 }
 2582                 softc->disk->d_sectorsize = softc->params.blksize = *(int *)addr;
 2583                 break;
 2584         case DVDIOCSENDKEY:
 2585         case DVDIOCREPORTKEY: {
 2586                 struct dvd_authinfo *authinfo;
 2587 
 2588                 authinfo = (struct dvd_authinfo *)addr;
 2589 
 2590                 if (cmd == DVDIOCREPORTKEY)
 2591                         error = cdreportkey(periph, authinfo);
 2592                 else
 2593                         error = cdsendkey(periph, authinfo);
 2594                 break;
 2595                 }
 2596         case DVDIOCREADSTRUCTURE: {
 2597                 struct dvd_struct *dvdstruct;
 2598 
 2599                 dvdstruct = (struct dvd_struct *)addr;
 2600 
 2601                 error = cdreaddvdstructure(periph, dvdstruct);
 2602 
 2603                 break;
 2604         }
 2605         default:
 2606                 cam_periph_lock(periph);
 2607                 error = cam_periph_ioctl(periph, cmd, addr, cderror);
 2608                 cam_periph_unlock(periph);
 2609                 break;
 2610         }
 2611 
 2612         cam_periph_lock(periph);
 2613         cam_periph_unhold(periph);
 2614 
 2615         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdioctl\n"));
 2616         if (error && bootverbose) {
 2617                 printf("scsi_cd.c::ioctl cmd=%08lx error=%d\n", cmd, error);
 2618         }
 2619         cam_periph_unlock(periph);
 2620 
 2621         return (error);
 2622 }
 2623 
 2624 static void
 2625 cdprevent(struct cam_periph *periph, int action)
 2626 {
 2627         union   ccb *ccb;
 2628         struct  cd_softc *softc;
 2629         int     error;
 2630 
 2631         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdprevent\n"));
 2632 
 2633         cam_periph_assert(periph, MA_OWNED);
 2634         softc = (struct cd_softc *)periph->softc;
 2635 
 2636         if (((action == PR_ALLOW)
 2637           && (softc->flags & CD_FLAG_DISC_LOCKED) == 0)
 2638          || ((action == PR_PREVENT)
 2639           && (softc->flags & CD_FLAG_DISC_LOCKED) != 0)) {
 2640                 return;
 2641         }
 2642 
 2643         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 2644 
 2645         scsi_prevent(&ccb->csio,
 2646                      /*retries*/ cd_retry_count,
 2647                      /*cbfcnp*/NULL,
 2648                      MSG_SIMPLE_Q_TAG,
 2649                      action,
 2650                      SSD_FULL_SIZE,
 2651                      /* timeout */60000);
 2652 
 2653         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 2654                         /*sense_flags*/SF_RETRY_UA|SF_NO_PRINT);
 2655 
 2656         xpt_release_ccb(ccb);
 2657 
 2658         if (error == 0) {
 2659                 if (action == PR_ALLOW)
 2660                         softc->flags &= ~CD_FLAG_DISC_LOCKED;
 2661                 else
 2662                         softc->flags |= CD_FLAG_DISC_LOCKED;
 2663         }
 2664 }
 2665 
 2666 static void
 2667 cdmediaprobedone(struct cam_periph *periph)
 2668 {
 2669         struct cd_softc *softc;
 2670 
 2671         cam_periph_assert(periph, MA_OWNED);
 2672         softc = (struct cd_softc *)periph->softc;
 2673 
 2674         softc->flags &= ~CD_FLAG_MEDIA_SCAN_ACT;
 2675 
 2676         if ((softc->flags & CD_FLAG_MEDIA_WAIT) != 0) {
 2677                 softc->flags &= ~CD_FLAG_MEDIA_WAIT;
 2678                 wakeup(&softc->toc);
 2679         }
 2680 }
 2681 
 2682 /*
 2683  * XXX: the disk media and sector size is only really able to change
 2684  * XXX: while the device is closed.
 2685  */
 2686 
 2687 static int
 2688 cdcheckmedia(struct cam_periph *periph, int do_wait)
 2689 {
 2690         struct cd_softc *softc;
 2691         int error;
 2692 
 2693         cam_periph_assert(periph, MA_OWNED);
 2694         softc = (struct cd_softc *)periph->softc;
 2695         error = 0;
 2696 
 2697         if ((do_wait != 0)
 2698          && ((softc->flags & CD_FLAG_MEDIA_WAIT) == 0)) {
 2699                 softc->flags |= CD_FLAG_MEDIA_WAIT;
 2700         }
 2701         if ((softc->flags & CD_FLAG_MEDIA_SCAN_ACT) == 0) {
 2702                 softc->state = CD_STATE_MEDIA_PREVENT;
 2703                 softc->flags |= CD_FLAG_MEDIA_SCAN_ACT;
 2704                 xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 2705         }
 2706 
 2707         if (do_wait == 0)
 2708                 goto bailout;
 2709 
 2710         error = msleep(&softc->toc, cam_periph_mtx(periph), PRIBIO,"cdmedia",0);
 2711 
 2712         if (error != 0)
 2713                 goto bailout;
 2714 
 2715         /*
 2716          * Check to see whether we have a valid size from the media.  We
 2717          * may or may not have a valid TOC.
 2718          */
 2719         if ((softc->flags & CD_FLAG_VALID_MEDIA) == 0)
 2720                 error = EINVAL;
 2721 bailout:
 2722 
 2723         return (error);
 2724 }
 2725 
 2726 #if 0
 2727 static int
 2728 cdcheckmedia(struct cam_periph *periph)
 2729 {
 2730         struct cd_softc *softc;
 2731         struct ioc_toc_header *toch;
 2732         struct cd_toc_single leadout;
 2733         u_int32_t size, toclen;
 2734         int error, num_entries, cdindex;
 2735 
 2736         softc = (struct cd_softc *)periph->softc;
 2737 
 2738         cdprevent(periph, PR_PREVENT);
 2739         softc->disk->d_sectorsize = 2048;
 2740         softc->disk->d_mediasize = 0;
 2741 
 2742         /*
 2743          * Get the disc size and block size.  If we can't get it, we don't
 2744          * have media, most likely.
 2745          */
 2746         if ((error = cdsize(periph, &size)) != 0) {
 2747                 softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC);
 2748                 cdprevent(periph, PR_ALLOW);
 2749                 return (error);
 2750         } else {
 2751                 softc->flags |= CD_FLAG_SAW_MEDIA | CD_FLAG_VALID_MEDIA;
 2752                 softc->disk->d_sectorsize = softc->params.blksize;
 2753                 softc->disk->d_mediasize =
 2754                     (off_t)softc->params.blksize * softc->params.disksize;
 2755         }
 2756 
 2757         /*
 2758          * Now we check the table of contents.  This (currently) is only
 2759          * used for the CDIOCPLAYTRACKS ioctl.  It may be used later to do
 2760          * things like present a separate entry in /dev for each track,
 2761          * like that acd(4) driver does.
 2762          */
 2763         bzero(&softc->toc, sizeof(softc->toc));
 2764         toch = &softc->toc.header;
 2765         /*
 2766          * We will get errors here for media that doesn't have a table of
 2767          * contents.  According to the MMC-3 spec: "When a Read TOC/PMA/ATIP
 2768          * command is presented for a DDCD/CD-R/RW media, where the first TOC
 2769          * has not been recorded (no complete session) and the Format codes
 2770          * 0000b, 0001b, or 0010b are specified, this command shall be rejected
 2771          * with an INVALID FIELD IN CDB.  Devices that are not capable of
 2772          * reading an incomplete session on DDC/CD-R/RW media shall report
 2773          * CANNOT READ MEDIUM - INCOMPATIBLE FORMAT."
 2774          *
 2775          * So this isn't fatal if we can't read the table of contents, it
 2776          * just means that the user won't be able to issue the play tracks
 2777          * ioctl, and likely lots of other stuff won't work either.  They
 2778          * need to burn the CD before we can do a whole lot with it.  So
 2779          * we don't print anything here if we get an error back.
 2780          */
 2781         error = cdreadtoc(periph, 0, 0, (u_int8_t *)toch, sizeof(*toch),
 2782                           SF_NO_PRINT);
 2783         /*
 2784          * Errors in reading the table of contents aren't fatal, we just
 2785          * won't have a valid table of contents cached.
 2786          */
 2787         if (error != 0) {
 2788                 error = 0;
 2789                 bzero(&softc->toc, sizeof(softc->toc));
 2790                 goto bailout;
 2791         }
 2792 
 2793         if (softc->quirks & CD_Q_BCD_TRACKS) {
 2794                 toch->starting_track = bcd2bin(toch->starting_track);
 2795                 toch->ending_track = bcd2bin(toch->ending_track);
 2796         }
 2797 
 2798         /* Number of TOC entries, plus leadout */
 2799         num_entries = (toch->ending_track - toch->starting_track) + 2;
 2800 
 2801         if (num_entries <= 0)
 2802                 goto bailout;
 2803 
 2804         toclen = num_entries * sizeof(struct cd_toc_entry);
 2805 
 2806         error = cdreadtoc(periph, CD_MSF_FORMAT, toch->starting_track,
 2807                           (u_int8_t *)&softc->toc, toclen + sizeof(*toch),
 2808                           SF_NO_PRINT);
 2809         if (error != 0) {
 2810                 error = 0;
 2811                 bzero(&softc->toc, sizeof(softc->toc));
 2812                 goto bailout;
 2813         }
 2814 
 2815         if (softc->quirks & CD_Q_BCD_TRACKS) {
 2816                 toch->starting_track = bcd2bin(toch->starting_track);
 2817                 toch->ending_track = bcd2bin(toch->ending_track);
 2818         }
 2819         /*
 2820          * XXX KDM is this necessary?  Probably only if the drive doesn't
 2821          * return leadout information with the table of contents.
 2822          */
 2823         cdindex = toch->starting_track + num_entries -1;
 2824         if (cdindex == toch->ending_track + 1) {
 2825                 error = cdreadtoc(periph, CD_MSF_FORMAT, LEADOUT,
 2826                                   (u_int8_t *)&leadout, sizeof(leadout),
 2827                                   SF_NO_PRINT);
 2828                 if (error != 0) {
 2829                         error = 0;
 2830                         goto bailout;
 2831                 }
 2832                 softc->toc.entries[cdindex - toch->starting_track] =
 2833                         leadout.entry;
 2834         }
 2835         if (softc->quirks & CD_Q_BCD_TRACKS) {
 2836                 for (cdindex = 0; cdindex < num_entries - 1; cdindex++) {
 2837                         softc->toc.entries[cdindex].track =
 2838                                 bcd2bin(softc->toc.entries[cdindex].track);
 2839                 }
 2840         }
 2841 
 2842         softc->flags |= CD_FLAG_VALID_TOC;
 2843 
 2844         /* If the first track is audio, correct sector size. */
 2845         if ((softc->toc.entries[0].control & 4) == 0) {
 2846                 softc->disk->d_sectorsize = softc->params.blksize = 2352;
 2847                 softc->disk->d_mediasize =
 2848                     (off_t)softc->params.blksize * softc->params.disksize;
 2849         }
 2850 
 2851 bailout:
 2852 
 2853         /*
 2854          * We unconditionally (re)set the blocksize each time the
 2855          * CD device is opened.  This is because the CD can change,
 2856          * and therefore the blocksize might change.
 2857          * XXX problems here if some slice or partition is still
 2858          * open with the old size?
 2859          */
 2860         if ((softc->disk->d_devstat->flags & DEVSTAT_BS_UNAVAILABLE) != 0)
 2861                 softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE;
 2862         softc->disk->d_devstat->block_size = softc->params.blksize;
 2863 
 2864         return (error);
 2865 }
 2866 
 2867 static int
 2868 cdsize(struct cam_periph *periph, u_int32_t *size)
 2869 {
 2870         struct cd_softc *softc;
 2871         union ccb *ccb;
 2872         struct scsi_read_capacity_data *rcap_buf;
 2873         int error;
 2874 
 2875         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdsize\n"));
 2876 
 2877         softc = (struct cd_softc *)periph->softc;
 2878 
 2879         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 2880 
 2881         /* XXX Should be M_WAITOK */
 2882         rcap_buf = malloc(sizeof(struct scsi_read_capacity_data),
 2883                           M_SCSICD, M_NOWAIT | M_ZERO);
 2884         if (rcap_buf == NULL)
 2885                 return (ENOMEM);
 2886 
 2887         scsi_read_capacity(&ccb->csio,
 2888                            /*retries*/ cd_retry_count,
 2889                            /*cbfcnp*/NULL,
 2890                            MSG_SIMPLE_Q_TAG,
 2891                            rcap_buf,
 2892                            SSD_FULL_SIZE,
 2893                            /* timeout */20000);
 2894 
 2895         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 2896                          /*sense_flags*/SF_RETRY_UA|SF_NO_PRINT);
 2897 
 2898         xpt_release_ccb(ccb);
 2899 
 2900         softc->params.disksize = scsi_4btoul(rcap_buf->addr) + 1;
 2901         softc->params.blksize  = scsi_4btoul(rcap_buf->length);
 2902         /* Make sure we got at least some block size. */
 2903         if (error == 0 && softc->params.blksize == 0)
 2904                 error = EIO;
 2905         /*
 2906          * SCSI-3 mandates that the reported blocksize shall be 2048.
 2907          * Older drives sometimes report funny values, trim it down to
 2908          * 2048, or other parts of the kernel will get confused.
 2909          *
 2910          * XXX we leave drives alone that might report 512 bytes, as
 2911          * well as drives reporting more weird sizes like perhaps 4K.
 2912          */
 2913         if (softc->params.blksize > 2048 && softc->params.blksize <= 2352)
 2914                 softc->params.blksize = 2048;
 2915 
 2916         free(rcap_buf, M_SCSICD);
 2917         *size = softc->params.disksize;
 2918 
 2919         return (error);
 2920 
 2921 }
 2922 #endif
 2923 
 2924 static int
 2925 cd6byteworkaround(union ccb *ccb)
 2926 {
 2927         u_int8_t *cdb;
 2928         struct cam_periph *periph;
 2929         struct cd_softc *softc;
 2930         struct cd_mode_params *params;
 2931         int frozen, found;
 2932 
 2933         periph = xpt_path_periph(ccb->ccb_h.path);
 2934         softc = (struct cd_softc *)periph->softc;
 2935 
 2936         cdb = ccb->csio.cdb_io.cdb_bytes;
 2937 
 2938         if ((ccb->ccb_h.flags & CAM_CDB_POINTER)
 2939          || ((cdb[0] != MODE_SENSE_6)
 2940           && (cdb[0] != MODE_SELECT_6)))
 2941                 return (0);
 2942 
 2943         /*
 2944          * Because there is no convenient place to stash the overall
 2945          * cd_mode_params structure pointer, we have to grab it like this.
 2946          * This means that ALL MODE_SENSE and MODE_SELECT requests in the
 2947          * cd(4) driver MUST go through cdgetmode() and cdsetmode()!
 2948          *
 2949          * XXX It would be nice if, at some point, we could increase the
 2950          * number of available peripheral private pointers.  Both pointers
 2951          * are currently used in most every peripheral driver.
 2952          */
 2953         found = 0;
 2954 
 2955         STAILQ_FOREACH(params, &softc->mode_queue, links) {
 2956                 if (params->mode_buf == ccb->csio.data_ptr) {
 2957                         found = 1;
 2958                         break;
 2959                 }
 2960         }
 2961 
 2962         /*
 2963          * This shouldn't happen.  All mode sense and mode select
 2964          * operations in the cd(4) driver MUST go through cdgetmode() and
 2965          * cdsetmode()!
 2966          */
 2967         if (found == 0) {
 2968                 xpt_print(periph->path,
 2969                     "mode buffer not found in mode queue!\n");
 2970                 return (0);
 2971         }
 2972 
 2973         params->cdb_size = 10;
 2974         softc->minimum_command_size = 10;
 2975         xpt_print(ccb->ccb_h.path,
 2976             "%s(6) failed, increasing minimum CDB size to 10 bytes\n",
 2977             (cdb[0] == MODE_SENSE_6) ? "MODE_SENSE" : "MODE_SELECT");
 2978 
 2979         if (cdb[0] == MODE_SENSE_6) {
 2980                 struct scsi_mode_sense_10 ms10;
 2981                 struct scsi_mode_sense_6 *ms6;
 2982                 int len;
 2983 
 2984                 ms6 = (struct scsi_mode_sense_6 *)cdb;
 2985 
 2986                 bzero(&ms10, sizeof(ms10));
 2987                 ms10.opcode = MODE_SENSE_10;
 2988                 ms10.byte2 = ms6->byte2;
 2989                 ms10.page = ms6->page;
 2990 
 2991                 /*
 2992                  * 10 byte mode header, block descriptor,
 2993                  * sizeof(union cd_pages)
 2994                  */
 2995                 len = sizeof(struct cd_mode_data_10);
 2996                 ccb->csio.dxfer_len = len;
 2997 
 2998                 scsi_ulto2b(len, ms10.length);
 2999                 ms10.control = ms6->control;
 3000                 bcopy(&ms10, cdb, 10);
 3001                 ccb->csio.cdb_len = 10;
 3002         } else {
 3003                 struct scsi_mode_select_10 ms10;
 3004                 struct scsi_mode_select_6 *ms6;
 3005                 struct scsi_mode_header_6 *header6;
 3006                 struct scsi_mode_header_10 *header10;
 3007                 struct scsi_mode_page_header *page_header;
 3008                 int blk_desc_len, page_num, page_size, len;
 3009 
 3010                 ms6 = (struct scsi_mode_select_6 *)cdb;
 3011 
 3012                 bzero(&ms10, sizeof(ms10));
 3013                 ms10.opcode = MODE_SELECT_10;
 3014                 ms10.byte2 = ms6->byte2;
 3015 
 3016                 header6 = (struct scsi_mode_header_6 *)params->mode_buf;
 3017                 header10 = (struct scsi_mode_header_10 *)params->mode_buf;
 3018 
 3019                 page_header = find_mode_page_6(header6);
 3020                 page_num = page_header->page_code;
 3021 
 3022                 blk_desc_len = header6->blk_desc_len;
 3023 
 3024                 page_size = cdgetpagesize(page_num);
 3025 
 3026                 if (page_size != (page_header->page_length +
 3027                     sizeof(*page_header)))
 3028                         page_size = page_header->page_length +
 3029                                 sizeof(*page_header);
 3030 
 3031                 len = sizeof(*header10) + blk_desc_len + page_size;
 3032 
 3033                 len = min(params->alloc_len, len);
 3034 
 3035                 /*
 3036                  * Since the 6 byte parameter header is shorter than the 10
 3037                  * byte parameter header, we need to copy the actual mode
 3038                  * page data, and the block descriptor, if any, so things wind
 3039                  * up in the right place.  The regions will overlap, but
 3040                  * bcopy() does the right thing.
 3041                  */
 3042                 bcopy(params->mode_buf + sizeof(*header6),
 3043                       params->mode_buf + sizeof(*header10),
 3044                       len - sizeof(*header10));
 3045 
 3046                 /* Make sure these fields are set correctly. */
 3047                 scsi_ulto2b(0, header10->data_length);
 3048                 header10->medium_type = 0;
 3049                 scsi_ulto2b(blk_desc_len, header10->blk_desc_len);
 3050 
 3051                 ccb->csio.dxfer_len = len;
 3052 
 3053                 scsi_ulto2b(len, ms10.length);
 3054                 ms10.control = ms6->control;
 3055                 bcopy(&ms10, cdb, 10);
 3056                 ccb->csio.cdb_len = 10;
 3057         }
 3058 
 3059         frozen = (ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
 3060         ccb->ccb_h.status = CAM_REQUEUE_REQ;
 3061         xpt_action(ccb);
 3062         if (frozen) {
 3063                 cam_release_devq(ccb->ccb_h.path,
 3064                                  /*relsim_flags*/0,
 3065                                  /*openings*/0,
 3066                                  /*timeout*/0,
 3067                                  /*getcount_only*/0);
 3068         }
 3069 
 3070         return (ERESTART);
 3071 }
 3072 
 3073 static int
 3074 cderror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
 3075 {
 3076         struct cd_softc *softc;
 3077         struct cam_periph *periph;
 3078         int error, error_code, sense_key, asc, ascq;
 3079 
 3080         periph = xpt_path_periph(ccb->ccb_h.path);
 3081         softc = (struct cd_softc *)periph->softc;
 3082 
 3083         cam_periph_assert(periph, MA_OWNED);
 3084 
 3085         /*
 3086          * We use a status of CAM_REQ_INVALID as shorthand -- if a 6 byte
 3087          * CDB comes back with this particular error, try transforming it
 3088          * into the 10 byte version.
 3089          */
 3090         error = 0;
 3091         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
 3092                 error = cd6byteworkaround(ccb);
 3093         } else if (scsi_extract_sense_ccb(ccb,
 3094             &error_code, &sense_key, &asc, &ascq)) {
 3095                 if (sense_key == SSD_KEY_ILLEGAL_REQUEST)
 3096                         error = cd6byteworkaround(ccb);
 3097                 else if (sense_key == SSD_KEY_UNIT_ATTENTION &&
 3098                     asc == 0x28 && ascq == 0x00)
 3099                         disk_media_changed(softc->disk, M_NOWAIT);
 3100                 else if (sense_key == SSD_KEY_NOT_READY &&
 3101                     asc == 0x3a && (softc->flags & CD_FLAG_SAW_MEDIA)) {
 3102                         softc->flags &= ~CD_FLAG_SAW_MEDIA;
 3103                         disk_media_gone(softc->disk, M_NOWAIT);
 3104                 }
 3105         }
 3106 
 3107         if (error == ERESTART)
 3108                 return (error);
 3109 
 3110         /*
 3111          * XXX
 3112          * Until we have a better way of doing pack validation,
 3113          * don't treat UAs as errors.
 3114          */
 3115         sense_flags |= SF_RETRY_UA;
 3116 
 3117         if (softc->quirks & CD_Q_RETRY_BUSY)
 3118                 sense_flags |= SF_RETRY_BUSY;
 3119         return (cam_periph_error(ccb, cam_flags, sense_flags));
 3120 }
 3121 
 3122 static void
 3123 cdmediapoll(void *arg)
 3124 {
 3125         struct cam_periph *periph = arg;
 3126         struct cd_softc *softc = periph->softc;
 3127 
 3128         if (softc->state == CD_STATE_NORMAL && !softc->tur &&
 3129             softc->outstanding_cmds == 0) {
 3130                 if (cam_periph_acquire(periph) == 0) {
 3131                         softc->tur = 1;
 3132                         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 3133                 }
 3134         }
 3135 
 3136         /* Queue us up again */
 3137         if (cd_poll_period != 0) {
 3138                 callout_schedule_sbt(&softc->mediapoll_c,
 3139                     cd_poll_period * SBT_1S, 0, C_PREL(1));
 3140         }
 3141 }
 3142 
 3143 /*
 3144  * Read table of contents
 3145  */
 3146 static int
 3147 cdreadtoc(struct cam_periph *periph, u_int32_t mode, u_int32_t start,
 3148           u_int8_t *data, u_int32_t len, u_int32_t sense_flags)
 3149 {
 3150         struct ccb_scsiio *csio;
 3151         union ccb *ccb;
 3152         int error;
 3153 
 3154         error = 0;
 3155 
 3156         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3157 
 3158         csio = &ccb->csio;
 3159 
 3160         scsi_read_toc(csio,
 3161                       /* retries */ cd_retry_count,
 3162                       /* cbfcnp */ NULL,
 3163                       /* tag_action */ MSG_SIMPLE_Q_TAG,
 3164                       /* byte1_flags */ (mode == CD_MSF_FORMAT) ? CD_MSF : 0,
 3165                       /* format */ SRTOC_FORMAT_TOC,
 3166                       /* track*/ start,
 3167                       /* data_ptr */ data,
 3168                       /* dxfer_len */ len,
 3169                       /* sense_len */ SSD_FULL_SIZE,
 3170                       /* timeout */ 50000);
 3171 
 3172         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3173                          /*sense_flags*/SF_RETRY_UA | sense_flags);
 3174 
 3175         xpt_release_ccb(ccb);
 3176 
 3177         return(error);
 3178 }
 3179 
 3180 static int
 3181 cdreadsubchannel(struct cam_periph *periph, u_int32_t mode,
 3182                  u_int32_t format, int track,
 3183                  struct cd_sub_channel_info *data, u_int32_t len)
 3184 {
 3185         struct scsi_read_subchannel *scsi_cmd;
 3186         struct ccb_scsiio *csio;
 3187         union ccb *ccb;
 3188         int error;
 3189 
 3190         error = 0;
 3191 
 3192         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3193 
 3194         csio = &ccb->csio;
 3195 
 3196         cam_fill_csio(csio,
 3197                       /* retries */ cd_retry_count,
 3198                       /* cbfcnp */ NULL,
 3199                       /* flags */ CAM_DIR_IN,
 3200                       /* tag_action */ MSG_SIMPLE_Q_TAG,
 3201                       /* data_ptr */ (u_int8_t *)data,
 3202                       /* dxfer_len */ len,
 3203                       /* sense_len */ SSD_FULL_SIZE,
 3204                       sizeof(struct scsi_read_subchannel),
 3205                       /* timeout */ 50000);
 3206 
 3207         scsi_cmd = (struct scsi_read_subchannel *)&csio->cdb_io.cdb_bytes;
 3208         bzero (scsi_cmd, sizeof(*scsi_cmd));
 3209 
 3210         scsi_cmd->op_code = READ_SUBCHANNEL;
 3211         if (mode == CD_MSF_FORMAT)
 3212                 scsi_cmd->byte1 |= CD_MSF;
 3213         scsi_cmd->byte2 = SRS_SUBQ;
 3214         scsi_cmd->subchan_format = format;
 3215         scsi_cmd->track = track;
 3216         scsi_ulto2b(len, (u_int8_t *)scsi_cmd->data_len);
 3217         scsi_cmd->control = 0;
 3218 
 3219         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3220                          /*sense_flags*/SF_RETRY_UA);
 3221 
 3222         xpt_release_ccb(ccb);
 3223 
 3224         return(error);
 3225 }
 3226 
 3227 /*
 3228  * All MODE_SENSE requests in the cd(4) driver MUST go through this
 3229  * routine.  See comments in cd6byteworkaround() for details.
 3230  */
 3231 static int
 3232 cdgetmode(struct cam_periph *periph, struct cd_mode_params *data,
 3233           u_int32_t page)
 3234 {
 3235         struct ccb_scsiio *csio;
 3236         struct cd_softc *softc;
 3237         union ccb *ccb;
 3238         int param_len;
 3239         int error;
 3240 
 3241         softc = (struct cd_softc *)periph->softc;
 3242 
 3243         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3244 
 3245         csio = &ccb->csio;
 3246 
 3247         data->cdb_size = softc->minimum_command_size;
 3248         if (data->cdb_size < 10)
 3249                 param_len = sizeof(struct cd_mode_data);
 3250         else
 3251                 param_len = sizeof(struct cd_mode_data_10);
 3252 
 3253         /* Don't say we've got more room than we actually allocated */
 3254         param_len = min(param_len, data->alloc_len);
 3255 
 3256         scsi_mode_sense_len(csio,
 3257                             /* retries */ cd_retry_count,
 3258                             /* cbfcnp */ NULL,
 3259                             /* tag_action */ MSG_SIMPLE_Q_TAG,
 3260                             /* dbd */ 0,
 3261                             /* page_code */ SMS_PAGE_CTRL_CURRENT,
 3262                             /* page */ page,
 3263                             /* param_buf */ data->mode_buf,
 3264                             /* param_len */ param_len,
 3265                             /* minimum_cmd_size */ softc->minimum_command_size,
 3266                             /* sense_len */ SSD_FULL_SIZE,
 3267                             /* timeout */ 50000);
 3268 
 3269         /*
 3270          * It would be nice not to have to do this, but there's no
 3271          * available pointer in the CCB that would allow us to stuff the
 3272          * mode params structure in there and retrieve it in
 3273          * cd6byteworkaround(), so we can set the cdb size.  The cdb size
 3274          * lets the caller know what CDB size we ended up using, so they
 3275          * can find the actual mode page offset.
 3276          */
 3277         STAILQ_INSERT_TAIL(&softc->mode_queue, data, links);
 3278 
 3279         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3280                          /*sense_flags*/SF_RETRY_UA);
 3281 
 3282         xpt_release_ccb(ccb);
 3283 
 3284         STAILQ_REMOVE(&softc->mode_queue, data, cd_mode_params, links);
 3285 
 3286         /*
 3287          * This is a bit of belt-and-suspenders checking, but if we run
 3288          * into a situation where the target sends back multiple block
 3289          * descriptors, we might not have enough space in the buffer to
 3290          * see the whole mode page.  Better to return an error than
 3291          * potentially access memory beyond our malloced region.
 3292          */
 3293         if (error == 0) {
 3294                 u_int32_t data_len;
 3295 
 3296                 if (data->cdb_size == 10) {
 3297                         struct scsi_mode_header_10 *hdr10;
 3298 
 3299                         hdr10 = (struct scsi_mode_header_10 *)data->mode_buf;
 3300                         data_len = scsi_2btoul(hdr10->data_length);
 3301                         data_len += sizeof(hdr10->data_length);
 3302                 } else {
 3303                         struct scsi_mode_header_6 *hdr6;
 3304 
 3305                         hdr6 = (struct scsi_mode_header_6 *)data->mode_buf;
 3306                         data_len = hdr6->data_length;
 3307                         data_len += sizeof(hdr6->data_length);
 3308                 }
 3309 
 3310                 /*
 3311                  * Complain if there is more mode data available than we
 3312                  * allocated space for.  This could potentially happen if
 3313                  * we miscalculated the page length for some reason, if the
 3314                  * drive returns multiple block descriptors, or if it sets
 3315                  * the data length incorrectly.
 3316                  */
 3317                 if (data_len > data->alloc_len) {
 3318                         xpt_print(periph->path, "allocated modepage %d length "
 3319                             "%d < returned length %d\n", page, data->alloc_len,
 3320                             data_len);
 3321                         error = ENOSPC;
 3322                 }
 3323         }
 3324         return (error);
 3325 }
 3326 
 3327 /*
 3328  * All MODE_SELECT requests in the cd(4) driver MUST go through this
 3329  * routine.  See comments in cd6byteworkaround() for details.
 3330  */
 3331 static int
 3332 cdsetmode(struct cam_periph *periph, struct cd_mode_params *data)
 3333 {
 3334         struct ccb_scsiio *csio;
 3335         struct cd_softc *softc;
 3336         union ccb *ccb;
 3337         int cdb_size, param_len;
 3338         int error;
 3339 
 3340         softc = (struct cd_softc *)periph->softc;
 3341 
 3342         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3343 
 3344         csio = &ccb->csio;
 3345 
 3346         error = 0;
 3347 
 3348         /*
 3349          * If the data is formatted for the 10 byte version of the mode
 3350          * select parameter list, we need to use the 10 byte CDB.
 3351          * Otherwise, we use whatever the stored minimum command size.
 3352          */
 3353         if (data->cdb_size == 10)
 3354                 cdb_size = data->cdb_size;
 3355         else
 3356                 cdb_size = softc->minimum_command_size;
 3357 
 3358         if (cdb_size >= 10) {
 3359                 struct scsi_mode_header_10 *mode_header;
 3360                 u_int32_t data_len;
 3361 
 3362                 mode_header = (struct scsi_mode_header_10 *)data->mode_buf;
 3363 
 3364                 data_len = scsi_2btoul(mode_header->data_length);
 3365 
 3366                 scsi_ulto2b(0, mode_header->data_length);
 3367                 /*
 3368                  * SONY drives do not allow a mode select with a medium_type
 3369                  * value that has just been returned by a mode sense; use a
 3370                  * medium_type of 0 (Default) instead.
 3371                  */
 3372                 mode_header->medium_type = 0;
 3373 
 3374                 /*
 3375                  * Pass back whatever the drive passed to us, plus the size
 3376                  * of the data length field.
 3377                  */
 3378                 param_len = data_len + sizeof(mode_header->data_length);
 3379 
 3380         } else {
 3381                 struct scsi_mode_header_6 *mode_header;
 3382 
 3383                 mode_header = (struct scsi_mode_header_6 *)data->mode_buf;
 3384 
 3385                 param_len = mode_header->data_length + 1;
 3386 
 3387                 mode_header->data_length = 0;
 3388                 /*
 3389                  * SONY drives do not allow a mode select with a medium_type
 3390                  * value that has just been returned by a mode sense; use a
 3391                  * medium_type of 0 (Default) instead.
 3392                  */
 3393                 mode_header->medium_type = 0;
 3394         }
 3395 
 3396         /* Don't say we've got more room than we actually allocated */
 3397         param_len = min(param_len, data->alloc_len);
 3398 
 3399         scsi_mode_select_len(csio,
 3400                              /* retries */ cd_retry_count,
 3401                              /* cbfcnp */ NULL,
 3402                              /* tag_action */ MSG_SIMPLE_Q_TAG,
 3403                              /* scsi_page_fmt */ 1,
 3404                              /* save_pages */ 0,
 3405                              /* param_buf */ data->mode_buf,
 3406                              /* param_len */ param_len,
 3407                              /* minimum_cmd_size */ cdb_size,
 3408                              /* sense_len */ SSD_FULL_SIZE,
 3409                              /* timeout */ 50000);
 3410 
 3411         /* See comments in cdgetmode() and cd6byteworkaround(). */
 3412         STAILQ_INSERT_TAIL(&softc->mode_queue, data, links);
 3413 
 3414         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3415                          /*sense_flags*/SF_RETRY_UA);
 3416 
 3417         xpt_release_ccb(ccb);
 3418 
 3419         STAILQ_REMOVE(&softc->mode_queue, data, cd_mode_params, links);
 3420 
 3421         return (error);
 3422 }
 3423 
 3424 static int
 3425 cdplay(struct cam_periph *periph, u_int32_t blk, u_int32_t len)
 3426 {
 3427         struct ccb_scsiio *csio;
 3428         union ccb *ccb;
 3429         int error;
 3430         u_int8_t cdb_len;
 3431 
 3432         error = 0;
 3433         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3434         csio = &ccb->csio;
 3435         /*
 3436          * Use the smallest possible command to perform the operation.
 3437          */
 3438         if ((len & 0xffff0000) == 0) {
 3439                 /*
 3440                  * We can fit in a 10 byte cdb.
 3441                  */
 3442                 struct scsi_play_10 *scsi_cmd;
 3443 
 3444                 scsi_cmd = (struct scsi_play_10 *)&csio->cdb_io.cdb_bytes;
 3445                 bzero (scsi_cmd, sizeof(*scsi_cmd));
 3446                 scsi_cmd->op_code = PLAY_10;
 3447                 scsi_ulto4b(blk, (u_int8_t *)scsi_cmd->blk_addr);
 3448                 scsi_ulto2b(len, (u_int8_t *)scsi_cmd->xfer_len);
 3449                 cdb_len = sizeof(*scsi_cmd);
 3450         } else  {
 3451                 struct scsi_play_12 *scsi_cmd;
 3452 
 3453                 scsi_cmd = (struct scsi_play_12 *)&csio->cdb_io.cdb_bytes;
 3454                 bzero (scsi_cmd, sizeof(*scsi_cmd));
 3455                 scsi_cmd->op_code = PLAY_12;
 3456                 scsi_ulto4b(blk, (u_int8_t *)scsi_cmd->blk_addr);
 3457                 scsi_ulto4b(len, (u_int8_t *)scsi_cmd->xfer_len);
 3458                 cdb_len = sizeof(*scsi_cmd);
 3459         }
 3460         cam_fill_csio(csio,
 3461                       /*retries*/ cd_retry_count,
 3462                       /*cbfcnp*/NULL,
 3463                       /*flags*/CAM_DIR_NONE,
 3464                       MSG_SIMPLE_Q_TAG,
 3465                       /*dataptr*/NULL,
 3466                       /*datalen*/0,
 3467                       /*sense_len*/SSD_FULL_SIZE,
 3468                       cdb_len,
 3469                       /*timeout*/50 * 1000);
 3470 
 3471         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3472                          /*sense_flags*/SF_RETRY_UA);
 3473 
 3474         xpt_release_ccb(ccb);
 3475 
 3476         return(error);
 3477 }
 3478 
 3479 static int
 3480 cdplaymsf(struct cam_periph *periph, u_int32_t startm, u_int32_t starts,
 3481           u_int32_t startf, u_int32_t endm, u_int32_t ends, u_int32_t endf)
 3482 {
 3483         struct scsi_play_msf *scsi_cmd;
 3484         struct ccb_scsiio *csio;
 3485         union ccb *ccb;
 3486         int error;
 3487 
 3488         error = 0;
 3489 
 3490         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3491 
 3492         csio = &ccb->csio;
 3493 
 3494         cam_fill_csio(csio,
 3495                       /* retries */ cd_retry_count,
 3496                       /* cbfcnp */ NULL,
 3497                       /* flags */ CAM_DIR_NONE,
 3498                       /* tag_action */ MSG_SIMPLE_Q_TAG,
 3499                       /* data_ptr */ NULL,
 3500                       /* dxfer_len */ 0,
 3501                       /* sense_len */ SSD_FULL_SIZE,
 3502                       sizeof(struct scsi_play_msf),
 3503                       /* timeout */ 50000);
 3504 
 3505         scsi_cmd = (struct scsi_play_msf *)&csio->cdb_io.cdb_bytes;
 3506         bzero (scsi_cmd, sizeof(*scsi_cmd));
 3507 
 3508         scsi_cmd->op_code = PLAY_MSF;
 3509         scsi_cmd->start_m = startm;
 3510         scsi_cmd->start_s = starts;
 3511         scsi_cmd->start_f = startf;
 3512         scsi_cmd->end_m = endm;
 3513         scsi_cmd->end_s = ends;
 3514         scsi_cmd->end_f = endf;
 3515 
 3516         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3517                          /*sense_flags*/SF_RETRY_UA);
 3518 
 3519         xpt_release_ccb(ccb);
 3520 
 3521         return(error);
 3522 }
 3523 
 3524 static int
 3525 cdplaytracks(struct cam_periph *periph, u_int32_t strack, u_int32_t sindex,
 3526              u_int32_t etrack, u_int32_t eindex)
 3527 {
 3528         struct scsi_play_track *scsi_cmd;
 3529         struct ccb_scsiio *csio;
 3530         union ccb *ccb;
 3531         int error;
 3532 
 3533         error = 0;
 3534 
 3535         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3536 
 3537         csio = &ccb->csio;
 3538 
 3539         cam_fill_csio(csio,
 3540                       /* retries */ cd_retry_count,
 3541                       /* cbfcnp */ NULL,
 3542                       /* flags */ CAM_DIR_NONE,
 3543                       /* tag_action */ MSG_SIMPLE_Q_TAG,
 3544                       /* data_ptr */ NULL,
 3545                       /* dxfer_len */ 0,
 3546                       /* sense_len */ SSD_FULL_SIZE,
 3547                       sizeof(struct scsi_play_track),
 3548                       /* timeout */ 50000);
 3549 
 3550         scsi_cmd = (struct scsi_play_track *)&csio->cdb_io.cdb_bytes;
 3551         bzero (scsi_cmd, sizeof(*scsi_cmd));
 3552 
 3553         scsi_cmd->op_code = PLAY_TRACK;
 3554         scsi_cmd->start_track = strack;
 3555         scsi_cmd->start_index = sindex;
 3556         scsi_cmd->end_track = etrack;
 3557         scsi_cmd->end_index = eindex;
 3558 
 3559         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3560                          /*sense_flags*/SF_RETRY_UA);
 3561 
 3562         xpt_release_ccb(ccb);
 3563 
 3564         return(error);
 3565 }
 3566 
 3567 static int
 3568 cdpause(struct cam_periph *periph, u_int32_t go)
 3569 {
 3570         struct scsi_pause *scsi_cmd;
 3571         struct ccb_scsiio *csio;
 3572         union ccb *ccb;
 3573         int error;
 3574 
 3575         error = 0;
 3576 
 3577         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3578 
 3579         csio = &ccb->csio;
 3580 
 3581         cam_fill_csio(csio,
 3582                       /* retries */ cd_retry_count,
 3583                       /* cbfcnp */ NULL,
 3584                       /* flags */ CAM_DIR_NONE,
 3585                       /* tag_action */ MSG_SIMPLE_Q_TAG,
 3586                       /* data_ptr */ NULL,
 3587                       /* dxfer_len */ 0,
 3588                       /* sense_len */ SSD_FULL_SIZE,
 3589                       sizeof(struct scsi_pause),
 3590                       /* timeout */ 50000);
 3591 
 3592         scsi_cmd = (struct scsi_pause *)&csio->cdb_io.cdb_bytes;
 3593         bzero (scsi_cmd, sizeof(*scsi_cmd));
 3594 
 3595         scsi_cmd->op_code = PAUSE;
 3596         scsi_cmd->resume = go;
 3597 
 3598         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3599                          /*sense_flags*/SF_RETRY_UA);
 3600 
 3601         xpt_release_ccb(ccb);
 3602 
 3603         return(error);
 3604 }
 3605 
 3606 static int
 3607 cdstartunit(struct cam_periph *periph, int load)
 3608 {
 3609         union ccb *ccb;
 3610         int error;
 3611 
 3612         error = 0;
 3613 
 3614         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3615 
 3616         scsi_start_stop(&ccb->csio,
 3617                         /* retries */ cd_retry_count,
 3618                         /* cbfcnp */ NULL,
 3619                         /* tag_action */ MSG_SIMPLE_Q_TAG,
 3620                         /* start */ TRUE,
 3621                         /* load_eject */ load,
 3622                         /* immediate */ FALSE,
 3623                         /* sense_len */ SSD_FULL_SIZE,
 3624                         /* timeout */ 50000);
 3625 
 3626         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3627                          /*sense_flags*/SF_RETRY_UA);
 3628 
 3629         xpt_release_ccb(ccb);
 3630 
 3631         return(error);
 3632 }
 3633 
 3634 static int
 3635 cdstopunit(struct cam_periph *periph, u_int32_t eject)
 3636 {
 3637         union ccb *ccb;
 3638         int error;
 3639 
 3640         error = 0;
 3641 
 3642         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3643 
 3644         scsi_start_stop(&ccb->csio,
 3645                         /* retries */ cd_retry_count,
 3646                         /* cbfcnp */ NULL,
 3647                         /* tag_action */ MSG_SIMPLE_Q_TAG,
 3648                         /* start */ FALSE,
 3649                         /* load_eject */ eject,
 3650                         /* immediate */ FALSE,
 3651                         /* sense_len */ SSD_FULL_SIZE,
 3652                         /* timeout */ 50000);
 3653 
 3654         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3655                          /*sense_flags*/SF_RETRY_UA);
 3656 
 3657         xpt_release_ccb(ccb);
 3658 
 3659         return(error);
 3660 }
 3661 
 3662 static int
 3663 cdsetspeed(struct cam_periph *periph, u_int32_t rdspeed, u_int32_t wrspeed)
 3664 {
 3665         struct scsi_set_speed *scsi_cmd;
 3666         struct ccb_scsiio *csio;
 3667         union ccb *ccb;
 3668         int error;
 3669 
 3670         error = 0;
 3671         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3672         csio = &ccb->csio;
 3673 
 3674         /* Preserve old behavior: units in multiples of CDROM speed */
 3675         if (rdspeed < 177)
 3676                 rdspeed *= 177;
 3677         if (wrspeed < 177)
 3678                 wrspeed *= 177;
 3679 
 3680         cam_fill_csio(csio,
 3681                       /* retries */ cd_retry_count,
 3682                       /* cbfcnp */ NULL,
 3683                       /* flags */ CAM_DIR_NONE,
 3684                       /* tag_action */ MSG_SIMPLE_Q_TAG,
 3685                       /* data_ptr */ NULL,
 3686                       /* dxfer_len */ 0,
 3687                       /* sense_len */ SSD_FULL_SIZE,
 3688                       sizeof(struct scsi_set_speed),
 3689                       /* timeout */ 50000);
 3690 
 3691         scsi_cmd = (struct scsi_set_speed *)&csio->cdb_io.cdb_bytes;
 3692         bzero(scsi_cmd, sizeof(*scsi_cmd));
 3693 
 3694         scsi_cmd->opcode = SET_CD_SPEED;
 3695         scsi_ulto2b(rdspeed, scsi_cmd->readspeed);
 3696         scsi_ulto2b(wrspeed, scsi_cmd->writespeed);
 3697 
 3698         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3699                          /*sense_flags*/SF_RETRY_UA);
 3700 
 3701         xpt_release_ccb(ccb);
 3702 
 3703         return(error);
 3704 }
 3705 
 3706 static int
 3707 cdreportkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
 3708 {
 3709         union ccb *ccb;
 3710         u_int8_t *databuf;
 3711         u_int32_t lba;
 3712         int error;
 3713         int length;
 3714 
 3715         error = 0;
 3716         databuf = NULL;
 3717         lba = 0;
 3718 
 3719         switch (authinfo->format) {
 3720         case DVD_REPORT_AGID:
 3721                 length = sizeof(struct scsi_report_key_data_agid);
 3722                 break;
 3723         case DVD_REPORT_CHALLENGE:
 3724                 length = sizeof(struct scsi_report_key_data_challenge);
 3725                 break;
 3726         case DVD_REPORT_KEY1:
 3727                 length = sizeof(struct scsi_report_key_data_key1_key2);
 3728                 break;
 3729         case DVD_REPORT_TITLE_KEY:
 3730                 length = sizeof(struct scsi_report_key_data_title);
 3731                 /* The lba field is only set for the title key */
 3732                 lba = authinfo->lba;
 3733                 break;
 3734         case DVD_REPORT_ASF:
 3735                 length = sizeof(struct scsi_report_key_data_asf);
 3736                 break;
 3737         case DVD_REPORT_RPC:
 3738                 length = sizeof(struct scsi_report_key_data_rpc);
 3739                 break;
 3740         case DVD_INVALIDATE_AGID:
 3741                 length = 0;
 3742                 break;
 3743         default:
 3744                 return (EINVAL);
 3745         }
 3746 
 3747         if (length != 0) {
 3748                 databuf = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
 3749         } else
 3750                 databuf = NULL;
 3751 
 3752         cam_periph_lock(periph);
 3753         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3754 
 3755         scsi_report_key(&ccb->csio,
 3756                         /* retries */ cd_retry_count,
 3757                         /* cbfcnp */ NULL,
 3758                         /* tag_action */ MSG_SIMPLE_Q_TAG,
 3759                         /* lba */ lba,
 3760                         /* agid */ authinfo->agid,
 3761                         /* key_format */ authinfo->format,
 3762                         /* data_ptr */ databuf,
 3763                         /* dxfer_len */ length,
 3764                         /* sense_len */ SSD_FULL_SIZE,
 3765                         /* timeout */ 50000);
 3766 
 3767         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3768                          /*sense_flags*/SF_RETRY_UA);
 3769 
 3770         if (error != 0)
 3771                 goto bailout;
 3772 
 3773         if (ccb->csio.resid != 0) {
 3774                 xpt_print(periph->path, "warning, residual for report key "
 3775                     "command is %d\n", ccb->csio.resid);
 3776         }
 3777 
 3778         switch(authinfo->format) {
 3779         case DVD_REPORT_AGID: {
 3780                 struct scsi_report_key_data_agid *agid_data;
 3781 
 3782                 agid_data = (struct scsi_report_key_data_agid *)databuf;
 3783 
 3784                 authinfo->agid = (agid_data->agid & RKD_AGID_MASK) >>
 3785                         RKD_AGID_SHIFT;
 3786                 break;
 3787         }
 3788         case DVD_REPORT_CHALLENGE: {
 3789                 struct scsi_report_key_data_challenge *chal_data;
 3790 
 3791                 chal_data = (struct scsi_report_key_data_challenge *)databuf;
 3792 
 3793                 bcopy(chal_data->challenge_key, authinfo->keychal,
 3794                       min(sizeof(chal_data->challenge_key),
 3795                           sizeof(authinfo->keychal)));
 3796                 break;
 3797         }
 3798         case DVD_REPORT_KEY1: {
 3799                 struct scsi_report_key_data_key1_key2 *key1_data;
 3800 
 3801                 key1_data = (struct scsi_report_key_data_key1_key2 *)databuf;
 3802 
 3803                 bcopy(key1_data->key1, authinfo->keychal,
 3804                       min(sizeof(key1_data->key1), sizeof(authinfo->keychal)));
 3805                 break;
 3806         }
 3807         case DVD_REPORT_TITLE_KEY: {
 3808                 struct scsi_report_key_data_title *title_data;
 3809 
 3810                 title_data = (struct scsi_report_key_data_title *)databuf;
 3811 
 3812                 authinfo->cpm = (title_data->byte0 & RKD_TITLE_CPM) >>
 3813                         RKD_TITLE_CPM_SHIFT;
 3814                 authinfo->cp_sec = (title_data->byte0 & RKD_TITLE_CP_SEC) >>
 3815                         RKD_TITLE_CP_SEC_SHIFT;
 3816                 authinfo->cgms = (title_data->byte0 & RKD_TITLE_CMGS_MASK) >>
 3817                         RKD_TITLE_CMGS_SHIFT;
 3818                 bcopy(title_data->title_key, authinfo->keychal,
 3819                       min(sizeof(title_data->title_key),
 3820                           sizeof(authinfo->keychal)));
 3821                 break;
 3822         }
 3823         case DVD_REPORT_ASF: {
 3824                 struct scsi_report_key_data_asf *asf_data;
 3825 
 3826                 asf_data = (struct scsi_report_key_data_asf *)databuf;
 3827 
 3828                 authinfo->asf = asf_data->success & RKD_ASF_SUCCESS;
 3829                 break;
 3830         }
 3831         case DVD_REPORT_RPC: {
 3832                 struct scsi_report_key_data_rpc *rpc_data;
 3833 
 3834                 rpc_data = (struct scsi_report_key_data_rpc *)databuf;
 3835 
 3836                 authinfo->reg_type = (rpc_data->byte4 & RKD_RPC_TYPE_MASK) >>
 3837                         RKD_RPC_TYPE_SHIFT;
 3838                 authinfo->vend_rsts =
 3839                         (rpc_data->byte4 & RKD_RPC_VENDOR_RESET_MASK) >>
 3840                         RKD_RPC_VENDOR_RESET_SHIFT;
 3841                 authinfo->user_rsts = rpc_data->byte4 & RKD_RPC_USER_RESET_MASK;
 3842                 authinfo->region = rpc_data->region_mask;
 3843                 authinfo->rpc_scheme = rpc_data->rpc_scheme1;
 3844                 break;
 3845         }
 3846         case DVD_INVALIDATE_AGID:
 3847                 break;
 3848         default:
 3849                 /* This should be impossible, since we checked above */
 3850                 error = EINVAL;
 3851                 goto bailout;
 3852                 break; /* NOTREACHED */
 3853         }
 3854 
 3855 bailout:
 3856         xpt_release_ccb(ccb);
 3857         cam_periph_unlock(periph);
 3858 
 3859         if (databuf != NULL)
 3860                 free(databuf, M_DEVBUF);
 3861 
 3862         return(error);
 3863 }
 3864 
 3865 static int
 3866 cdsendkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
 3867 {
 3868         union ccb *ccb;
 3869         u_int8_t *databuf;
 3870         int length;
 3871         int error;
 3872 
 3873         error = 0;
 3874         databuf = NULL;
 3875 
 3876         switch(authinfo->format) {
 3877         case DVD_SEND_CHALLENGE: {
 3878                 struct scsi_report_key_data_challenge *challenge_data;
 3879 
 3880                 length = sizeof(*challenge_data);
 3881 
 3882                 challenge_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
 3883 
 3884                 databuf = (u_int8_t *)challenge_data;
 3885 
 3886                 scsi_ulto2b(length - sizeof(challenge_data->data_len),
 3887                             challenge_data->data_len);
 3888 
 3889                 bcopy(authinfo->keychal, challenge_data->challenge_key,
 3890                       min(sizeof(authinfo->keychal),
 3891                           sizeof(challenge_data->challenge_key)));
 3892                 break;
 3893         }
 3894         case DVD_SEND_KEY2: {
 3895                 struct scsi_report_key_data_key1_key2 *key2_data;
 3896 
 3897                 length = sizeof(*key2_data);
 3898 
 3899                 key2_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
 3900 
 3901                 databuf = (u_int8_t *)key2_data;
 3902 
 3903                 scsi_ulto2b(length - sizeof(key2_data->data_len),
 3904                             key2_data->data_len);
 3905 
 3906                 bcopy(authinfo->keychal, key2_data->key1,
 3907                       min(sizeof(authinfo->keychal), sizeof(key2_data->key1)));
 3908 
 3909                 break;
 3910         }
 3911         case DVD_SEND_RPC: {
 3912                 struct scsi_send_key_data_rpc *rpc_data;
 3913 
 3914                 length = sizeof(*rpc_data);
 3915 
 3916                 rpc_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
 3917 
 3918                 databuf = (u_int8_t *)rpc_data;
 3919 
 3920                 scsi_ulto2b(length - sizeof(rpc_data->data_len),
 3921                             rpc_data->data_len);
 3922 
 3923                 rpc_data->region_code = authinfo->region;
 3924                 break;
 3925         }
 3926         default:
 3927                 return (EINVAL);
 3928         }
 3929 
 3930         cam_periph_lock(periph);
 3931         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 3932 
 3933         scsi_send_key(&ccb->csio,
 3934                       /* retries */ cd_retry_count,
 3935                       /* cbfcnp */ NULL,
 3936                       /* tag_action */ MSG_SIMPLE_Q_TAG,
 3937                       /* agid */ authinfo->agid,
 3938                       /* key_format */ authinfo->format,
 3939                       /* data_ptr */ databuf,
 3940                       /* dxfer_len */ length,
 3941                       /* sense_len */ SSD_FULL_SIZE,
 3942                       /* timeout */ 50000);
 3943 
 3944         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 3945                          /*sense_flags*/SF_RETRY_UA);
 3946 
 3947         xpt_release_ccb(ccb);
 3948         cam_periph_unlock(periph);
 3949 
 3950         if (databuf != NULL)
 3951                 free(databuf, M_DEVBUF);
 3952 
 3953         return(error);
 3954 }
 3955 
 3956 static int
 3957 cdreaddvdstructure(struct cam_periph *periph, struct dvd_struct *dvdstruct)
 3958 {
 3959         union ccb *ccb;
 3960         u_int8_t *databuf;
 3961         u_int32_t address;
 3962         int error;
 3963         int length;
 3964 
 3965         error = 0;
 3966         databuf = NULL;
 3967         /* The address is reserved for many of the formats */
 3968         address = 0;
 3969 
 3970         switch(dvdstruct->format) {
 3971         case DVD_STRUCT_PHYSICAL:
 3972                 length = sizeof(struct scsi_read_dvd_struct_data_physical);
 3973                 break;
 3974         case DVD_STRUCT_COPYRIGHT:
 3975                 length = sizeof(struct scsi_read_dvd_struct_data_copyright);
 3976                 break;
 3977         case DVD_STRUCT_DISCKEY:
 3978                 length = sizeof(struct scsi_read_dvd_struct_data_disc_key);
 3979                 break;
 3980         case DVD_STRUCT_BCA:
 3981                 length = sizeof(struct scsi_read_dvd_struct_data_bca);
 3982                 break;
 3983         case DVD_STRUCT_MANUFACT:
 3984                 length = sizeof(struct scsi_read_dvd_struct_data_manufacturer);
 3985                 break;
 3986         case DVD_STRUCT_CMI:
 3987                 return (ENODEV);
 3988         case DVD_STRUCT_PROTDISCID:
 3989                 length = sizeof(struct scsi_read_dvd_struct_data_prot_discid);
 3990                 break;
 3991         case DVD_STRUCT_DISCKEYBLOCK:
 3992                 length = sizeof(struct scsi_read_dvd_struct_data_disc_key_blk);
 3993                 break;
 3994         case DVD_STRUCT_DDS:
 3995                 length = sizeof(struct scsi_read_dvd_struct_data_dds);
 3996                 break;
 3997         case DVD_STRUCT_MEDIUM_STAT:
 3998                 length = sizeof(struct scsi_read_dvd_struct_data_medium_status);
 3999                 break;
 4000         case DVD_STRUCT_SPARE_AREA:
 4001                 length = sizeof(struct scsi_read_dvd_struct_data_spare_area);
 4002                 break;
 4003         case DVD_STRUCT_RMD_LAST:
 4004                 return (ENODEV);
 4005         case DVD_STRUCT_RMD_RMA:
 4006                 return (ENODEV);
 4007         case DVD_STRUCT_PRERECORDED:
 4008                 length = sizeof(struct scsi_read_dvd_struct_data_leadin);
 4009                 break;
 4010         case DVD_STRUCT_UNIQUEID:
 4011                 length = sizeof(struct scsi_read_dvd_struct_data_disc_id);
 4012                 break;
 4013         case DVD_STRUCT_DCB:
 4014                 return (ENODEV);
 4015         case DVD_STRUCT_LIST:
 4016                 /*
 4017                  * This is the maximum allocation length for the READ DVD
 4018                  * STRUCTURE command.  There's nothing in the MMC3 spec
 4019                  * that indicates a limit in the amount of data that can
 4020                  * be returned from this call, other than the limits
 4021                  * imposed by the 2-byte length variables.
 4022                  */
 4023                 length = 65535;
 4024                 break;
 4025         default:
 4026                 return (EINVAL);
 4027         }
 4028 
 4029         if (length != 0) {
 4030                 databuf = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO);
 4031         } else
 4032                 databuf = NULL;
 4033 
 4034         cam_periph_lock(periph);
 4035         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 4036 
 4037         scsi_read_dvd_structure(&ccb->csio,
 4038                                 /* retries */ cd_retry_count,
 4039                                 /* cbfcnp */ NULL,
 4040                                 /* tag_action */ MSG_SIMPLE_Q_TAG,
 4041                                 /* lba */ address,
 4042                                 /* layer_number */ dvdstruct->layer_num,
 4043                                 /* key_format */ dvdstruct->format,
 4044                                 /* agid */ dvdstruct->agid,
 4045                                 /* data_ptr */ databuf,
 4046                                 /* dxfer_len */ length,
 4047                                 /* sense_len */ SSD_FULL_SIZE,
 4048                                 /* timeout */ 50000);
 4049 
 4050         error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
 4051                          /*sense_flags*/SF_RETRY_UA);
 4052 
 4053         if (error != 0)
 4054                 goto bailout;
 4055 
 4056         switch(dvdstruct->format) {
 4057         case DVD_STRUCT_PHYSICAL: {
 4058                 struct scsi_read_dvd_struct_data_layer_desc *inlayer;
 4059                 struct dvd_layer *outlayer;
 4060                 struct scsi_read_dvd_struct_data_physical *phys_data;
 4061 
 4062                 phys_data =
 4063                         (struct scsi_read_dvd_struct_data_physical *)databuf;
 4064                 inlayer = &phys_data->layer_desc;
 4065                 outlayer = (struct dvd_layer *)&dvdstruct->data;
 4066 
 4067                 dvdstruct->length = sizeof(*inlayer);
 4068 
 4069                 outlayer->book_type = (inlayer->book_type_version &
 4070                         RDSD_BOOK_TYPE_MASK) >> RDSD_BOOK_TYPE_SHIFT;
 4071                 outlayer->book_version = (inlayer->book_type_version &
 4072                         RDSD_BOOK_VERSION_MASK);
 4073                 outlayer->disc_size = (inlayer->disc_size_max_rate &
 4074                         RDSD_DISC_SIZE_MASK) >> RDSD_DISC_SIZE_SHIFT;
 4075                 outlayer->max_rate = (inlayer->disc_size_max_rate &
 4076                         RDSD_MAX_RATE_MASK);
 4077                 outlayer->nlayers = (inlayer->layer_info &
 4078                         RDSD_NUM_LAYERS_MASK) >> RDSD_NUM_LAYERS_SHIFT;
 4079                 outlayer->track_path = (inlayer->layer_info &
 4080                         RDSD_TRACK_PATH_MASK) >> RDSD_TRACK_PATH_SHIFT;
 4081                 outlayer->layer_type = (inlayer->layer_info &
 4082                         RDSD_LAYER_TYPE_MASK);
 4083                 outlayer->linear_density = (inlayer->density &
 4084                         RDSD_LIN_DENSITY_MASK) >> RDSD_LIN_DENSITY_SHIFT;
 4085                 outlayer->track_density = (inlayer->density &
 4086                         RDSD_TRACK_DENSITY_MASK);
 4087                 outlayer->bca = (inlayer->bca & RDSD_BCA_MASK) >>
 4088                         RDSD_BCA_SHIFT;
 4089                 outlayer->start_sector = scsi_3btoul(inlayer->main_data_start);
 4090                 outlayer->end_sector = scsi_3btoul(inlayer->main_data_end);
 4091                 outlayer->end_sector_l0 =
 4092                         scsi_3btoul(inlayer->end_sector_layer0);
 4093                 break;
 4094         }
 4095         case DVD_STRUCT_COPYRIGHT: {
 4096                 struct scsi_read_dvd_struct_data_copyright *copy_data;
 4097 
 4098                 copy_data = (struct scsi_read_dvd_struct_data_copyright *)
 4099                         databuf;
 4100 
 4101                 dvdstruct->cpst = copy_data->cps_type;
 4102                 dvdstruct->rmi = copy_data->region_info;
 4103                 dvdstruct->length = 0;
 4104 
 4105                 break;
 4106         }
 4107         default:
 4108                 /*
 4109                  * Tell the user what the overall length is, no matter
 4110                  * what we can actually fit in the data buffer.
 4111                  */
 4112                 dvdstruct->length = length - ccb->csio.resid -
 4113                         sizeof(struct scsi_read_dvd_struct_data_header);
 4114 
 4115                 /*
 4116                  * But only actually copy out the smaller of what we read
 4117                  * in or what the structure can take.
 4118                  */
 4119                 bcopy(databuf + sizeof(struct scsi_read_dvd_struct_data_header),
 4120                       dvdstruct->data,
 4121                       min(sizeof(dvdstruct->data), dvdstruct->length));
 4122                 break;
 4123         }
 4124 
 4125 bailout:
 4126         xpt_release_ccb(ccb);
 4127         cam_periph_unlock(periph);
 4128 
 4129         if (databuf != NULL)
 4130                 free(databuf, M_DEVBUF);
 4131 
 4132         return(error);
 4133 }
 4134 
 4135 void
 4136 scsi_report_key(struct ccb_scsiio *csio, u_int32_t retries,
 4137                 void (*cbfcnp)(struct cam_periph *, union ccb *),
 4138                 u_int8_t tag_action, u_int32_t lba, u_int8_t agid,
 4139                 u_int8_t key_format, u_int8_t *data_ptr, u_int32_t dxfer_len,
 4140                 u_int8_t sense_len, u_int32_t timeout)
 4141 {
 4142         struct scsi_report_key *scsi_cmd;
 4143 
 4144         scsi_cmd = (struct scsi_report_key *)&csio->cdb_io.cdb_bytes;
 4145         bzero(scsi_cmd, sizeof(*scsi_cmd));
 4146         scsi_cmd->opcode = REPORT_KEY;
 4147         scsi_ulto4b(lba, scsi_cmd->lba);
 4148         scsi_ulto2b(dxfer_len, scsi_cmd->alloc_len);
 4149         scsi_cmd->agid_keyformat = (agid << RK_KF_AGID_SHIFT) |
 4150                 (key_format & RK_KF_KEYFORMAT_MASK);
 4151 
 4152         cam_fill_csio(csio,
 4153                       retries,
 4154                       cbfcnp,
 4155                       /*flags*/ (dxfer_len == 0) ? CAM_DIR_NONE : CAM_DIR_IN,
 4156                       tag_action,
 4157                       /*data_ptr*/ data_ptr,
 4158                       /*dxfer_len*/ dxfer_len,
 4159                       sense_len,
 4160                       sizeof(*scsi_cmd),
 4161                       timeout);
 4162 }
 4163 
 4164 void
 4165 scsi_send_key(struct ccb_scsiio *csio, u_int32_t retries,
 4166               void (*cbfcnp)(struct cam_periph *, union ccb *),
 4167               u_int8_t tag_action, u_int8_t agid, u_int8_t key_format,
 4168               u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
 4169               u_int32_t timeout)
 4170 {
 4171         struct scsi_send_key *scsi_cmd;
 4172 
 4173         scsi_cmd = (struct scsi_send_key *)&csio->cdb_io.cdb_bytes;
 4174         bzero(scsi_cmd, sizeof(*scsi_cmd));
 4175         scsi_cmd->opcode = SEND_KEY;
 4176 
 4177         scsi_ulto2b(dxfer_len, scsi_cmd->param_len);
 4178         scsi_cmd->agid_keyformat = (agid << RK_KF_AGID_SHIFT) |
 4179                 (key_format & RK_KF_KEYFORMAT_MASK);
 4180 
 4181         cam_fill_csio(csio,
 4182                       retries,
 4183                       cbfcnp,
 4184                       /*flags*/ CAM_DIR_OUT,
 4185                       tag_action,
 4186                       /*data_ptr*/ data_ptr,
 4187                       /*dxfer_len*/ dxfer_len,
 4188                       sense_len,
 4189                       sizeof(*scsi_cmd),
 4190                       timeout);
 4191 }
 4192 
 4193 void
 4194 scsi_read_dvd_structure(struct ccb_scsiio *csio, u_int32_t retries,
 4195                         void (*cbfcnp)(struct cam_periph *, union ccb *),
 4196                         u_int8_t tag_action, u_int32_t address,
 4197                         u_int8_t layer_number, u_int8_t format, u_int8_t agid,
 4198                         u_int8_t *data_ptr, u_int32_t dxfer_len,
 4199                         u_int8_t sense_len, u_int32_t timeout)
 4200 {
 4201         struct scsi_read_dvd_structure *scsi_cmd;
 4202 
 4203         scsi_cmd = (struct scsi_read_dvd_structure *)&csio->cdb_io.cdb_bytes;
 4204         bzero(scsi_cmd, sizeof(*scsi_cmd));
 4205         scsi_cmd->opcode = READ_DVD_STRUCTURE;
 4206 
 4207         scsi_ulto4b(address, scsi_cmd->address);
 4208         scsi_cmd->layer_number = layer_number;
 4209         scsi_cmd->format = format;
 4210         scsi_ulto2b(dxfer_len, scsi_cmd->alloc_len);
 4211         /* The AGID is the top two bits of this byte */
 4212         scsi_cmd->agid = agid << 6;
 4213 
 4214         cam_fill_csio(csio,
 4215                       retries,
 4216                       cbfcnp,
 4217                       /*flags*/ CAM_DIR_IN,
 4218                       tag_action,
 4219                       /*data_ptr*/ data_ptr,
 4220                       /*dxfer_len*/ dxfer_len,
 4221                       sense_len,
 4222                       sizeof(*scsi_cmd),
 4223                       timeout);
 4224 }
 4225 
 4226 void
 4227 scsi_read_toc(struct ccb_scsiio *csio, uint32_t retries,
 4228               void (*cbfcnp)(struct cam_periph *, union ccb *),
 4229               uint8_t tag_action, uint8_t byte1_flags, uint8_t format,
 4230               uint8_t track, uint8_t *data_ptr, uint32_t dxfer_len,
 4231               int sense_len, int timeout)
 4232 {
 4233         struct scsi_read_toc *scsi_cmd;
 4234 
 4235         scsi_cmd = (struct scsi_read_toc *)&csio->cdb_io.cdb_bytes;
 4236         bzero(scsi_cmd, sizeof(*scsi_cmd));
 4237         scsi_cmd->op_code = READ_TOC;
 4238 
 4239         /*
 4240          * The structure is counting from 1, the function counting from 0.
 4241          * The spec counts from 0.  In MMC-6, there is only one flag, the
 4242          * MSF flag.  But we put the whole byte in for a bit a future-proofing.
 4243          */
 4244         scsi_cmd->byte2 = byte1_flags;
 4245         scsi_cmd->format = format;
 4246         scsi_cmd->from_track = track;
 4247         scsi_ulto2b(dxfer_len, scsi_cmd->data_len);
 4248 
 4249         cam_fill_csio(csio,
 4250                       /* retries */ retries,
 4251                       /* cbfcnp */ cbfcnp,
 4252                       /* flags */ CAM_DIR_IN,
 4253                       /* tag_action */ tag_action,
 4254                       /* data_ptr */ data_ptr,
 4255                       /* dxfer_len */ dxfer_len,
 4256                       /* sense_len */ sense_len,
 4257                       sizeof(*scsi_cmd),
 4258                       /* timeout */ timeout);
 4259 }

Cache object: ade68815242afd4d2000e380cd552430


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