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