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

Cache object: 1562f0db99b0374206af3d360c6bc4f3


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