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