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