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


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

FreeBSD/Linux Kernel Cross Reference
sys/cam/scsi/scsi_cd.c

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

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

Cache object: a5ca3a544689b563940585f853111a4f


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