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

Cache object: 54d2a670abfa6452526829e839c7d788


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