2 * Copyright (c) 1997 Justin T. Gibbs.
3 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2003, 2003 Kenneth D. Merry.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
27 * $FreeBSD: src/sys/cam/scsi/scsi_cd.c,v 1.31.2.16 2003/10/21 22:26:11 thomas Exp $
30 * Portions of this driver taken from the original FreeBSD cd driver.
31 * Written by Julian Elischer (julian@tfs.com)
32 * for TRW Financial Systems for use under the MACH(2.5) operating system.
34 * TRW Financial Systems, in accordance with their agreement with Carnegie
35 * Mellon University, makes this software available to CMU to distribute
36 * or use in any manner that they see fit as long as this message is kept with
37 * the software. For this reason TFS also grants any other persons or
38 * organisations permission to use or modify this software.
40 * TFS supplies this software to be publicly redistributed
41 * on the understanding that TFS is not responsible for the correct
42 * functioning of this software in any circumstances.
44 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
46 * from: cd.c,v 1.83 1997/05/04 15:24:22 joerg Exp $
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/kernel.h>
58 #include <sys/dtype.h>
59 #include <sys/malloc.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>
67 #include <sys/camlib.h>
73 #include "../cam_ccb.h"
74 #include "../cam_extend.h"
75 #include "../cam_periph.h"
76 #include "../cam_xpt_periph.h"
77 #include "../cam_queue.h"
78 #include "../cam_sim.h"
80 #include "scsi_message.h"
84 #define LEADOUT 0xaa /* leadout toc entry */
94 CD_Q_BCD_TRACKS
= 0x02,
95 CD_Q_NO_CHANGER
= 0x04,
97 CD_Q_10_BYTE_ONLY
= 0x10
101 CD_FLAG_INVALID
= 0x0001,
102 CD_FLAG_NEW_DISC
= 0x0002,
103 CD_FLAG_DISC_LOCKED
= 0x0004,
104 CD_FLAG_DISC_REMOVABLE
= 0x0008,
105 CD_FLAG_TAGGED_QUEUING
= 0x0010,
106 CD_FLAG_CHANGER
= 0x0040,
107 CD_FLAG_ACTIVE
= 0x0080,
108 CD_FLAG_SCHED_ON_COMP
= 0x0100,
109 CD_FLAG_RETRY_UA
= 0x0200,
110 CD_FLAG_VALID_MEDIA
= 0x0400,
111 CD_FLAG_VALID_TOC
= 0x0800,
112 CD_FLAG_SCTX_INIT
= 0x1000,
113 CD_FLAG_OPEN
= 0x2000,
114 CD_FLAG_CAP_MUTE
= 0x4000
118 CD_CCB_POLLED
= 0x00,
120 CD_CCB_BUFFER_IO
= 0x02,
121 CD_CCB_WAITING
= 0x03,
122 CD_CCB_TYPE_MASK
= 0x0F,
123 CD_CCB_RETRY_UA
= 0x10
127 CHANGER_TIMEOUT_SCHED
= 0x01,
128 CHANGER_SHORT_TMOUT_SCHED
= 0x02,
129 CHANGER_MANUAL_CALL
= 0x04,
130 CHANGER_NEED_TIMEOUT
= 0x08
133 #define ccb_state ppriv_field0
134 #define ccb_bio ppriv_ptr1
137 struct ioc_toc_header header
;
138 struct cd_toc_entry entries
[100];
141 struct cd_toc_single
{
142 struct ioc_toc_header header
;
143 struct cd_toc_entry entry
;
154 volatile cd_flags flags
;
155 struct bio_queue_head bio_queue
;
156 LIST_HEAD(, ccb_hdr
) pending_ccbs
;
157 struct cd_params params
;
161 struct devstat device_stats
;
162 STAILQ_ENTRY(cd_softc
) changer_links
;
163 struct cdchanger
*changer
;
165 struct cam_periph
*periph
;
166 int minimum_command_size
;
167 int outstanding_cmds
;
168 struct task sysctl_task
;
169 struct sysctl_ctx_list sysctl_ctx
;
170 struct sysctl_oid
*sysctl_tree
;
171 STAILQ_HEAD(, cd_mode_params
) mode_queue
;
172 struct cd_tocdata toc
;
175 struct cd_page_sizes
{
180 static struct cd_page_sizes cd_page_size_table
[] =
182 { AUDIO_PAGE
, sizeof(struct cd_audio_page
)}
185 struct cd_quirk_entry
{
186 struct scsi_inquiry_pattern inq_pat
;
191 * The changer quirk entries aren't strictly necessary. Basically, what
192 * they do is tell cdregister() up front that a device is a changer.
193 * Otherwise, it will figure that fact out once it sees a LUN on the device
194 * that is greater than 0. If it is known up front that a device is a changer,
195 * all I/O to the device will go through the changer scheduling routines, as
196 * opposed to the "normal" CD code.
198 * NOTE ON 10_BYTE_ONLY quirks: Any 10_BYTE_ONLY quirks MUST be because
199 * your device hangs when it gets a 10 byte command. Adding a quirk just
200 * to get rid of the informative diagnostic message is not acceptable. All
201 * 10_BYTE_ONLY quirks must be documented in full in a PR (which should be
202 * referenced in a comment along with the quirk) , and must be approved by
203 * ken@FreeBSD.org. Any quirks added that don't adhere to this policy may
204 * be removed until the submitter can explain why they are needed.
205 * 10_BYTE_ONLY quirks will be removed (as they will no longer be necessary)
206 * when the CAM_NEW_TRAN_CODE work is done.
208 static struct cd_quirk_entry cd_quirk_table
[] =
211 { T_CDROM
, SIP_MEDIA_REMOVABLE
, "NRC", "MBR-7", "*"},
212 /*quirks*/ CD_Q_CHANGER
215 { T_CDROM
, SIP_MEDIA_REMOVABLE
, "PIONEER", "CD-ROM DRM*",
216 "*"}, /* quirks */ CD_Q_CHANGER
219 { T_CDROM
, SIP_MEDIA_REMOVABLE
, "NAKAMICH", "MJ-*", "*"},
220 /* quirks */ CD_Q_CHANGER
223 { T_CDROM
, SIP_MEDIA_REMOVABLE
, "CHINON", "CD-ROM CDS-535","*"},
224 /* quirks */ CD_Q_BCD_TRACKS
228 static d_open_t cdopen
;
229 static d_close_t cdclose
;
230 static d_ioctl_t cdioctl
;
231 static d_strategy_t cdstrategy
;
233 static periph_init_t cdinit
;
234 static periph_ctor_t cdregister
;
235 static periph_dtor_t cdcleanup
;
236 static periph_start_t cdstart
;
237 static periph_oninv_t cdoninvalidate
;
238 static void cdasync(void *callback_arg
, u_int32_t code
,
239 struct cam_path
*path
, void *arg
);
240 static int cdcmdsizesysctl(SYSCTL_HANDLER_ARGS
);
241 static void cdshorttimeout(void *arg
);
242 static void cdschedule(struct cam_periph
*periph
, int priority
);
243 static void cdrunchangerqueue(void *arg
);
244 static void cdchangerschedule(struct cd_softc
*softc
);
245 static int cdrunccb(union ccb
*ccb
,
246 int (*error_routine
)(union ccb
*ccb
,
248 u_int32_t sense_flags
),
249 u_int32_t cam_flags
, u_int32_t sense_flags
);
250 static union ccb
*cdgetccb(struct cam_periph
*periph
,
252 static void cddone(struct cam_periph
*periph
,
253 union ccb
*start_ccb
);
254 static int cderror(union ccb
*ccb
, u_int32_t cam_flags
,
255 u_int32_t sense_flags
);
256 static union cd_pages
*cdgetpage(struct cd_mode_params
*mode_params
);
257 static int cdgetpagesize(int page_num
);
258 static void cdprevent(struct cam_periph
*periph
, int action
);
259 static int cdcheckmedia(struct cam_periph
*periph
);
260 static int cdsize(struct cam_periph
*periph
, u_int32_t
*size
);
261 static int cd6byteworkaround(union ccb
*ccb
);
262 static int cdreadtoc(struct cam_periph
*periph
, u_int32_t mode
,
263 u_int32_t start
, u_int8_t
*data
,
264 u_int32_t len
, u_int32_t sense_flags
);
265 static int cdgetmode(struct cam_periph
*periph
,
266 struct cd_mode_params
*data
, u_int32_t page
);
267 static int cdsetmode(struct cam_periph
*periph
,
268 struct cd_mode_params
*data
);
269 static int cdplay(struct cam_periph
*periph
, u_int32_t blk
,
271 static int cdreadsubchannel(struct cam_periph
*periph
,
272 u_int32_t mode
, u_int32_t format
,
274 struct cd_sub_channel_info
*data
,
276 static int cdplaymsf(struct cam_periph
*periph
, u_int32_t startm
,
277 u_int32_t starts
, u_int32_t startf
,
278 u_int32_t endm
, u_int32_t ends
,
280 static int cdplaytracks(struct cam_periph
*periph
,
281 u_int32_t strack
, u_int32_t sindex
,
282 u_int32_t etrack
, u_int32_t eindex
);
283 static int cdpause(struct cam_periph
*periph
, u_int32_t go
);
284 static int cdstopunit(struct cam_periph
*periph
, u_int32_t eject
);
285 static int cdstartunit(struct cam_periph
*periph
, int load
);
286 static int cdsetspeed(struct cam_periph
*periph
,
287 u_int32_t rdspeed
, u_int32_t wrspeed
);
288 static int cdreportkey(struct cam_periph
*periph
,
289 struct dvd_authinfo
*authinfo
);
290 static int cdsendkey(struct cam_periph
*periph
,
291 struct dvd_authinfo
*authinfo
);
292 static int cdreaddvdstructure(struct cam_periph
*periph
,
293 struct dvd_struct
*dvdstruct
);
295 static struct periph_driver cddriver
=
298 TAILQ_HEAD_INITIALIZER(cddriver
.units
), /* generation */ 0
301 PERIPHDRIVER_DECLARE(cd
, cddriver
);
303 static struct dev_ops cd_ops
= {
304 { "cd", 0, D_DISK
| D_MPSAFE
},
308 .d_write
= physwrite
,
310 .d_strategy
= cdstrategy
313 static struct extend_array
*cdperiphs
;
315 #ifndef CHANGER_MIN_BUSY_SECONDS
316 #define CHANGER_MIN_BUSY_SECONDS 5
318 #ifndef CHANGER_MAX_BUSY_SECONDS
319 #define CHANGER_MAX_BUSY_SECONDS 15
322 static int changer_min_busy_seconds
= CHANGER_MIN_BUSY_SECONDS
;
323 static int changer_max_busy_seconds
= CHANGER_MAX_BUSY_SECONDS
;
325 SYSCTL_NODE(_kern_cam
, OID_AUTO
, cd
, CTLFLAG_RD
, 0, "CAM CDROM driver");
326 SYSCTL_NODE(_kern_cam_cd
, OID_AUTO
, changer
, CTLFLAG_RD
, 0, "CD Changer");
327 SYSCTL_INT(_kern_cam_cd_changer
, OID_AUTO
, min_busy_seconds
, CTLFLAG_RW
,
328 &changer_min_busy_seconds
, 0, "Minimum changer scheduling quantum");
329 TUNABLE_INT("kern.cam.cd.changer.min_busy_seconds", &changer_min_busy_seconds
);
330 SYSCTL_INT(_kern_cam_cd_changer
, OID_AUTO
, max_busy_seconds
, CTLFLAG_RW
,
331 &changer_max_busy_seconds
, 0, "Maximum changer scheduling quantum");
332 TUNABLE_INT("kern.cam.cd.changer.max_busy_seconds", &changer_max_busy_seconds
);
336 target_id_t target_id
;
339 struct timeval start_time
;
340 struct cd_softc
*cur_device
;
341 struct callout short_handle
;
342 struct callout long_handle
;
343 volatile cd_changer_flags flags
;
344 STAILQ_ENTRY(cdchanger
) changer_links
;
345 STAILQ_HEAD(chdevlist
, cd_softc
) chluns
;
348 static struct lock changerq_lock
;
349 static STAILQ_HEAD(changerlist
, cdchanger
) changerq
;
350 static int num_changers
;
352 MALLOC_DEFINE(M_SCSICD
, "scsi_cd", "scsi_cd buffers");
359 lockinit(&changerq_lock
, "cdchangerq", 0, LK_CANRECURSE
);
360 STAILQ_INIT(&changerq
);
363 * Create our extend array for storing the devices we attach to.
365 cdperiphs
= cam_extend_new();
366 if (cdperiphs
== NULL
) {
367 kprintf("cd: Failed to alloc extend array!\n");
372 * Install a global async callback. This callback will
373 * receive async callbacks like "new device found".
375 status
= xpt_register_async(AC_FOUND_DEVICE
, cdasync
, NULL
, NULL
);
377 if (status
!= CAM_REQ_CMP
) {
378 kprintf("cd: Failed to attach master async callback "
379 "due to status 0x%x!\n", status
);
384 cdoninvalidate(struct cam_periph
*periph
)
386 struct cd_softc
*softc
;
390 softc
= (struct cd_softc
*)periph
->softc
;
393 * De-register any async callbacks.
395 xpt_register_async(0, cdasync
, periph
, periph
->path
);
397 softc
->flags
|= CD_FLAG_INVALID
;
400 * Return all queued I/O with ENXIO.
401 * XXX Handle any transactions queued to the card
402 * with XPT_ABORT_CCB.
404 while ((q_bio
= bioq_takefirst(&softc
->bio_queue
)) != NULL
) {
405 q_bp
= q_bio
->bio_buf
;
406 q_bp
->b_resid
= q_bp
->b_bcount
;
407 q_bp
->b_error
= ENXIO
;
408 q_bp
->b_flags
|= B_ERROR
;
413 * If this device is part of a changer, and it was scheduled
414 * to run, remove it from the run queue since we just nuked
415 * all of its scheduled I/O.
417 if ((softc
->flags
& CD_FLAG_CHANGER
)
418 && (softc
->pinfo
.index
!= CAM_UNQUEUED_INDEX
))
419 camq_remove(&softc
->changer
->devq
, softc
->pinfo
.index
);
421 xpt_print(periph
->path
, "lost device\n");
425 cdcleanup(struct cam_periph
*periph
)
427 struct cd_softc
*softc
;
429 softc
= (struct cd_softc
*)periph
->softc
;
431 xpt_print(periph
->path
, "removing device entry\n");
433 if ((softc
->flags
& CD_FLAG_SCTX_INIT
) != 0
434 && sysctl_ctx_free(&softc
->sysctl_ctx
) != 0) {
435 xpt_print(periph
->path
, "can't remove sysctl context\n");
439 * In the queued, non-active case, the device in question
440 * has already been removed from the changer run queue. Since this
441 * device is active, we need to de-activate it, and schedule
442 * another device to run. (if there is another one to run)
444 if ((softc
->flags
& CD_FLAG_CHANGER
)
445 && (softc
->flags
& CD_FLAG_ACTIVE
)) {
448 * The purpose of the short timeout is soley to determine
449 * whether the current device has finished or not. Well,
450 * since we're removing the active device, we know that it
451 * is finished. So, get rid of the short timeout.
452 * Otherwise, if we're in the time period before the short
453 * timeout fires, and there are no other devices in the
454 * queue to run, there won't be any other device put in the
455 * active slot. i.e., when we call cdrunchangerqueue()
456 * below, it won't do anything. Then, when the short
457 * timeout fires, it'll look at the "current device", which
458 * we are free below, and possibly panic the kernel on a
459 * bogus pointer reference.
461 * The long timeout doesn't really matter, since we
462 * decrement the qfrozen_cnt to indicate that there is
463 * nothing in the active slot now. Therefore, there won't
464 * be any bogus pointer references there.
466 if (softc
->changer
->flags
& CHANGER_SHORT_TMOUT_SCHED
) {
467 callout_stop(&softc
->changer
->short_handle
);
468 softc
->changer
->flags
&= ~CHANGER_SHORT_TMOUT_SCHED
;
470 softc
->changer
->devq
.qfrozen_cnt
--;
471 softc
->changer
->flags
|= CHANGER_MANUAL_CALL
;
472 cdrunchangerqueue(softc
->changer
);
476 * If we're removing the last device on the changer, go ahead and
477 * remove the changer device structure.
479 if ((softc
->flags
& CD_FLAG_CHANGER
)
480 && (--softc
->changer
->num_devices
== 0)) {
483 * Theoretically, there shouldn't be any timeouts left, but
484 * I'm not completely sure that that will be the case. So,
485 * it won't hurt to check and see if there are any left.
487 if (softc
->changer
->flags
& CHANGER_TIMEOUT_SCHED
) {
488 callout_stop(&softc
->changer
->long_handle
);
489 softc
->changer
->flags
&= ~CHANGER_TIMEOUT_SCHED
;
492 if (softc
->changer
->flags
& CHANGER_SHORT_TMOUT_SCHED
) {
493 callout_stop(&softc
->changer
->short_handle
);
494 softc
->changer
->flags
&= ~CHANGER_SHORT_TMOUT_SCHED
;
497 lockmgr(&changerq_lock
, LK_EXCLUSIVE
);
498 STAILQ_REMOVE(&changerq
, softc
->changer
, cdchanger
,
501 lockmgr(&changerq_lock
, LK_RELEASE
);
502 xpt_print(periph
->path
, "removing changer entry\n");
503 kfree(softc
->changer
, M_DEVBUF
);
505 devstat_remove_entry(&softc
->device_stats
);
506 cam_extend_release(cdperiphs
, periph
->unit_number
);
507 if (softc
->disk
.d_rawdev
) {
508 cam_periph_unlock(periph
);
509 disk_destroy(&softc
->disk
);
510 cam_periph_lock(periph
);
512 kfree(softc
, M_DEVBUF
);
516 cdasync(void *callback_arg
, u_int32_t code
,
517 struct cam_path
*path
, void *arg
)
519 struct cam_periph
*periph
;
521 periph
= (struct cam_periph
*)callback_arg
;
524 case AC_FOUND_DEVICE
:
526 struct ccb_getdev
*cgd
;
529 cgd
= (struct ccb_getdev
*)arg
;
533 if (SID_TYPE(&cgd
->inq_data
) != T_CDROM
534 && SID_TYPE(&cgd
->inq_data
) != T_WORM
)
538 * Don't complain if a valid peripheral is already attached.
540 periph
= cam_periph_find(cgd
->ccb_h
.path
, "cd");
541 if (periph
&& (periph
->flags
& CAM_PERIPH_INVALID
) == 0)
545 * Allocate a peripheral instance for
546 * this device and start the probe
549 status
= cam_periph_alloc(cdregister
, cdoninvalidate
,
551 "cd", CAM_PERIPH_BIO
,
552 cgd
->ccb_h
.path
, cdasync
,
553 AC_FOUND_DEVICE
, cgd
);
555 if (status
!= CAM_REQ_CMP
&& status
!= CAM_REQ_INPROG
) {
556 kprintf("cdasync: Unable to attach new device "
557 "due to status 0x%x\n", status
);
564 struct cd_softc
*softc
;
565 struct ccb_hdr
*ccbh
;
567 softc
= (struct cd_softc
*)periph
->softc
;
569 * Don't fail on the expected unit attention
572 softc
->flags
|= CD_FLAG_RETRY_UA
;
573 LIST_FOREACH(ccbh
, &softc
->pending_ccbs
, periph_links
.le
)
574 ccbh
->ccb_state
|= CD_CCB_RETRY_UA
;
578 cam_periph_async(periph
, code
, path
, arg
);
584 cdsysctlinit(void *context
, int pending
)
586 struct cam_periph
*periph
;
587 struct cd_softc
*softc
;
588 char tmpstr
[80], tmpstr2
[80];
590 periph
= (struct cam_periph
*)context
;
591 if (cam_periph_acquire(periph
) != CAM_REQ_CMP
) {
595 softc
= (struct cd_softc
*)periph
->softc
;
596 ksnprintf(tmpstr
, sizeof(tmpstr
),
597 "CAM CD unit %d", periph
->unit_number
);
598 ksnprintf(tmpstr2
, sizeof(tmpstr2
),
599 "%d", periph
->unit_number
);
601 sysctl_ctx_free(&softc
->sysctl_ctx
);
602 sysctl_ctx_init(&softc
->sysctl_ctx
);
603 softc
->flags
|= CD_FLAG_SCTX_INIT
;
604 softc
->sysctl_tree
= SYSCTL_ADD_NODE(&softc
->sysctl_ctx
,
605 SYSCTL_STATIC_CHILDREN(_kern_cam_cd
), OID_AUTO
,
606 tmpstr2
, CTLFLAG_RD
, 0, tmpstr
);
608 if (softc
->sysctl_tree
== NULL
) {
609 kprintf("cdsysctlinit: unable to allocate sysctl tree\n");
610 cam_periph_release(periph
);
615 * Now register the sysctl handler, so the user can the value on
618 SYSCTL_ADD_PROC(&softc
->sysctl_ctx
,SYSCTL_CHILDREN(softc
->sysctl_tree
),
619 OID_AUTO
, "minimum_cmd_size", CTLTYPE_INT
| CTLFLAG_RW
,
620 &softc
->minimum_command_size
, 0, cdcmdsizesysctl
, "I",
623 cam_periph_release(periph
);
627 * We have a handler function for this so we can check the values when the
628 * user sets them, instead of every time we look at them.
631 cdcmdsizesysctl(SYSCTL_HANDLER_ARGS
)
635 value
= *(int *)arg1
;
637 error
= sysctl_handle_int(oidp
, &value
, 0, req
);
639 if ((error
!= 0) || (req
->newptr
== NULL
))
643 * The only real values we can have here are 6 or 10. I don't
644 * really forsee having 12 be an option at any time in the future.
645 * So if the user sets something less than or equal to 6, we'll set
646 * it to 6. If he sets something greater than 6, we'll set it to 10.
648 * I suppose we could just return an error here for the wrong values,
649 * but I don't think it's necessary to do so, as long as we can
650 * determine the user's intent without too much trouble.
657 *(int *)arg1
= value
;
664 cdregister(struct cam_periph
*periph
, void *arg
)
666 struct cd_softc
*softc
;
667 struct ccb_pathinq
*cpi
;
668 struct ccb_getdev
*cgd
;
672 cgd
= (struct ccb_getdev
*)arg
;
673 if (periph
== NULL
) {
674 kprintf("cdregister: periph was NULL!!\n");
675 return(CAM_REQ_CMP_ERR
);
678 kprintf("cdregister: no getdev CCB, can't register device\n");
679 return(CAM_REQ_CMP_ERR
);
682 softc
= kmalloc(sizeof(*softc
), M_DEVBUF
, M_INTWAIT
| M_ZERO
);
683 sysctl_ctx_init(&softc
->sysctl_ctx
);
684 LIST_INIT(&softc
->pending_ccbs
);
685 STAILQ_INIT(&softc
->mode_queue
);
686 softc
->state
= CD_STATE_PROBE
;
687 bioq_init(&softc
->bio_queue
);
688 if (SID_IS_REMOVABLE(&cgd
->inq_data
))
689 softc
->flags
|= CD_FLAG_DISC_REMOVABLE
;
690 if ((cgd
->inq_data
.flags
& SID_CmdQue
) != 0)
691 softc
->flags
|= CD_FLAG_TAGGED_QUEUING
;
693 periph
->softc
= softc
;
694 softc
->periph
= periph
;
696 cam_extend_set(cdperiphs
, periph
->unit_number
, periph
);
699 * See if this device has any quirks.
701 match
= cam_quirkmatch((caddr_t
)&cgd
->inq_data
,
702 (caddr_t
)cd_quirk_table
,
703 NELEM(cd_quirk_table
),
704 sizeof(*cd_quirk_table
), scsi_inquiry_match
);
707 softc
->quirks
= ((struct cd_quirk_entry
*)match
)->quirks
;
709 softc
->quirks
= CD_Q_NONE
;
711 /* Check if the SIM does not want 6 byte commands */
712 cpi
= &xpt_alloc_ccb()->cpi
;
713 xpt_setup_ccb(&cpi
->ccb_h
, periph
->path
, /*priority*/1);
714 cpi
->ccb_h
.func_code
= XPT_PATH_INQ
;
715 xpt_action((union ccb
*)cpi
);
716 if (cpi
->ccb_h
.status
== CAM_REQ_CMP
&& (cpi
->hba_misc
& PIM_NO_6_BYTE
))
717 softc
->quirks
|= CD_Q_10_BYTE_ONLY
;
718 xpt_free_ccb(&cpi
->ccb_h
);
720 TASK_INIT(&softc
->sysctl_task
, 0, cdsysctlinit
, periph
);
722 /* The default is 6 byte commands, unless quirked otherwise */
723 if (softc
->quirks
& CD_Q_10_BYTE_ONLY
)
724 softc
->minimum_command_size
= 10;
726 softc
->minimum_command_size
= 6;
729 * Load the user's default, if any.
731 ksnprintf(tmpstr
, sizeof(tmpstr
), "kern.cam.cd.%d.minimum_cmd_size",
732 periph
->unit_number
);
733 TUNABLE_INT_FETCH(tmpstr
, &softc
->minimum_command_size
);
735 /* 6 and 10 are the only permissible values here. */
736 if (softc
->minimum_command_size
< 6)
737 softc
->minimum_command_size
= 6;
738 else if (softc
->minimum_command_size
> 6)
739 softc
->minimum_command_size
= 10;
742 * We need to register the statistics structure for this device,
743 * but we don't have the blocksize yet for it. So, we register
744 * the structure and indicate that we don't have the blocksize
745 * yet. Unlike other SCSI peripheral drivers, we explicitly set
746 * the device type here to be CDROM, rather than just ORing in
747 * the device type. This is because this driver can attach to either
748 * CDROM or WORM devices, and we want this peripheral driver to
749 * show up in the devstat list as a CD peripheral driver, not a
750 * WORM peripheral driver. WORM drives will also have the WORM
751 * driver attached to them.
753 cam_periph_unlock(periph
);
754 devstat_add_entry(&softc
->device_stats
, "cd",
755 periph
->unit_number
, 0,
756 DEVSTAT_BS_UNAVAILABLE
,
757 DEVSTAT_TYPE_CDROM
| DEVSTAT_TYPE_IF_SCSI
,
758 DEVSTAT_PRIORITY_CD
);
759 disk_create(periph
->unit_number
, &softc
->disk
, &cd_ops
);
760 disk_setdisktype(&softc
->disk
, "optical");
761 softc
->disk
.d_rawdev
->si_iosize_max
= MAXPHYS
;
762 softc
->disk
.d_info
.d_dsflags
= DSO_ONESLICE
| DSO_COMPATLABEL
|
764 cam_periph_lock(periph
);
767 * Add an async callback so that we get
768 * notified if this device goes away.
770 xpt_register_async(AC_SENT_BDR
| AC_BUS_RESET
| AC_LOST_DEVICE
,
771 cdasync
, periph
, periph
->path
);
774 * If the target lun is greater than 0, we most likely have a CD
775 * changer device. Check the quirk entries as well, though, just
776 * in case someone has a CD tower with one lun per drive or
777 * something like that. Also, if we know up front that a
778 * particular device is a changer, we can mark it as such starting
779 * with lun 0, instead of lun 1. It shouldn't be necessary to have
780 * a quirk entry to define something as a changer, however.
782 if (((cgd
->ccb_h
.target_lun
> 0)
783 && ((softc
->quirks
& CD_Q_NO_CHANGER
) == 0))
784 || ((softc
->quirks
& CD_Q_CHANGER
) != 0)) {
785 struct cdchanger
*nchanger
;
786 struct cam_periph
*nperiph
;
787 struct cam_path
*path
;
791 /* Set the changer flag in the current device's softc */
792 softc
->flags
|= CD_FLAG_CHANGER
;
795 * Now, look around for an existing changer device with the
796 * same path and target ID as the current device.
798 lockmgr(&changerq_lock
, LK_EXCLUSIVE
);
800 nchanger
= (struct cdchanger
*)STAILQ_FIRST(&changerq
);
802 nchanger
= STAILQ_NEXT(nchanger
, changer_links
)){
803 if ((nchanger
->path_id
== cgd
->ccb_h
.path_id
)
804 && (nchanger
->target_id
== cgd
->ccb_h
.target_id
)) {
809 lockmgr(&changerq_lock
, LK_RELEASE
);
812 * If we found a matching entry, just add this device to
813 * the list of devices on this changer.
816 struct chdevlist
*chlunhead
;
818 chlunhead
= &nchanger
->chluns
;
821 * XXX KDM look at consolidating this code with the
822 * code below in a separate function.
826 * Create a path with lun id 0, and see if we can
827 * find a matching device
829 status
= xpt_create_path(&path
, /*periph*/ periph
,
831 cgd
->ccb_h
.target_id
, 0);
833 if ((status
== CAM_REQ_CMP
)
834 && ((nperiph
= cam_periph_find(path
, "cd")) != NULL
)){
835 struct cd_softc
*nsoftc
;
837 nsoftc
= (struct cd_softc
*)nperiph
->softc
;
839 if ((nsoftc
->flags
& CD_FLAG_CHANGER
) == 0){
840 nsoftc
->flags
|= CD_FLAG_CHANGER
;
841 nchanger
->num_devices
++;
842 if (camq_resize(&nchanger
->devq
,
843 nchanger
->num_devices
)!=CAM_REQ_CMP
){
844 kprintf("cdregister: "
850 nsoftc
->changer
= nchanger
;
851 nsoftc
->pinfo
.index
=CAM_UNQUEUED_INDEX
;
853 STAILQ_INSERT_TAIL(&nchanger
->chluns
,
854 nsoftc
,changer_links
);
857 } else if (status
== CAM_REQ_CMP
)
860 kprintf("cdregister: unable to allocate path\n"
861 "cdregister: changer support may be "
865 nchanger
->num_devices
++;
867 softc
->changer
= nchanger
;
868 softc
->pinfo
.index
= CAM_UNQUEUED_INDEX
;
870 if (camq_resize(&nchanger
->devq
,
871 nchanger
->num_devices
) != CAM_REQ_CMP
) {
872 kprintf("cdregister: camq_resize "
873 "failed, changer support may "
877 STAILQ_INSERT_TAIL(chlunhead
, softc
, changer_links
);
880 * In this case, we don't already have an entry for this
881 * particular changer, so we need to create one, add it to
882 * the queue, and queue this device on the list for this
883 * changer. Before we queue this device, however, we need
884 * to search for lun id 0 on this target, and add it to the
885 * queue first, if it exists. (and if it hasn't already
886 * been marked as part of the changer.)
889 nchanger
= kmalloc(sizeof(struct cdchanger
),
890 M_DEVBUF
, M_INTWAIT
| M_ZERO
);
891 callout_init_lk(&nchanger
->short_handle
,
893 callout_init_lk(&nchanger
->long_handle
,
895 if (camq_init(&nchanger
->devq
, 1) != 0) {
896 softc
->flags
&= ~CD_FLAG_CHANGER
;
897 kprintf("cdregister: changer support "
902 nchanger
->path_id
= cgd
->ccb_h
.path_id
;
903 nchanger
->target_id
= cgd
->ccb_h
.target_id
;
905 /* this is superfluous, but it makes things clearer */
906 nchanger
->num_devices
= 0;
908 STAILQ_INIT(&nchanger
->chluns
);
910 callout_init_lk(&nchanger
->long_handle
,
912 callout_init_lk(&nchanger
->short_handle
,
915 lockmgr(&changerq_lock
, LK_EXCLUSIVE
);
917 STAILQ_INSERT_TAIL(&changerq
, nchanger
,
919 lockmgr(&changerq_lock
, LK_RELEASE
);
922 * Create a path with lun id 0, and see if we can
923 * find a matching device
925 status
= xpt_create_path(&path
, /*periph*/ periph
,
927 cgd
->ccb_h
.target_id
, 0);
930 * If we were able to allocate the path, and if we
931 * find a matching device and it isn't already
932 * marked as part of a changer, then we add it to
933 * the current changer.
935 if ((status
== CAM_REQ_CMP
)
936 && ((nperiph
= cam_periph_find(path
, "cd")) != NULL
)
937 && ((((struct cd_softc
*)periph
->softc
)->flags
&
938 CD_FLAG_CHANGER
) == 0)) {
939 struct cd_softc
*nsoftc
;
941 nsoftc
= (struct cd_softc
*)nperiph
->softc
;
943 nsoftc
->flags
|= CD_FLAG_CHANGER
;
944 nchanger
->num_devices
++;
945 if (camq_resize(&nchanger
->devq
,
946 nchanger
->num_devices
) != CAM_REQ_CMP
) {
947 kprintf("cdregister: camq_resize "
948 "failed, changer support may "
951 nsoftc
->changer
= nchanger
;
952 nsoftc
->pinfo
.index
= CAM_UNQUEUED_INDEX
;
954 STAILQ_INSERT_TAIL(&nchanger
->chluns
,
955 nsoftc
, changer_links
);
957 } else if (status
== CAM_REQ_CMP
)
960 kprintf("cdregister: unable to allocate path\n"
961 "cdregister: changer support may be "
965 softc
->changer
= nchanger
;
966 softc
->pinfo
.index
= CAM_UNQUEUED_INDEX
;
967 nchanger
->num_devices
++;
968 if (camq_resize(&nchanger
->devq
,
969 nchanger
->num_devices
) != CAM_REQ_CMP
) {
970 kprintf("cdregister: camq_resize "
971 "failed, changer support may "
974 STAILQ_INSERT_TAIL(&nchanger
->chluns
, softc
,
982 * Refcount and block open attempts until we are setup
985 cam_periph_hold(periph
, 0);
987 if ((softc
->flags
& CD_FLAG_CHANGER
) == 0)
988 xpt_schedule(periph
, /*priority*/5);
990 cdschedule(periph
, /*priority*/ 5);
996 cdopen(struct dev_open_args
*ap
)
998 cdev_t dev
= ap
->a_head
.a_dev
;
999 struct cam_periph
*periph
;
1000 struct cd_softc
*softc
;
1004 * Disallow CAM access if RESTRICTEDROOT
1006 if (caps_priv_check_self(SYSCAP_RESTRICTEDROOT
))
1010 periph
= cam_extend_get(cdperiphs
, unit
);
1015 softc
= (struct cd_softc
*)periph
->softc
;
1017 if (cam_periph_acquire(periph
) != CAM_REQ_CMP
)
1020 cam_periph_lock(periph
);
1022 if (softc
->flags
& CD_FLAG_INVALID
) {
1023 cam_periph_unlock(periph
);
1024 cam_periph_release(periph
);
1028 if ((error
= cam_periph_hold(periph
, PCATCH
)) != 0) {
1029 cam_periph_unlock(periph
);
1030 cam_periph_release(periph
);
1034 /* Closes aren't symmetrical with opens, so fix up the refcounting. */
1035 if (softc
->flags
& CD_FLAG_OPEN
)
1036 cam_periph_release(periph
);
1038 softc
->flags
|= CD_FLAG_OPEN
;
1041 * Check for media, and set the appropriate flags. We don't bail
1042 * if we don't have media, but then we don't allow anything but the
1043 * CDIOCEJECT/CDIOCCLOSE ioctls if there is no media.
1045 * XXX KDM for now, we do fail the open if we don't have media. We
1046 * can change this once we've figured out how to make the slice
1047 * code work well with media changing underneath it.
1049 error
= cdcheckmedia(periph
);
1052 softc
->flags
|= CD_FLAG_CAP_MUTE
;
1054 softc
->flags
&= ~CD_FLAG_CAP_MUTE
;
1057 cdprevent(periph
, PR_PREVENT
);
1058 CAM_DEBUG(periph
->path
, CAM_DEBUG_TRACE
, ("leaving cdopen\n"));
1059 cam_periph_unhold(periph
, 1);
1060 /* stays acquired */
1066 cdclose(struct dev_close_args
*ap
)
1068 cdev_t dev
= ap
->a_head
.a_dev
;
1069 struct cam_periph
*periph
;
1070 struct cd_softc
*softc
;
1071 struct disk_info
*info
;
1075 periph
= cam_extend_get(cdperiphs
, unit
);
1079 softc
= (struct cd_softc
*)periph
->softc
;
1081 cam_periph_lock(periph
);
1082 cam_periph_hold(periph
, 0);
1084 if ((softc
->flags
& CD_FLAG_DISC_REMOVABLE
) != 0)
1085 cdprevent(periph
, PR_ALLOW
);
1088 * Unconditionally set the dsopen() flags back to their default
1091 info
= &softc
->disk
.d_info
;
1092 info
->d_dsflags
&= ~DSO_NOLABELS
;
1093 info
->d_dsflags
|= DSO_COMPATLABEL
;
1096 * Since we're closing this CD, mark the blocksize as unavailable.
1097 * It will be marked as available when the CD is opened again.
1099 softc
->device_stats
.flags
|= DEVSTAT_BS_UNAVAILABLE
;
1102 * We'll check the media and toc again at the next open().
1104 softc
->flags
&= ~(CD_FLAG_VALID_MEDIA
|CD_FLAG_VALID_TOC
|CD_FLAG_OPEN
);
1106 cam_periph_unhold(periph
, 1);
1107 cam_periph_release(periph
);
1113 cdshorttimeout(void *arg
)
1115 struct cdchanger
*changer
;
1117 changer
= (struct cdchanger
*)arg
;
1119 /* Always clear the short timeout flag, since that's what we're in */
1120 changer
->flags
&= ~CHANGER_SHORT_TMOUT_SCHED
;
1123 * Check to see if there is any more pending or outstanding I/O for
1124 * this device. If not, move it out of the active slot.
1126 if ((bioq_first(&changer
->cur_device
->bio_queue
) == NULL
)
1127 && (changer
->cur_device
->outstanding_cmds
== 0)) {
1128 changer
->flags
|= CHANGER_MANUAL_CALL
;
1129 cdrunchangerqueue(changer
);
1134 * This is a wrapper for xpt_schedule. It only applies to changers.
1137 cdschedule(struct cam_periph
*periph
, int priority
)
1139 struct cd_softc
*softc
;
1141 softc
= (struct cd_softc
*)periph
->softc
;
1144 * If this device isn't currently queued, and if it isn't
1145 * the active device, then we queue this device and run the
1146 * changer queue if there is no timeout scheduled to do it.
1147 * If this device is the active device, just schedule it
1148 * to run again. If this device is queued, there should be
1149 * a timeout in place already that will make sure it runs.
1151 if ((softc
->pinfo
.index
== CAM_UNQUEUED_INDEX
)
1152 && ((softc
->flags
& CD_FLAG_ACTIVE
) == 0)) {
1154 * We don't do anything with the priority here.
1155 * This is strictly a fifo queue.
1157 softc
->pinfo
.priority
= 1;
1158 softc
->pinfo
.generation
= ++softc
->changer
->devq
.generation
;
1159 camq_insert(&softc
->changer
->devq
, (cam_pinfo
*)softc
);
1162 * Since we just put a device in the changer queue,
1163 * check and see if there is a timeout scheduled for
1164 * this changer. If so, let the timeout handle
1165 * switching this device into the active slot. If
1166 * not, manually call the timeout routine to
1169 if (((softc
->changer
->flags
& CHANGER_TIMEOUT_SCHED
)==0)
1170 && ((softc
->changer
->flags
& CHANGER_NEED_TIMEOUT
)==0)
1171 && ((softc
->changer
->flags
& CHANGER_SHORT_TMOUT_SCHED
)==0)){
1172 softc
->changer
->flags
|= CHANGER_MANUAL_CALL
;
1173 cdrunchangerqueue(softc
->changer
);
1175 } else if ((softc
->flags
& CD_FLAG_ACTIVE
)
1176 && ((softc
->flags
& CD_FLAG_SCHED_ON_COMP
) == 0)) {
1177 xpt_schedule(periph
, priority
);
1182 cdrunchangerqueue(void *arg
)
1184 struct cd_softc
*softc
;
1185 struct cdchanger
*changer
;
1186 int called_from_timeout
;
1188 changer
= (struct cdchanger
*)arg
;
1191 * If we have NOT been called from cdstrategy() or cddone(), and
1192 * instead from a timeout routine, go ahead and clear the
1195 if ((changer
->flags
& CHANGER_MANUAL_CALL
) == 0) {
1196 changer
->flags
&= ~CHANGER_TIMEOUT_SCHED
;
1197 called_from_timeout
= 1;
1199 called_from_timeout
= 0;
1201 /* Always clear the manual call flag */
1202 changer
->flags
&= ~CHANGER_MANUAL_CALL
;
1204 /* nothing to do if the queue is empty */
1205 if (changer
->devq
.entries
<= 0) {
1210 * If the changer queue is frozen, that means we have an active
1213 if (changer
->devq
.qfrozen_cnt
> 0) {
1216 * We always need to reset the frozen count and clear the
1219 changer
->devq
.qfrozen_cnt
--;
1220 changer
->cur_device
->flags
&= ~CD_FLAG_ACTIVE
;
1221 changer
->cur_device
->flags
&= ~CD_FLAG_SCHED_ON_COMP
;
1223 if (changer
->cur_device
->outstanding_cmds
> 0) {
1224 changer
->cur_device
->flags
|= CD_FLAG_SCHED_ON_COMP
;
1225 changer
->cur_device
->bufs_left
=
1226 changer
->cur_device
->outstanding_cmds
;
1227 if (called_from_timeout
) {
1228 callout_reset(&changer
->long_handle
,
1229 changer_max_busy_seconds
* hz
,
1230 cdrunchangerqueue
, changer
);
1231 changer
->flags
|= CHANGER_TIMEOUT_SCHED
;
1237 * Check to see whether the current device has any I/O left
1238 * to do. If so, requeue it at the end of the queue. If
1239 * not, there is no need to requeue it.
1241 if (bioq_first(&changer
->cur_device
->bio_queue
) != NULL
) {
1243 changer
->cur_device
->pinfo
.generation
=
1244 ++changer
->devq
.generation
;
1245 camq_insert(&changer
->devq
,
1246 (cam_pinfo
*)changer
->cur_device
);
1250 softc
= (struct cd_softc
*)camq_remove(&changer
->devq
, CAMQ_HEAD
);
1252 changer
->cur_device
= softc
;
1254 changer
->devq
.qfrozen_cnt
++;
1255 softc
->flags
|= CD_FLAG_ACTIVE
;
1257 /* Just in case this device is waiting */
1258 wakeup(&softc
->changer
);
1259 xpt_schedule(softc
->periph
, /*priority*/ 1);
1262 * Get rid of any pending timeouts, and set a flag to schedule new
1263 * ones so this device gets its full time quantum.
1265 if (changer
->flags
& CHANGER_TIMEOUT_SCHED
) {
1266 callout_stop(&changer
->long_handle
);
1267 changer
->flags
&= ~CHANGER_TIMEOUT_SCHED
;
1270 if (changer
->flags
& CHANGER_SHORT_TMOUT_SCHED
) {
1271 callout_stop(&changer
->short_handle
);
1272 changer
->flags
&= ~CHANGER_SHORT_TMOUT_SCHED
;
1276 * We need to schedule timeouts, but we only do this after the
1277 * first transaction has completed. This eliminates the changer
1280 changer
->flags
|= CHANGER_NEED_TIMEOUT
;
1284 cdchangerschedule(struct cd_softc
*softc
)
1286 struct cdchanger
*changer
;
1288 changer
= softc
->changer
;
1291 * If this is a changer, and this is the current device,
1292 * and this device has at least the minimum time quantum to
1293 * run, see if we can switch it out.
1295 if ((softc
->flags
& CD_FLAG_ACTIVE
)
1296 && ((changer
->flags
& CHANGER_SHORT_TMOUT_SCHED
) == 0)
1297 && ((changer
->flags
& CHANGER_NEED_TIMEOUT
) == 0)) {
1299 * We try three things here. The first is that we
1300 * check to see whether the schedule on completion
1301 * flag is set. If it is, we decrement the number
1302 * of buffers left, and if it's zero, we reschedule.
1303 * Next, we check to see whether the pending buffer
1304 * queue is empty and whether there are no
1305 * outstanding transactions. If so, we reschedule.
1306 * Next, we see if the pending buffer queue is empty.
1307 * If it is, we set the number of buffers left to
1308 * the current active buffer count and set the
1309 * schedule on complete flag.
1311 if (softc
->flags
& CD_FLAG_SCHED_ON_COMP
) {
1312 if (--softc
->bufs_left
== 0) {
1313 softc
->changer
->flags
|=
1314 CHANGER_MANUAL_CALL
;
1315 softc
->flags
&= ~CD_FLAG_SCHED_ON_COMP
;
1316 cdrunchangerqueue(softc
->changer
);
1318 } else if ((bioq_first(&softc
->bio_queue
) == NULL
)
1319 && (softc
->outstanding_cmds
== 0)) {
1320 softc
->changer
->flags
|= CHANGER_MANUAL_CALL
;
1321 cdrunchangerqueue(softc
->changer
);
1323 } else if ((softc
->changer
->flags
& CHANGER_NEED_TIMEOUT
)
1324 && (softc
->flags
& CD_FLAG_ACTIVE
)) {
1327 * Now that the first transaction to this
1328 * particular device has completed, we can go ahead
1329 * and schedule our timeouts.
1331 if ((changer
->flags
& CHANGER_TIMEOUT_SCHED
) == 0) {
1332 callout_reset(&changer
->long_handle
,
1333 changer_max_busy_seconds
* hz
,
1334 cdrunchangerqueue
, changer
);
1335 changer
->flags
|= CHANGER_TIMEOUT_SCHED
;
1337 kprintf("cdchangerschedule: already have a long"
1340 if ((changer
->flags
& CHANGER_SHORT_TMOUT_SCHED
) == 0) {
1341 callout_reset(&changer
->short_handle
,
1342 changer_min_busy_seconds
* hz
,
1343 cdshorttimeout
, changer
);
1344 changer
->flags
|= CHANGER_SHORT_TMOUT_SCHED
;
1346 kprintf("cdchangerschedule: already have a short "
1350 * We just scheduled timeouts, no need to schedule
1353 changer
->flags
&= ~CHANGER_NEED_TIMEOUT
;
1359 cdrunccb(union ccb
*ccb
, int (*error_routine
)(union ccb
*ccb
,
1360 u_int32_t cam_flags
,
1361 u_int32_t sense_flags
),
1362 u_int32_t cam_flags
, u_int32_t sense_flags
)
1364 struct cd_softc
*softc
;
1365 struct cam_periph
*periph
;
1368 periph
= xpt_path_periph(ccb
->ccb_h
.path
);
1369 softc
= (struct cd_softc
*)periph
->softc
;
1371 error
= cam_periph_runccb(ccb
, error_routine
, cam_flags
, sense_flags
,
1372 &softc
->device_stats
);
1374 if (softc
->flags
& CD_FLAG_CHANGER
)
1375 cdchangerschedule(softc
);
1381 cdgetccb(struct cam_periph
*periph
, u_int32_t priority
)
1383 struct cd_softc
*softc
;
1384 static union ccb
*ccb
;
1386 softc
= (struct cd_softc
*)periph
->softc
;
1388 if (softc
->flags
& CD_FLAG_CHANGER
) {
1390 * This should work the first time this device is woken up,
1391 * but just in case it doesn't, we use a while loop.
1393 while ((softc
->flags
& CD_FLAG_ACTIVE
) == 0) {
1395 * If this changer isn't already queued, queue it up.
1397 if (softc
->pinfo
.index
== CAM_UNQUEUED_INDEX
) {
1398 softc
->pinfo
.priority
= 1;
1399 softc
->pinfo
.generation
=
1400 ++softc
->changer
->devq
.generation
;
1401 camq_insert(&softc
->changer
->devq
,
1402 (cam_pinfo
*)softc
);
1404 if (((softc
->changer
->flags
& CHANGER_TIMEOUT_SCHED
)==0)
1405 && ((softc
->changer
->flags
& CHANGER_NEED_TIMEOUT
)==0)
1406 && ((softc
->changer
->flags
1407 & CHANGER_SHORT_TMOUT_SCHED
)==0)) {
1408 softc
->changer
->flags
|= CHANGER_MANUAL_CALL
;
1409 cdrunchangerqueue(softc
->changer
);
1411 sim_lock_sleep(&softc
->changer
, 0, "cgticb", 0,
1415 ccb
= cam_periph_getccb(periph
, priority
);
1416 ccb
->ccb_h
.ccb_state
= CD_CCB_POLLED
;
1422 * Actually translate the requested transfer into one the physical driver
1423 * can understand. The transfer is described by a buf and will include
1424 * only one physical transfer.
1427 cdstrategy(struct dev_strategy_args
*ap
)
1429 cdev_t dev
= ap
->a_head
.a_dev
;
1430 struct bio
*bio
= ap
->a_bio
;
1431 struct buf
*bp
= bio
->bio_buf
;
1432 struct cam_periph
*periph
;
1433 struct cd_softc
*softc
;
1437 periph
= cam_extend_get(cdperiphs
, unit
);
1438 if (periph
== NULL
) {
1439 bp
->b_error
= ENXIO
;
1443 cam_periph_lock(periph
);
1444 CAM_DEBUG(periph
->path
, CAM_DEBUG_TRACE
, ("entering cdstrategy\n"));
1446 softc
= (struct cd_softc
*)periph
->softc
;
1449 * If the device has been made invalid, error out
1451 if ((softc
->flags
& CD_FLAG_INVALID
)) {
1452 cam_periph_unlock(periph
);
1453 bp
->b_error
= ENXIO
;
1458 * If we don't have valid media, look for it before trying to
1461 if ((softc
->flags
& CD_FLAG_VALID_MEDIA
) == 0) {
1464 error
= cdcheckmedia(periph
);
1466 cam_periph_unlock(periph
);
1467 bp
->b_error
= error
;
1473 * Place it in the queue of disk activities for this disk
1475 bioqdisksort(&softc
->bio_queue
, bio
);
1478 * Schedule ourselves for performing the work. We do things
1479 * differently for changers.
1481 if ((softc
->flags
& CD_FLAG_CHANGER
) == 0)
1482 xpt_schedule(periph
, /* XXX priority */1);
1484 cdschedule(periph
, /* priority */ 1);
1486 cam_periph_unlock(periph
);
1489 bp
->b_flags
|= B_ERROR
;
1491 * Correctly set the buf to indicate a completed xfer
1493 bp
->b_resid
= bp
->b_bcount
;
1499 cdstart(struct cam_periph
*periph
, union ccb
*start_ccb
)
1501 struct cd_softc
*softc
;
1504 struct ccb_scsiio
*csio
;
1505 struct scsi_read_capacity_data
*rcap
;
1507 softc
= (struct cd_softc
*)periph
->softc
;
1509 CAM_DEBUG(periph
->path
, CAM_DEBUG_TRACE
, ("entering cdstart\n"));
1511 switch (softc
->state
) {
1512 case CD_STATE_NORMAL
:
1514 bio
= bioq_first(&softc
->bio_queue
);
1515 if (periph
->immediate_priority
<= periph
->pinfo
.priority
) {
1516 start_ccb
->ccb_h
.ccb_state
= CD_CCB_WAITING
;
1518 SLIST_INSERT_HEAD(&periph
->ccb_list
, &start_ccb
->ccb_h
,
1520 periph
->immediate_priority
= CAM_PRIORITY_NONE
;
1521 wakeup(&periph
->ccb_list
);
1522 } else if (bio
== NULL
) {
1523 xpt_release_ccb(start_ccb
);
1526 bioq_remove(&softc
->bio_queue
, bio
);
1528 devstat_start_transaction(&softc
->device_stats
);
1530 KKASSERT(bio
->bio_offset
% softc
->params
.blksize
== 0);
1532 scsi_read_write(&start_ccb
->csio
,
1534 /* cbfcnp */ cddone
,
1536 /* read */(bp
->b_cmd
== BUF_CMD_READ
),
1538 /* minimum_cmd_size */ 10,
1540 bio
->bio_offset
/ softc
->params
.blksize
,
1541 bp
->b_bcount
/ softc
->params
.blksize
,
1542 /* data_ptr */ bp
->b_data
,
1543 /* dxfer_len */ bp
->b_bcount
,
1544 /* sense_len */ SSD_FULL_SIZE
,
1545 /* timeout */ 30000);
1546 start_ccb
->ccb_h
.ccb_state
= CD_CCB_BUFFER_IO
;
1549 LIST_INSERT_HEAD(&softc
->pending_ccbs
,
1550 &start_ccb
->ccb_h
, periph_links
.le
);
1552 softc
->outstanding_cmds
++;
1553 /* We expect a unit attention from this device */
1554 if ((softc
->flags
& CD_FLAG_RETRY_UA
) != 0) {
1555 start_ccb
->ccb_h
.ccb_state
|= CD_CCB_RETRY_UA
;
1556 softc
->flags
&= ~CD_FLAG_RETRY_UA
;
1559 start_ccb
->ccb_h
.ccb_bio
= bio
;
1560 bio
= bioq_first(&softc
->bio_queue
);
1562 xpt_action(start_ccb
);
1565 /* Have more work to do, so ensure we stay scheduled */
1566 xpt_schedule(periph
, /* XXX priority */1);
1570 case CD_STATE_PROBE
:
1573 rcap
= kmalloc(sizeof(*rcap
), M_SCSICD
, M_INTWAIT
);
1574 csio
= &start_ccb
->csio
;
1575 scsi_read_capacity(csio
,
1582 start_ccb
->ccb_h
.ccb_bio
= NULL
;
1583 start_ccb
->ccb_h
.ccb_state
= CD_CCB_PROBE
;
1584 xpt_action(start_ccb
);
1591 cddone(struct cam_periph
*periph
, union ccb
*done_ccb
)
1593 struct cd_softc
*softc
;
1594 struct ccb_scsiio
*csio
;
1596 CAM_DEBUG(periph
->path
, CAM_DEBUG_TRACE
, ("entering cddone\n"));
1598 softc
= (struct cd_softc
*)periph
->softc
;
1599 csio
= &done_ccb
->csio
;
1601 switch (csio
->ccb_h
.ccb_state
& CD_CCB_TYPE_MASK
) {
1602 case CD_CCB_BUFFER_IO
:
1608 bio
= (struct bio
*)done_ccb
->ccb_h
.ccb_bio
;
1612 if ((done_ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) {
1615 if ((done_ccb
->ccb_h
.ccb_state
& CD_CCB_RETRY_UA
) != 0)
1620 error
= cderror(done_ccb
, CAM_RETRY_SELTO
, sf
);
1621 if (error
== ERESTART
) {
1623 * A retry was scheuled, so
1634 xpt_print(periph
->path
,
1635 "cddone: got error %#x back\n", error
);
1636 while ((q_bio
= bioq_takefirst(&softc
->bio_queue
)) != NULL
) {
1637 q_bp
= q_bio
->bio_buf
;
1638 q_bp
->b_resid
= q_bp
->b_bcount
;
1639 q_bp
->b_error
= EIO
;
1640 q_bp
->b_flags
|= B_ERROR
;
1643 bp
->b_resid
= bp
->b_bcount
;
1644 bp
->b_error
= error
;
1645 bp
->b_flags
|= B_ERROR
;
1646 cam_release_devq(done_ccb
->ccb_h
.path
,
1650 /*getcount_only*/0);
1653 bp
->b_resid
= csio
->resid
;
1655 if (bp
->b_resid
!= 0) {
1656 /* Short transfer ??? */
1657 bp
->b_flags
|= B_ERROR
;
1661 LIST_REMOVE(&done_ccb
->ccb_h
, periph_links
.le
);
1662 softc
->outstanding_cmds
--;
1664 if (softc
->flags
& CD_FLAG_CHANGER
)
1665 cdchangerschedule(softc
);
1667 devstat_end_transaction_buf(&softc
->device_stats
, bp
);
1674 * Currently (9/30/97) the longest possible announce
1675 * buffer is 108 bytes, for the first error case below.
1676 * That is 39 bytes for the basic string, 16 bytes for the
1677 * biggest sense key (hardware error), 52 bytes for the
1678 * text of the largest sense qualifier valid for a CDROM,
1679 * (0x72, 0x03 or 0x04, 0x03), and one byte for the
1680 * null terminating character. To allow for longer strings,
1681 * the announce buffer is 120 bytes.
1683 * We need to call disk_setdiskinfo() before the disk
1684 * subsystem will allow any opens. Because additional
1685 * probe code is in cdopen() we do this now whether a CD
1686 * is present or not.
1688 struct scsi_read_capacity_data
*rdcap
;
1689 struct disk_info info
;
1690 char announce_buf
[120];
1691 struct cd_params
*cdp
;
1694 cdp
= &softc
->params
;
1695 bzero(&info
, sizeof(info
));
1696 info
.d_type
= DTYPE_SCSI
;
1697 info
.d_dsflags
&= ~DSO_COMPATLABEL
;
1698 info
.d_dsflags
|= DSO_NOLABELS
| DSO_COMPATPARTA
;
1699 info
.d_serialno
= xpt_path_serialno(periph
->path
);
1701 rdcap
= (struct scsi_read_capacity_data
*)csio
->data_ptr
;
1703 cdp
->disksize
= scsi_4btoul (rdcap
->addr
) + 1;
1704 cdp
->blksize
= scsi_4btoul (rdcap
->length
);
1706 if ((csio
->ccb_h
.status
& CAM_STATUS_MASK
) == CAM_REQ_CMP
) {
1707 ksnprintf(announce_buf
, sizeof(announce_buf
),
1708 "cd present [%lu x %lu byte records]",
1709 cdp
->disksize
, (u_long
)cdp
->blksize
);
1710 info
.d_media_blksize
= cdp
->blksize
;
1711 info
.d_media_blocks
= cdp
->disksize
;
1717 * Retry any UNIT ATTENTION type errors. They
1718 * are expected at boot.
1720 error
= cderror(done_ccb
, CAM_RETRY_SELTO
,
1721 SF_RETRY_UA
| SF_NO_PRINT
);
1722 if (error
== ERESTART
) {
1724 * A retry was scheuled, so
1728 } else if (error
!= 0) {
1729 struct scsi_sense_data
*sense
;
1731 int sense_key
, error_code
;
1734 struct ccb_getdev
*cgd
;
1736 /* Don't wedge this device's queue */
1737 cam_release_devq(done_ccb
->ccb_h
.path
,
1741 /*getcount_only*/0);
1743 status
= done_ccb
->ccb_h
.status
;
1745 cgd
= &xpt_alloc_ccb()->cgd
;
1746 xpt_setup_ccb(&cgd
->ccb_h
,
1747 done_ccb
->ccb_h
.path
,
1749 cgd
->ccb_h
.func_code
= XPT_GDEV_TYPE
;
1750 xpt_action((union ccb
*)cgd
);
1752 if (((csio
->ccb_h
.flags
& CAM_SENSE_PHYS
) != 0)
1753 || ((csio
->ccb_h
.flags
& CAM_SENSE_PTR
) != 0)
1754 || ((status
& CAM_AUTOSNS_VALID
) == 0))
1760 sense
= &csio
->sense_data
;
1761 scsi_extract_sense(sense
, &error_code
,
1766 * Attach to anything that claims to be a
1767 * CDROM or WORM device, as long as it
1768 * doesn't return a "Logical unit not
1769 * supported" (0x25) error.
1771 if ((have_sense
) && (asc
!= 0x25)
1772 && (error_code
== SSD_CURRENT_ERROR
)) {
1773 const char *sense_key_desc
;
1774 const char *asc_desc
;
1776 scsi_sense_desc(sense_key
, asc
, ascq
,
1780 ksnprintf(announce_buf
,
1781 sizeof(announce_buf
),
1782 "Attempt to query device "
1783 "size failed: %s, %s",
1786 info
.d_media_blksize
= 2048;
1788 } else if (SID_TYPE(&cgd
->inq_data
) == T_CDROM
) {
1790 * We only print out an error for
1791 * CDROM type devices. For WORM
1792 * devices, we don't print out an
1793 * error since a few WORM devices
1794 * don't support CDROM commands.
1795 * If we have sense information, go
1796 * ahead and print it out.
1797 * Otherwise, just say that we
1802 * Just print out the error, not
1803 * the full probe message, when we
1810 xpt_print(periph
->path
,
1811 "got CAM status %#x\n",
1812 done_ccb
->ccb_h
.status
);
1814 xpt_print(periph
->path
, "fatal error, "
1815 "failed to attach to device\n");
1817 * Invalidate this peripheral.
1819 cam_periph_invalidate(periph
);
1821 announce_buf
[0] = '\0';
1825 * Invalidate this peripheral.
1827 cam_periph_invalidate(periph
);
1828 announce_buf
[0] = '\0';
1830 xpt_free_ccb(&cgd
->ccb_h
);
1833 kfree(rdcap
, M_SCSICD
);
1834 if (announce_buf
[0] != '\0') {
1835 xpt_announce_periph(periph
, announce_buf
);
1836 if (softc
->flags
& CD_FLAG_CHANGER
)
1837 cdchangerschedule(softc
);
1839 * Create our sysctl variables, now that we know
1840 * we have successfully attached.
1842 taskqueue_enqueue(taskqueue_thread
[mycpuid
],
1843 &softc
->sysctl_task
);
1845 softc
->state
= CD_STATE_NORMAL
;
1847 * Since our peripheral may be invalidated by an error
1848 * above or an external event, we must release our CCB
1849 * before releasing the probe lock on the peripheral.
1850 * The peripheral will only go away once the last lock
1851 * is removed, and we need it around for the CCB release
1854 xpt_release_ccb(done_ccb
);
1855 cam_periph_unhold(periph
, 0);
1857 disk_setdiskinfo(&softc
->disk
, &info
);
1861 case CD_CCB_WAITING
:
1863 /* Caller will release the CCB */
1864 CAM_DEBUG(periph
->path
, CAM_DEBUG_TRACE
,
1865 ("trying to wakeup ccbwait\n"));
1867 wakeup(&done_ccb
->ccb_h
.cbfcnp
);
1871 /* Caller releases CCB */
1872 wakeup(&done_ccb
->ccb_h
.cbfcnp
);
1877 xpt_release_ccb(done_ccb
);
1880 static union cd_pages
*
1881 cdgetpage(struct cd_mode_params
*mode_params
)
1883 union cd_pages
*page
;
1885 if (mode_params
->cdb_size
== 10)
1886 page
= (union cd_pages
*)find_mode_page_10(
1887 (struct scsi_mode_header_10
*)mode_params
->mode_buf
);
1889 page
= (union cd_pages
*)find_mode_page_6(
1890 (struct scsi_mode_header_6
*)mode_params
->mode_buf
);
1896 cdgetpagesize(int page_num
)
1900 for (i
= 0; i
< NELEM(cd_page_size_table
); i
++) {
1901 if (cd_page_size_table
[i
].page
== page_num
)
1902 return (cd_page_size_table
[i
].page_size
);
1908 cdioctl(struct dev_ioctl_args
*ap
)
1910 cdev_t dev
= ap
->a_head
.a_dev
;
1911 caddr_t addr
= ap
->a_data
;
1912 struct cam_periph
*periph
;
1913 struct cd_softc
*softc
;
1914 int unit
, error
= 0;
1918 periph
= cam_extend_get(cdperiphs
, unit
);
1922 cam_periph_lock(periph
);
1923 CAM_DEBUG(periph
->path
, CAM_DEBUG_TRACE
, ("entering cdioctl\n"));
1925 softc
= (struct cd_softc
*)periph
->softc
;
1927 CAM_DEBUG(periph
->path
, CAM_DEBUG_TRACE
,
1928 ("trying to do ioctl %#lx\n", ap
->a_cmd
));
1930 if ((error
= cam_periph_hold(periph
, PCATCH
)) != 0) {
1931 cam_periph_unlock(periph
);
1932 cam_periph_release(periph
);
1937 * If we don't have media loaded, check for it. If still don't
1938 * have media loaded, we can only do a load or eject.
1940 * We only care whether media is loaded if this is a cd-specific ioctl
1941 * (thus the IOCGROUP check below). Note that this will break if
1942 * anyone adds any ioctls into the switch statement below that don't
1943 * have their ioctl group set to 'c'.
1945 if (((softc
->flags
& CD_FLAG_VALID_MEDIA
) == 0)
1946 && ((ap
->a_cmd
!= CDIOCCLOSE
)
1947 && (ap
->a_cmd
!= CDIOCEJECT
))
1948 && (IOCGROUP(ap
->a_cmd
) == 'c')) {
1949 error
= cdcheckmedia(periph
);
1951 cam_periph_unhold(periph
, 1);
1956 * Drop the lock here so later mallocs can use WAITOK. The periph
1957 * is essentially locked still with the cam_periph_hold call above.
1959 cam_periph_unlock(periph
);
1961 switch (ap
->a_cmd
) {
1963 case CDIOCPLAYTRACKS
:
1965 struct ioc_play_track
*args
1966 = (struct ioc_play_track
*)addr
;
1967 struct cd_mode_params params
;
1968 union cd_pages
*page
;
1970 params
.alloc_len
= sizeof(union cd_mode_data_6_10
);
1971 params
.mode_buf
= kmalloc(params
.alloc_len
, M_SCSICD
,
1974 cam_periph_lock(periph
);
1975 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
1976 ("trying to do CDIOCPLAYTRACKS\n"));
1978 error
= cdgetmode(periph
, ¶ms
, AUDIO_PAGE
);
1980 kfree(params
.mode_buf
, M_SCSICD
);
1981 cam_periph_unlock(periph
);
1984 page
= cdgetpage(¶ms
);
1986 page
->audio
.flags
&= ~CD_PA_SOTC
;
1987 page
->audio
.flags
|= CD_PA_IMMED
;
1988 error
= cdsetmode(periph
, ¶ms
);
1989 kfree(params
.mode_buf
, M_SCSICD
);
1991 cam_periph_unlock(periph
);
1996 * This was originally implemented with the PLAY
1997 * AUDIO TRACK INDEX command, but that command was
1998 * deprecated after SCSI-2. Most (all?) SCSI CDROM
1999 * drives support it but ATAPI and ATAPI-derivative
2000 * drives don't seem to support it. So we keep a
2001 * cache of the table of contents and translate
2002 * track numbers to MSF format.
2004 if (softc
->flags
& CD_FLAG_VALID_TOC
) {
2005 union msf_lba
*sentry
, *eentry
;
2008 if (args
->end_track
<
2009 softc
->toc
.header
.ending_track
+ 1)
2011 if (args
->end_track
>
2012 softc
->toc
.header
.ending_track
+ 1)
2014 softc
->toc
.header
.ending_track
+ 1;
2015 st
= args
->start_track
-
2016 softc
->toc
.header
.starting_track
;
2017 et
= args
->end_track
-
2018 softc
->toc
.header
.starting_track
;
2021 || (st
> (softc
->toc
.header
.ending_track
-
2022 softc
->toc
.header
.starting_track
))) {
2026 sentry
= &softc
->toc
.entries
[st
].addr
;
2027 eentry
= &softc
->toc
.entries
[et
].addr
;
2028 error
= cdplaymsf(periph
,
2037 * If we don't have a valid TOC, try the
2038 * play track index command. It is part of
2039 * the SCSI-2 spec, but was removed in the
2040 * MMC specs. ATAPI and ATAPI-derived
2041 * drives don't support it.
2043 if (softc
->quirks
& CD_Q_BCD_TRACKS
) {
2045 bin2bcd(args
->start_track
);
2047 bin2bcd(args
->end_track
);
2049 error
= cdplaytracks(periph
,
2055 cam_periph_unlock(periph
);
2060 struct ioc_play_msf
*args
2061 = (struct ioc_play_msf
*) addr
;
2062 struct cd_mode_params params
;
2063 union cd_pages
*page
;
2065 params
.alloc_len
= sizeof(union cd_mode_data_6_10
);
2066 params
.mode_buf
= kmalloc(params
.alloc_len
, M_SCSICD
,
2069 cam_periph_lock(periph
);
2070 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2071 ("trying to do CDIOCPLAYMSF\n"));
2073 error
= cdgetmode(periph
, ¶ms
, AUDIO_PAGE
);
2075 kfree(params
.mode_buf
, M_SCSICD
);
2076 cam_periph_unlock(periph
);
2079 page
= cdgetpage(¶ms
);
2081 page
->audio
.flags
&= ~CD_PA_SOTC
;
2082 page
->audio
.flags
|= CD_PA_IMMED
;
2083 error
= cdsetmode(periph
, ¶ms
);
2084 kfree(params
.mode_buf
, M_SCSICD
);
2086 cam_periph_unlock(periph
);
2089 error
= cdplaymsf(periph
,
2096 cam_periph_unlock(periph
);
2099 case CDIOCPLAYBLOCKS
:
2101 struct ioc_play_blocks
*args
2102 = (struct ioc_play_blocks
*) addr
;
2103 struct cd_mode_params params
;
2104 union cd_pages
*page
;
2106 params
.alloc_len
= sizeof(union cd_mode_data_6_10
);
2107 params
.mode_buf
= kmalloc(params
.alloc_len
, M_SCSICD
,
2109 cam_periph_lock(periph
);
2110 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2111 ("trying to do CDIOCPLAYBLOCKS\n"));
2114 error
= cdgetmode(periph
, ¶ms
, AUDIO_PAGE
);
2116 kfree(params
.mode_buf
, M_SCSICD
);
2117 cam_periph_unlock(periph
);
2120 page
= cdgetpage(¶ms
);
2122 page
->audio
.flags
&= ~CD_PA_SOTC
;
2123 page
->audio
.flags
|= CD_PA_IMMED
;
2124 error
= cdsetmode(periph
, ¶ms
);
2125 kfree(params
.mode_buf
, M_SCSICD
);
2127 cam_periph_unlock(periph
);
2130 error
= cdplay(periph
, args
->blk
, args
->len
);
2131 cam_periph_unlock(periph
);
2134 case CDIOCREADSUBCHANNEL
:
2136 struct ioc_read_subchannel
*args
2137 = (struct ioc_read_subchannel
*) addr
;
2138 struct cd_sub_channel_info
*data
;
2139 u_int32_t len
= args
->data_len
;
2141 data
= kmalloc(sizeof(struct cd_sub_channel_info
),
2142 M_SCSICD
, M_WAITOK
);
2144 cam_periph_lock(periph
);
2145 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2146 ("trying to do CDIOCREADSUBCHANNEL\n"));
2148 if ((len
> sizeof(struct cd_sub_channel_info
)) ||
2149 (len
< sizeof(struct cd_sub_channel_header
))) {
2151 "scsi_cd: cdioctl: "
2152 "cdioreadsubchannel: error, len=%d\n",
2155 kfree(data
, M_SCSICD
);
2156 cam_periph_unlock(periph
);
2160 if (softc
->quirks
& CD_Q_BCD_TRACKS
)
2161 args
->track
= bin2bcd(args
->track
);
2163 error
= cdreadsubchannel(periph
, args
->address_format
,
2164 args
->data_format
, args
->track
, data
, len
);
2167 kfree(data
, M_SCSICD
);
2168 cam_periph_unlock(periph
);
2171 if (softc
->quirks
& CD_Q_BCD_TRACKS
)
2172 data
->what
.track_info
.track_number
=
2173 bcd2bin(data
->what
.track_info
.track_number
);
2174 len
= min(len
, ((data
->header
.data_len
[0] << 8) +
2175 data
->header
.data_len
[1] +
2176 sizeof(struct cd_sub_channel_header
)));
2177 cam_periph_unlock(periph
);
2178 if (copyout(data
, args
->data
, len
) != 0) {
2181 kfree(data
, M_SCSICD
);
2185 case CDIOREADTOCHEADER
:
2187 struct ioc_toc_header
*th
;
2189 th
= kmalloc(sizeof(struct ioc_toc_header
), M_SCSICD
,
2192 cam_periph_lock(periph
);
2193 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2194 ("trying to do CDIOREADTOCHEADER\n"));
2196 error
= cdreadtoc(periph
, 0, 0, (u_int8_t
*)th
,
2197 sizeof (*th
), /*sense_flags*/0);
2199 kfree(th
, M_SCSICD
);
2200 cam_periph_unlock(periph
);
2203 if (softc
->quirks
& CD_Q_BCD_TRACKS
) {
2204 /* we are going to have to convert the BCD
2205 * encoding on the cd to what is expected
2207 th
->starting_track
=
2208 bcd2bin(th
->starting_track
);
2209 th
->ending_track
= bcd2bin(th
->ending_track
);
2211 th
->len
= ntohs(th
->len
);
2212 bcopy(th
, addr
, sizeof(*th
));
2213 kfree(th
, M_SCSICD
);
2214 cam_periph_unlock(periph
);
2217 case CDIOREADTOCENTRYS
:
2219 struct cd_tocdata
*data
;
2220 struct cd_toc_single
*lead
;
2221 struct ioc_read_toc_entry
*te
=
2222 (struct ioc_read_toc_entry
*) addr
;
2223 struct ioc_toc_header
*th
;
2224 u_int32_t len
, readlen
, idx
, num
;
2225 u_int32_t starting_track
= te
->starting_track
;
2227 data
= kmalloc(sizeof(*data
), M_SCSICD
, M_WAITOK
);
2228 lead
= kmalloc(sizeof(*lead
), M_SCSICD
, M_WAITOK
);
2230 cam_periph_lock(periph
);
2231 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2232 ("trying to do CDIOREADTOCENTRYS\n"));
2234 if (te
->data_len
< sizeof(struct cd_toc_entry
)
2235 || (te
->data_len
% sizeof(struct cd_toc_entry
)) != 0
2236 || (te
->address_format
!= CD_MSF_FORMAT
2237 && te
->address_format
!= CD_LBA_FORMAT
)) {
2239 kprintf("scsi_cd: error in readtocentries, "
2240 "returning EINVAL\n");
2241 kfree(data
, M_SCSICD
);
2242 kfree(lead
, M_SCSICD
);
2243 cam_periph_unlock(periph
);
2248 error
= cdreadtoc(periph
, 0, 0, (u_int8_t
*)th
,
2249 sizeof (*th
), /*sense_flags*/0);
2251 kfree(data
, M_SCSICD
);
2252 kfree(lead
, M_SCSICD
);
2253 cam_periph_unlock(periph
);
2257 if (softc
->quirks
& CD_Q_BCD_TRACKS
) {
2258 /* we are going to have to convert the BCD
2259 * encoding on the cd to what is expected
2261 th
->starting_track
=
2262 bcd2bin(th
->starting_track
);
2263 th
->ending_track
= bcd2bin(th
->ending_track
);
2266 if (starting_track
== 0)
2267 starting_track
= th
->starting_track
;
2268 else if (starting_track
== LEADOUT
)
2269 starting_track
= th
->ending_track
+ 1;
2270 else if (starting_track
< th
->starting_track
||
2271 starting_track
> th
->ending_track
+ 1) {
2272 kprintf("scsi_cd: error in readtocentries, "
2273 "returning EINVAL\n");
2274 kfree(data
, M_SCSICD
);
2275 kfree(lead
, M_SCSICD
);
2276 cam_periph_unlock(periph
);
2281 /* calculate reading length without leadout entry */
2282 readlen
= (th
->ending_track
- starting_track
+ 1) *
2283 sizeof(struct cd_toc_entry
);
2285 /* and with leadout entry */
2286 len
= readlen
+ sizeof(struct cd_toc_entry
);
2287 if (te
->data_len
< len
) {
2292 if (len
> sizeof(data
->entries
)) {
2293 kprintf("scsi_cd: error in readtocentries, "
2294 "returning EINVAL\n");
2296 kfree(data
, M_SCSICD
);
2297 kfree(lead
, M_SCSICD
);
2298 cam_periph_unlock(periph
);
2301 num
= len
/ sizeof(struct cd_toc_entry
);
2304 error
= cdreadtoc(periph
, te
->address_format
,
2307 readlen
+ sizeof (*th
),
2310 kfree(data
, M_SCSICD
);
2311 kfree(lead
, M_SCSICD
);
2312 cam_periph_unlock(periph
);
2317 /* make leadout entry if needed */
2318 idx
= starting_track
+ num
- 1;
2319 if (softc
->quirks
& CD_Q_BCD_TRACKS
)
2320 th
->ending_track
= bcd2bin(th
->ending_track
);
2321 if (idx
== th
->ending_track
+ 1) {
2322 error
= cdreadtoc(periph
, te
->address_format
,
2323 LEADOUT
, (u_int8_t
*)lead
,
2327 kfree(data
, M_SCSICD
);
2328 kfree(lead
, M_SCSICD
);
2329 cam_periph_unlock(periph
);
2332 data
->entries
[idx
- starting_track
] =
2335 if (softc
->quirks
& CD_Q_BCD_TRACKS
) {
2336 for (idx
= 0; idx
< num
- 1; idx
++) {
2337 data
->entries
[idx
].track
=
2338 bcd2bin(data
->entries
[idx
].track
);
2342 cam_periph_unlock(periph
);
2343 error
= copyout(data
->entries
, te
->data
, len
);
2344 kfree(data
, M_SCSICD
);
2345 kfree(lead
, M_SCSICD
);
2348 case CDIOREADTOCENTRY
:
2350 struct cd_toc_single
*data
;
2351 struct ioc_read_toc_single_entry
*te
=
2352 (struct ioc_read_toc_single_entry
*) addr
;
2353 struct ioc_toc_header
*th
;
2356 data
= kmalloc(sizeof(*data
), M_SCSICD
, M_WAITOK
);
2358 cam_periph_lock(periph
);
2359 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2360 ("trying to do CDIOREADTOCENTRY\n"));
2362 if (te
->address_format
!= CD_MSF_FORMAT
2363 && te
->address_format
!= CD_LBA_FORMAT
) {
2364 kprintf("error in readtocentry, "
2365 " returning EINVAL\n");
2366 kfree(data
, M_SCSICD
);
2368 cam_periph_unlock(periph
);
2373 error
= cdreadtoc(periph
, 0, 0, (u_int8_t
*)th
,
2374 sizeof (*th
), /*sense_flags*/0);
2376 kfree(data
, M_SCSICD
);
2377 cam_periph_unlock(periph
);
2381 if (softc
->quirks
& CD_Q_BCD_TRACKS
) {
2382 /* we are going to have to convert the BCD
2383 * encoding on the cd to what is expected
2385 th
->starting_track
=
2386 bcd2bin(th
->starting_track
);
2387 th
->ending_track
= bcd2bin(th
->ending_track
);
2391 track
= th
->starting_track
;
2392 else if (track
== LEADOUT
)
2394 else if (track
< th
->starting_track
||
2395 track
> th
->ending_track
+ 1) {
2396 kprintf("error in readtocentry, "
2397 " returning EINVAL\n");
2398 kfree(data
, M_SCSICD
);
2400 cam_periph_unlock(periph
);
2404 error
= cdreadtoc(periph
, te
->address_format
, track
,
2405 (u_int8_t
*)data
, sizeof(*data
),
2408 kfree(data
, M_SCSICD
);
2409 cam_periph_unlock(periph
);
2413 if (softc
->quirks
& CD_Q_BCD_TRACKS
)
2414 data
->entry
.track
= bcd2bin(data
->entry
.track
);
2415 bcopy(&data
->entry
, &te
->entry
,
2416 sizeof(struct cd_toc_entry
));
2417 kfree(data
, M_SCSICD
);
2418 cam_periph_unlock(periph
);
2423 struct ioc_patch
*arg
= (struct ioc_patch
*)addr
;
2424 struct cd_mode_params params
;
2425 union cd_pages
*page
;
2427 params
.alloc_len
= sizeof(union cd_mode_data_6_10
);
2428 params
.mode_buf
= kmalloc(params
.alloc_len
, M_SCSICD
,
2431 cam_periph_lock(periph
);
2432 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2433 ("trying to do CDIOCSETPATCH\n"));
2435 error
= cdgetmode(periph
, ¶ms
, AUDIO_PAGE
);
2437 kfree(params
.mode_buf
, M_SCSICD
);
2438 cam_periph_unlock(periph
);
2441 page
= cdgetpage(¶ms
);
2443 page
->audio
.port
[LEFT_PORT
].channels
=
2445 page
->audio
.port
[RIGHT_PORT
].channels
=
2447 page
->audio
.port
[2].channels
= arg
->patch
[2];
2448 page
->audio
.port
[3].channels
= arg
->patch
[3];
2449 error
= cdsetmode(periph
, ¶ms
);
2450 kfree(params
.mode_buf
, M_SCSICD
);
2451 cam_periph_unlock(periph
);
2456 struct ioc_vol
*arg
= (struct ioc_vol
*) addr
;
2457 struct cd_mode_params params
;
2458 union cd_pages
*page
;
2460 params
.alloc_len
= sizeof(union cd_mode_data_6_10
);
2461 params
.mode_buf
= kmalloc(params
.alloc_len
, M_SCSICD
,
2464 cam_periph_lock(periph
);
2465 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2466 ("trying to do CDIOCGETVOL\n"));
2468 error
= cdgetmode(periph
, ¶ms
, AUDIO_PAGE
);
2470 kfree(params
.mode_buf
, M_SCSICD
);
2471 cam_periph_unlock(periph
);
2474 page
= cdgetpage(¶ms
);
2476 arg
->vol
[LEFT_PORT
] =
2477 page
->audio
.port
[LEFT_PORT
].volume
;
2478 arg
->vol
[RIGHT_PORT
] =
2479 page
->audio
.port
[RIGHT_PORT
].volume
;
2480 arg
->vol
[2] = page
->audio
.port
[2].volume
;
2481 arg
->vol
[3] = page
->audio
.port
[3].volume
;
2482 kfree(params
.mode_buf
, M_SCSICD
);
2483 cam_periph_unlock(periph
);
2488 struct ioc_vol
*arg
= (struct ioc_vol
*) addr
;
2489 struct cd_mode_params params
;
2490 union cd_pages
*page
;
2492 params
.alloc_len
= sizeof(union cd_mode_data_6_10
);
2493 params
.mode_buf
= kmalloc(params
.alloc_len
, M_SCSICD
,
2496 cam_periph_lock(periph
);
2497 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2498 ("trying to do CDIOCSETVOL\n"));
2500 error
= cdgetmode(periph
, ¶ms
, AUDIO_PAGE
);
2502 kfree(params
.mode_buf
, M_SCSICD
);
2503 cam_periph_unlock(periph
);
2506 page
= cdgetpage(¶ms
);
2508 page
->audio
.port
[LEFT_PORT
].channels
= CHANNEL_0
;
2509 page
->audio
.port
[LEFT_PORT
].volume
=
2510 arg
->vol
[LEFT_PORT
];
2511 page
->audio
.port
[RIGHT_PORT
].channels
= CHANNEL_1
;
2512 page
->audio
.port
[RIGHT_PORT
].volume
=
2513 arg
->vol
[RIGHT_PORT
];
2514 page
->audio
.port
[2].volume
= arg
->vol
[2];
2515 page
->audio
.port
[3].volume
= arg
->vol
[3];
2516 error
= cdsetmode(periph
, ¶ms
);
2517 cam_periph_unlock(periph
);
2518 kfree(params
.mode_buf
, M_SCSICD
);
2523 struct cd_mode_params params
;
2524 union cd_pages
*page
;
2526 params
.alloc_len
= sizeof(union cd_mode_data_6_10
);
2527 params
.mode_buf
= kmalloc(params
.alloc_len
, M_SCSICD
,
2530 cam_periph_lock(periph
);
2531 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2532 ("trying to do CDIOCSETMONO\n"));
2534 error
= cdgetmode(periph
, ¶ms
, AUDIO_PAGE
);
2536 kfree(params
.mode_buf
, M_SCSICD
);
2537 cam_periph_unlock(periph
);
2540 page
= cdgetpage(¶ms
);
2542 page
->audio
.port
[LEFT_PORT
].channels
=
2543 LEFT_CHANNEL
| RIGHT_CHANNEL
;
2544 page
->audio
.port
[RIGHT_PORT
].channels
=
2545 LEFT_CHANNEL
| RIGHT_CHANNEL
;
2546 page
->audio
.port
[2].channels
= 0;
2547 page
->audio
.port
[3].channels
= 0;
2548 error
= cdsetmode(periph
, ¶ms
);
2549 cam_periph_unlock(periph
);
2550 kfree(params
.mode_buf
, M_SCSICD
);
2553 case CDIOCSETSTEREO
:
2555 struct cd_mode_params params
;
2556 union cd_pages
*page
;
2558 params
.alloc_len
= sizeof(union cd_mode_data_6_10
);
2559 params
.mode_buf
= kmalloc(params
.alloc_len
, M_SCSICD
,
2562 cam_periph_lock(periph
);
2563 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2564 ("trying to do CDIOCSETSTEREO\n"));
2566 error
= cdgetmode(periph
, ¶ms
, AUDIO_PAGE
);
2568 kfree(params
.mode_buf
, M_SCSICD
);
2569 cam_periph_unlock(periph
);
2572 page
= cdgetpage(¶ms
);
2574 page
->audio
.port
[LEFT_PORT
].channels
=
2576 page
->audio
.port
[RIGHT_PORT
].channels
=
2578 page
->audio
.port
[2].channels
= 0;
2579 page
->audio
.port
[3].channels
= 0;
2580 error
= cdsetmode(periph
, ¶ms
);
2581 kfree(params
.mode_buf
, M_SCSICD
);
2582 cam_periph_unlock(periph
);
2587 struct cd_mode_params params
;
2588 union cd_pages
*page
;
2590 params
.alloc_len
= sizeof(union cd_mode_data_6_10
);
2591 params
.mode_buf
= kmalloc(params
.alloc_len
, M_SCSICD
,
2594 cam_periph_lock(periph
);
2595 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2596 ("trying to do CDIOCSETMUTE\n"));
2598 error
= cdgetmode(periph
, ¶ms
, AUDIO_PAGE
);
2600 kfree(¶ms
, M_SCSICD
);
2601 cam_periph_unlock(periph
);
2604 page
= cdgetpage(¶ms
);
2606 page
->audio
.port
[LEFT_PORT
].channels
= 0;
2607 page
->audio
.port
[RIGHT_PORT
].channels
= 0;
2608 page
->audio
.port
[2].channels
= 0;
2609 page
->audio
.port
[3].channels
= 0;
2610 error
= cdsetmode(periph
, ¶ms
);
2611 kfree(params
.mode_buf
, M_SCSICD
);
2612 cam_periph_unlock(periph
);
2617 struct cd_mode_params params
;
2618 union cd_pages
*page
;
2620 params
.alloc_len
= sizeof(union cd_mode_data_6_10
);
2621 params
.mode_buf
= kmalloc(params
.alloc_len
, M_SCSICD
,
2624 cam_periph_lock(periph
);
2625 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2626 ("trying to do CDIOCSETLEFT\n"));
2628 error
= cdgetmode(periph
, ¶ms
, AUDIO_PAGE
);
2630 kfree(params
.mode_buf
, M_SCSICD
);
2631 cam_periph_unlock(periph
);
2634 page
= cdgetpage(¶ms
);
2636 page
->audio
.port
[LEFT_PORT
].channels
= LEFT_CHANNEL
;
2637 page
->audio
.port
[RIGHT_PORT
].channels
= LEFT_CHANNEL
;
2638 page
->audio
.port
[2].channels
= 0;
2639 page
->audio
.port
[3].channels
= 0;
2640 error
= cdsetmode(periph
, ¶ms
);
2641 kfree(params
.mode_buf
, M_SCSICD
);
2642 cam_periph_unlock(periph
);
2647 struct cd_mode_params params
;
2648 union cd_pages
*page
;
2650 params
.alloc_len
= sizeof(union cd_mode_data_6_10
);
2651 params
.mode_buf
= kmalloc(params
.alloc_len
, M_SCSICD
,
2654 cam_periph_lock(periph
);
2655 CAM_DEBUG(periph
->path
, CAM_DEBUG_SUBTRACE
,
2656 ("trying to do CDIOCSETRIGHT\n"));
2658 error
= cdgetmode(periph
, ¶ms
, AUDIO_PAGE
);
2660 kfree(params
.mode_buf
, M_SCSICD
);
2661 cam_periph_unlock(periph
);
2664 page
= cdgetpage(¶ms
);
2666 page
->audio
.port
[LEFT_PORT
].channels
= RIGHT_CHANNEL
;
2667 page
->audio
.port
[RIGHT_PORT
].channels
= RIGHT_CHANNEL
;
2668 page
->audio
.port
[2].channels
= 0;
2669 page
->audio
.port
[3].channels
= 0;
2670 error
= cdsetmode(periph
, ¶ms
);
2671 kfree(params
.mode_buf
, M_SCSICD
);
2672 cam_periph_unlock(periph
);
2676 cam_periph_lock(periph
);
2677 error
= cdpause(periph
, 1);
2678 cam_periph_unlock(periph
);
2681 cam_periph_lock(periph
);
2682 error
= cdpause(periph
, 0);
2683 cam_periph_unlock(periph
);
2686 cam_periph_lock(periph
);
2687 error
= cdstartunit(periph
, 0);
2688 cam_periph_unlock(periph
);
2691 cam_periph_lock(periph
);
2692 error
= cdstartunit(periph
, 1);
2693 cam_periph_unlock(periph
);
2696 cam_periph_lock(periph
);
2697 error
= cdstopunit(periph
, 0);
2698 cam_periph_unlock(periph
);
2701 cam_periph_lock(periph
);
2702 error
= cdstopunit(periph
, 1);
2703 cam_periph_unlock(periph
);
2706 cam_periph_lock(periph
);
2707 cdprevent(periph
, PR_ALLOW
);
2708 cam_periph_unlock(periph
);
2711 cam_periph_lock(periph
);
2712 cdprevent(periph
, PR_PREVENT
);
2713 cam_periph_unlock(periph
);
2716 /* sc_link->flags |= (SDEV_DB1 | SDEV_DB2); */
2720 /* sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2); */
2724 /* return (cd_reset(periph)); */
2727 case CDRIOCREADSPEED
:
2728 cam_periph_lock(periph
);
2729 error
= cdsetspeed(periph
, *(u_int32_t
*)addr
, CDR_MAX_SPEED
);
2730 cam_periph_unlock(periph
);
2732 case CDRIOCWRITESPEED
:
2733 cam_periph_lock(periph
);
2734 error
= cdsetspeed(periph
, CDR_MAX_SPEED
, *(u_int32_t
*)addr
);
2735 cam_periph_unlock(periph
);
2738 case DVDIOCREPORTKEY
: {
2739 struct dvd_authinfo
*authinfo
;
2741 authinfo
= (struct dvd_authinfo
*)addr
;
2743 cam_periph_lock(periph
);
2744 if (ap
->a_cmd
== DVDIOCREPORTKEY
)
2745 error
= cdreportkey(periph
, authinfo
);
2747 error
= cdsendkey(periph
, authinfo
);
2748 cam_periph_unlock(periph
);
2751 case DVDIOCREADSTRUCTURE
: {
2752 struct dvd_struct
*dvdstruct
;
2754 dvdstruct
= (struct dvd_struct
*)addr
;
2756 cam_periph_lock(periph
);
2757 error
= cdreaddvdstructure(periph
, dvdstruct
);
2758 cam_periph_unlock(periph
);
2763 cam_periph_lock(periph
);
2764 error
= cam_periph_ioctl(periph
, ap
->a_cmd
, addr
, cderror
);
2765 cam_periph_unlock(periph
);
2769 cam_periph_lock(periph
);
2770 CAM_DEBUG(periph
->path
, CAM_DEBUG_TRACE
, ("leaving cdioctl\n"));
2771 cam_periph_unhold(periph
, 1);
2777 cdprevent(struct cam_periph
*periph
, int action
)
2780 struct cd_softc
*softc
;
2783 CAM_DEBUG(periph
->path
, CAM_DEBUG_TRACE
, ("entering cdprevent\n"));
2785 softc
= (struct cd_softc
*)periph
->softc
;
2787 if (((action
== PR_ALLOW
)
2788 && (softc
->flags
& CD_FLAG_DISC_LOCKED
) == 0)
2789 || ((action
== PR_PREVENT
)
2790 && (softc
->flags
& CD_FLAG_DISC_LOCKED
) != 0)) {
2794 ccb
= cdgetccb(periph
, /* priority */ 1);
2796 scsi_prevent(&ccb
->csio
,
2802 /* timeout */60000);
2804 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
2805 /*sense_flags*/SF_RETRY_UA
|SF_NO_PRINT
);
2807 xpt_release_ccb(ccb
);
2810 if (action
== PR_ALLOW
)
2811 softc
->flags
&= ~CD_FLAG_DISC_LOCKED
;
2813 softc
->flags
|= CD_FLAG_DISC_LOCKED
;
2818 cdcheckmedia(struct cam_periph
*periph
)
2820 struct cd_softc
*softc
;
2821 struct ioc_toc_header
*toch
;
2822 struct cd_toc_single leadout
;
2823 struct ccb_getdev
*cgd
;
2824 u_int32_t size
, toclen
;
2825 int error
, num_entries
, cdindex
;
2826 int first_track_audio
;
2827 struct disk_info info
;
2829 softc
= (struct cd_softc
*)periph
->softc
;
2831 first_track_audio
= -1;
2835 * Set up disk info fields and tell the disk subsystem to reset
2836 * its internal copy of the label.
2838 bzero(&info
, sizeof(info
));
2839 info
.d_type
= DTYPE_SCSI
;
2840 info
.d_dsflags
&= ~DSO_COMPATLABEL
;
2841 info
.d_dsflags
|= DSO_NOLABELS
| DSO_COMPATPARTA
;
2842 info
.d_serialno
= xpt_path_serialno(periph
->path
);
2845 * Grab the inquiry data to get the vendor and product names.
2846 * Put them in the typename and packname for the label.
2848 cgd
= &xpt_alloc_ccb()->cgd
;
2849 xpt_setup_ccb(&cgd
->ccb_h
, periph
->path
, /*priority*/ 1);
2850 cgd
->ccb_h
.func_code
= XPT_GDEV_TYPE
;
2851 xpt_action((union ccb
*)cgd
);
2854 strncpy(label
->d_typename
, cgd
->inq_data
.vendor
,
2855 min(SID_VENDOR_SIZE
, sizeof(label
->d_typename
)));
2856 strncpy(label
->d_packname
, cgd
->inq_data
.product
,
2857 min(SID_PRODUCT_SIZE
, sizeof(label
->d_packname
)));
2859 xpt_free_ccb(&cgd
->ccb_h
);
2862 * Clear the valid media and TOC flags until we've verified that we
2865 softc
->flags
&= ~(CD_FLAG_VALID_MEDIA
|CD_FLAG_VALID_TOC
);
2868 * Get the disc size and block size. If we can't get it, we don't
2869 * have media, most likely.
2871 if ((error
= cdsize(periph
, &size
)) != 0) {
2873 * Set a bogus sector size, so the slice code won't try to
2874 * divide by 0 and panic the kernel.
2876 info
.d_media_blksize
= 2048;
2877 disk_setdiskinfo(&softc
->disk
, &info
);
2880 * Tell devstat(9) we don't have a blocksize.
2882 softc
->device_stats
.flags
|= DEVSTAT_BS_UNAVAILABLE
;
2886 info
.d_media_blksize
= softc
->params
.blksize
;
2887 info
.d_media_blocks
= softc
->params
.disksize
;
2888 disk_setdiskinfo(&softc
->disk
, &info
);
2891 * We unconditionally (re)set the blocksize each time the
2892 * CD device is opened. This is because the CD can change,
2893 * and therefore the blocksize might change.
2894 * XXX problems here if some slice or partition is still
2895 * open with the old size?
2897 if ((softc
->device_stats
.flags
& DEVSTAT_BS_UNAVAILABLE
) != 0)
2898 softc
->device_stats
.flags
&= ~DEVSTAT_BS_UNAVAILABLE
;
2899 softc
->device_stats
.block_size
= softc
->params
.blksize
;
2901 softc
->flags
|= CD_FLAG_VALID_MEDIA
;
2905 * Now we check the table of contents. This (currently) is only
2906 * used for the CDIOCPLAYTRACKS ioctl. It may be used later to do
2907 * things like present a separate entry in /dev for each track,
2908 * like that acd(4) driver does.
2910 bzero(&softc
->toc
, sizeof(softc
->toc
));
2911 toch
= &softc
->toc
.header
;
2914 * We will get errors here for media that doesn't have a table of
2915 * contents. According to the MMC-3 spec: "When a Read TOC/PMA/ATIP
2916 * command is presented for a DDCD/CD-R/RW media, where the first TOC
2917 * has not been recorded (no complete session) and the Format codes
2918 * 0000b, 0001b, or 0010b are specified, this command shall be rejected
2919 * with an INVALID FIELD IN CDB. Devices that are not capable of
2920 * reading an incomplete session on DDC/CD-R/RW media shall report
2921 * CANNOT READ MEDIUM - INCOMPATIBLE FORMAT."
2923 * So this isn't fatal if we can't read the table of contents, it
2924 * just means that the user won't be able to issue the play tracks
2925 * ioctl, and likely lots of other stuff won't work either. They
2926 * need to burn the CD before we can do a whole lot with it. So
2927 * we don't print anything here if we get an error back.
2929 error
= cdreadtoc(periph
, 0, 0, (u_int8_t
*)toch
, sizeof(*toch
),
2932 * Errors in reading the table of contents aren't fatal, we just
2933 * won't have a valid table of contents cached.
2937 bzero(&softc
->toc
, sizeof(softc
->toc
));
2941 if (softc
->quirks
& CD_Q_BCD_TRACKS
) {
2942 toch
->starting_track
= bcd2bin(toch
->starting_track
);
2943 toch
->ending_track
= bcd2bin(toch
->ending_track
);
2946 /* Number of TOC entries, plus leadout */
2947 num_entries
= (toch
->ending_track
- toch
->starting_track
) + 2;
2949 if (num_entries
<= 0)
2952 toclen
= num_entries
* sizeof(struct cd_toc_entry
);
2954 error
= cdreadtoc(periph
, CD_MSF_FORMAT
, toch
->starting_track
,
2955 (u_int8_t
*)&softc
->toc
, toclen
+ sizeof(*toch
),
2959 bzero(&softc
->toc
, sizeof(softc
->toc
));
2963 if (softc
->quirks
& CD_Q_BCD_TRACKS
) {
2964 toch
->starting_track
= bcd2bin(toch
->starting_track
);
2965 toch
->ending_track
= bcd2bin(toch
->ending_track
);
2967 toch
->len
= scsi_2btoul((uint8_t *)&toch
->len
);
2970 * XXX KDM is this necessary? Probably only if the drive doesn't
2971 * return leadout information with the table of contents.
2973 cdindex
= toch
->starting_track
+ num_entries
-1;
2974 if (cdindex
== toch
->ending_track
+ 1) {
2976 error
= cdreadtoc(periph
, CD_MSF_FORMAT
, LEADOUT
,
2977 (u_int8_t
*)&leadout
, sizeof(leadout
),
2983 softc
->toc
.entries
[cdindex
- toch
->starting_track
] =
2986 if (softc
->quirks
& CD_Q_BCD_TRACKS
) {
2987 for (cdindex
= 0; cdindex
< (num_entries
- 1); cdindex
++) {
2988 softc
->toc
.entries
[cdindex
].track
=
2989 bcd2bin(softc
->toc
.entries
[cdindex
].track
);
2994 * Run through the TOC entries, find the first entry and determine
2995 * whether it is an audio or data track.
2997 for (cdindex
= 0; cdindex
< (num_entries
- 1); cdindex
++) {
2998 if (softc
->toc
.entries
[cdindex
].track
== toch
->starting_track
) {
2999 if (softc
->toc
.entries
[cdindex
].control
& 0x04)
3000 first_track_audio
= 0;
3002 first_track_audio
= 1;
3008 * If first_track_audio is non-zero, we either have an error (e.g.
3009 * couldn't find the starting track) or the first track is an audio
3010 * track. If first_track_audio is 0, the first track is a data
3011 * track that could have a disklabel. Attempt to read the
3012 * disklabel off the media, just in case the user put one there.
3014 if (first_track_audio
== 0) {
3015 info
.d_dsflags
|= DSO_COMPATLABEL
;
3016 info
.d_dsflags
&= ~DSO_NOLABELS
;
3017 disk_setdiskinfo(&softc
->disk
, &info
);
3019 softc
->flags
|= CD_FLAG_VALID_TOC
;
3026 cdsize(struct cam_periph
*periph
, u_int32_t
*size
)
3028 struct cd_softc
*softc
;
3030 struct scsi_read_capacity_data
*rcap_buf
;
3033 CAM_DEBUG(periph
->path
, CAM_DEBUG_TRACE
, ("entering cdsize\n"));
3035 softc
= (struct cd_softc
*)periph
->softc
;
3037 ccb
= cdgetccb(periph
, /* priority */ 1);
3039 rcap_buf
= kmalloc(sizeof(struct scsi_read_capacity_data
),
3040 M_SCSICD
, M_INTWAIT
| M_ZERO
);
3042 scsi_read_capacity(&ccb
->csio
,
3048 /* timeout */20000);
3050 if (softc
->flags
& CD_FLAG_CAP_MUTE
)
3051 ccb
->ccb_h
.flags
|= CAM_QUIET
;
3053 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3054 /*sense_flags*/SF_RETRY_UA
|SF_NO_PRINT
);
3056 xpt_release_ccb(ccb
);
3058 softc
->params
.disksize
= scsi_4btoul(rcap_buf
->addr
) + 1;
3059 softc
->params
.blksize
= scsi_4btoul(rcap_buf
->length
);
3061 * SCSI-3 mandates that the reported blocksize shall be 2048.
3062 * Older drives sometimes report funny values, trim it down to
3063 * 2048, or other parts of the kernel will get confused.
3065 * XXX we leave drives alone that might report 512 bytes, as
3066 * well as drives reporting more weird sizes like perhaps 4K.
3068 if (softc
->params
.blksize
> 2048 && softc
->params
.blksize
<= 2352)
3069 softc
->params
.blksize
= 2048;
3071 kfree(rcap_buf
, M_SCSICD
);
3072 *size
= softc
->params
.disksize
;
3079 cd6byteworkaround(union ccb
*ccb
)
3082 struct cam_periph
*periph
;
3083 struct cd_softc
*softc
;
3084 struct cd_mode_params
*params
;
3087 periph
= xpt_path_periph(ccb
->ccb_h
.path
);
3088 softc
= (struct cd_softc
*)periph
->softc
;
3090 cdb
= ccb
->csio
.cdb_io
.cdb_bytes
;
3092 if ((ccb
->ccb_h
.flags
& CAM_CDB_POINTER
)
3093 || ((cdb
[0] != MODE_SENSE_6
)
3094 && (cdb
[0] != MODE_SELECT_6
)))
3098 * Because there is no convenient place to stash the overall
3099 * cd_mode_params structure pointer, we have to grab it like this.
3100 * This means that ALL MODE_SENSE and MODE_SELECT requests in the
3101 * cd(4) driver MUST go through cdgetmode() and cdsetmode()!
3103 * XXX It would be nice if, at some point, we could increase the
3104 * number of available peripheral private pointers. Both pointers
3105 * are currently used in most every peripheral driver.
3109 STAILQ_FOREACH(params
, &softc
->mode_queue
, links
) {
3110 if (params
->mode_buf
== ccb
->csio
.data_ptr
) {
3117 * This shouldn't happen. All mode sense and mode select
3118 * operations in the cd(4) driver MUST go through cdgetmode() and
3122 xpt_print(periph
->path
,
3123 "mode buffer not found in mode queue!\n");
3127 params
->cdb_size
= 10;
3128 softc
->minimum_command_size
= 10;
3129 xpt_print(ccb
->ccb_h
.path
,
3130 "%s(6) failed, increasing minimum CDB size to 10 bytes\n",
3131 (cdb
[0] == MODE_SENSE_6
) ? "MODE_SENSE" : "MODE_SELECT");
3133 if (cdb
[0] == MODE_SENSE_6
) {
3134 struct scsi_mode_sense_10 ms10
;
3135 struct scsi_mode_sense_6
*ms6
;
3138 ms6
= (struct scsi_mode_sense_6
*)cdb
;
3140 bzero(&ms10
, sizeof(ms10
));
3141 ms10
.opcode
= MODE_SENSE_10
;
3142 ms10
.byte2
= ms6
->byte2
;
3143 ms10
.page
= ms6
->page
;
3146 * 10 byte mode header, block descriptor,
3147 * sizeof(union cd_pages)
3149 len
= sizeof(struct cd_mode_data_10
);
3150 ccb
->csio
.dxfer_len
= len
;
3152 scsi_ulto2b(len
, ms10
.length
);
3153 ms10
.control
= ms6
->control
;
3154 bcopy(&ms10
, cdb
, 10);
3155 ccb
->csio
.cdb_len
= 10;
3157 struct scsi_mode_select_10 ms10
;
3158 struct scsi_mode_select_6
*ms6
;
3159 struct scsi_mode_header_6
*header6
;
3160 struct scsi_mode_header_10
*header10
;
3161 struct scsi_mode_page_header
*page_header
;
3162 int blk_desc_len
, page_num
, page_size
, len
;
3164 ms6
= (struct scsi_mode_select_6
*)cdb
;
3166 bzero(&ms10
, sizeof(ms10
));
3167 ms10
.opcode
= MODE_SELECT_10
;
3168 ms10
.byte2
= ms6
->byte2
;
3170 header6
= (struct scsi_mode_header_6
*)params
->mode_buf
;
3171 header10
= (struct scsi_mode_header_10
*)params
->mode_buf
;
3173 page_header
= find_mode_page_6(header6
);
3174 page_num
= page_header
->page_code
;
3176 blk_desc_len
= header6
->blk_desc_len
;
3178 page_size
= cdgetpagesize(page_num
);
3180 if (page_size
!= (page_header
->page_length
+
3181 sizeof(*page_header
)))
3182 page_size
= page_header
->page_length
+
3183 sizeof(*page_header
);
3185 len
= sizeof(*header10
) + blk_desc_len
+ page_size
;
3187 len
= min(params
->alloc_len
, len
);
3190 * Since the 6 byte parameter header is shorter than the 10
3191 * byte parameter header, we need to copy the actual mode
3192 * page data, and the block descriptor, if any, so things wind
3193 * up in the right place. The regions will overlap, but
3194 * bcopy() does the right thing.
3196 bcopy(params
->mode_buf
+ sizeof(*header6
),
3197 params
->mode_buf
+ sizeof(*header10
),
3198 len
- sizeof(*header10
));
3200 /* Make sure these fields are set correctly. */
3201 scsi_ulto2b(0, header10
->data_length
);
3202 header10
->medium_type
= 0;
3203 scsi_ulto2b(blk_desc_len
, header10
->blk_desc_len
);
3205 ccb
->csio
.dxfer_len
= len
;
3207 scsi_ulto2b(len
, ms10
.length
);
3208 ms10
.control
= ms6
->control
;
3209 bcopy(&ms10
, cdb
, 10);
3210 ccb
->csio
.cdb_len
= 10;
3213 frozen
= (ccb
->ccb_h
.status
& CAM_DEV_QFRZN
) != 0;
3214 ccb
->ccb_h
.status
= CAM_REQUEUE_REQ
;
3217 cam_release_devq(ccb
->ccb_h
.path
,
3221 /*getcount_only*/0);
3228 cderror(union ccb
*ccb
, u_int32_t cam_flags
, u_int32_t sense_flags
)
3230 struct cd_softc
*softc
;
3231 struct cam_periph
*periph
;
3234 periph
= xpt_path_periph(ccb
->ccb_h
.path
);
3235 softc
= (struct cd_softc
*)periph
->softc
;
3240 * We use a status of CAM_REQ_INVALID as shorthand -- if a 6 byte
3241 * CDB comes back with this particular error, try transforming it
3242 * into the 10 byte version.
3244 if ((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) == CAM_REQ_INVALID
) {
3245 error
= cd6byteworkaround(ccb
);
3246 } else if (((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) ==
3247 CAM_SCSI_STATUS_ERROR
)
3248 && (ccb
->ccb_h
.status
& CAM_AUTOSNS_VALID
)
3249 && (ccb
->csio
.scsi_status
== SCSI_STATUS_CHECK_COND
)
3250 && ((ccb
->ccb_h
.flags
& CAM_SENSE_PHYS
) == 0)
3251 && ((ccb
->ccb_h
.flags
& CAM_SENSE_PTR
) == 0)) {
3252 int sense_key
, error_code
, asc
, ascq
;
3254 scsi_extract_sense(&ccb
->csio
.sense_data
,
3255 &error_code
, &sense_key
, &asc
, &ascq
);
3256 if (sense_key
== SSD_KEY_ILLEGAL_REQUEST
)
3257 error
= cd6byteworkaround(ccb
);
3260 if (error
== ERESTART
)
3265 * Until we have a better way of doing pack validation,
3266 * don't treat UAs as errors.
3268 sense_flags
|= SF_RETRY_UA
;
3269 return (cam_periph_error(ccb
, cam_flags
, sense_flags
,
3270 &softc
->saved_ccb
));
3274 * Read table of contents
3277 cdreadtoc(struct cam_periph
*periph
, u_int32_t mode
, u_int32_t start
,
3278 u_int8_t
*data
, u_int32_t len
, u_int32_t sense_flags
)
3280 struct scsi_read_toc
*scsi_cmd
;
3282 struct ccb_scsiio
*csio
;
3289 ccb
= cdgetccb(periph
, /* priority */ 1);
3295 /* cbfcnp */ cddone
,
3296 /* flags */ CAM_DIR_IN
,
3297 /* tag_action */ MSG_SIMPLE_Q_TAG
,
3298 /* data_ptr */ data
,
3299 /* dxfer_len */ len
,
3300 /* sense_len */ SSD_FULL_SIZE
,
3301 sizeof(struct scsi_read_toc
),
3302 /* timeout */ 50000);
3304 scsi_cmd
= (struct scsi_read_toc
*)&csio
->cdb_io
.cdb_bytes
;
3305 bzero (scsi_cmd
, sizeof(*scsi_cmd
));
3307 if (mode
== CD_MSF_FORMAT
)
3308 scsi_cmd
->byte2
|= CD_MSF
;
3309 scsi_cmd
->from_track
= start
;
3310 /* scsi_ulto2b(ntoc, (u_int8_t *)scsi_cmd->data_len); */
3311 scsi_cmd
->data_len
[0] = (ntoc
) >> 8;
3312 scsi_cmd
->data_len
[1] = (ntoc
) & 0xff;
3314 scsi_cmd
->op_code
= READ_TOC
;
3316 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3317 /*sense_flags*/SF_RETRY_UA
| sense_flags
);
3319 xpt_release_ccb(ccb
);
3325 cdreadsubchannel(struct cam_periph
*periph
, u_int32_t mode
,
3326 u_int32_t format
, int track
,
3327 struct cd_sub_channel_info
*data
, u_int32_t len
)
3329 struct scsi_read_subchannel
*scsi_cmd
;
3330 struct ccb_scsiio
*csio
;
3336 ccb
= cdgetccb(periph
, /* priority */ 1);
3342 /* cbfcnp */ cddone
,
3343 /* flags */ CAM_DIR_IN
,
3344 /* tag_action */ MSG_SIMPLE_Q_TAG
,
3345 /* data_ptr */ (u_int8_t
*)data
,
3346 /* dxfer_len */ len
,
3347 /* sense_len */ SSD_FULL_SIZE
,
3348 sizeof(struct scsi_read_subchannel
),
3349 /* timeout */ 50000);
3351 scsi_cmd
= (struct scsi_read_subchannel
*)&csio
->cdb_io
.cdb_bytes
;
3352 bzero (scsi_cmd
, sizeof(*scsi_cmd
));
3354 scsi_cmd
->op_code
= READ_SUBCHANNEL
;
3355 if (mode
== CD_MSF_FORMAT
)
3356 scsi_cmd
->byte1
|= CD_MSF
;
3357 scsi_cmd
->byte2
= SRS_SUBQ
;
3358 scsi_cmd
->subchan_format
= format
;
3359 scsi_cmd
->track
= track
;
3360 scsi_ulto2b(len
, (u_int8_t
*)scsi_cmd
->data_len
);
3361 scsi_cmd
->control
= 0;
3363 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3364 /*sense_flags*/SF_RETRY_UA
);
3366 xpt_release_ccb(ccb
);
3372 * All MODE_SENSE requests in the cd(4) driver MUST go through this
3373 * routine. See comments in cd6byteworkaround() for details.
3376 cdgetmode(struct cam_periph
*periph
, struct cd_mode_params
*data
,
3379 struct ccb_scsiio
*csio
;
3380 struct cd_softc
*softc
;
3385 softc
= (struct cd_softc
*)periph
->softc
;
3387 ccb
= cdgetccb(periph
, /* priority */ 1);
3391 data
->cdb_size
= softc
->minimum_command_size
;
3392 if (data
->cdb_size
< 10)
3393 param_len
= sizeof(struct cd_mode_data
);
3395 param_len
= sizeof(struct cd_mode_data_10
);
3397 /* Don't say we've got more room than we actually allocated */
3398 param_len
= min(param_len
, data
->alloc_len
);
3400 scsi_mode_sense_len(csio
,
3402 /* cbfcnp */ cddone
,
3403 /* tag_action */ MSG_SIMPLE_Q_TAG
,
3405 /* page_code */ SMS_PAGE_CTRL_CURRENT
,
3407 /* param_buf */ data
->mode_buf
,
3408 /* param_len */ param_len
,
3409 /* minimum_cmd_size */ softc
->minimum_command_size
,
3410 /* sense_len */ SSD_FULL_SIZE
,
3411 /* timeout */ 50000);
3414 * It would be nice not to have to do this, but there's no
3415 * available pointer in the CCB that would allow us to stuff the
3416 * mode params structure in there and retrieve it in
3417 * cd6byteworkaround(), so we can set the cdb size. The cdb size
3418 * lets the caller know what CDB size we ended up using, so they
3419 * can find the actual mode page offset.
3421 STAILQ_INSERT_TAIL(&softc
->mode_queue
, data
, links
);
3423 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3424 /*sense_flags*/SF_RETRY_UA
);
3426 xpt_release_ccb(ccb
);
3428 STAILQ_REMOVE(&softc
->mode_queue
, data
, cd_mode_params
, links
);
3431 * This is a bit of belt-and-suspenders checking, but if we run
3432 * into a situation where the target sends back multiple block
3433 * descriptors, we might not have enough space in the buffer to
3434 * see the whole mode page. Better to return an error than
3435 * potentially access memory beyond our malloced region.
3440 if (data
->cdb_size
== 10) {
3441 struct scsi_mode_header_10
*hdr10
;
3443 hdr10
= (struct scsi_mode_header_10
*)data
->mode_buf
;
3444 data_len
= scsi_2btoul(hdr10
->data_length
);
3445 data_len
+= sizeof(hdr10
->data_length
);
3447 struct scsi_mode_header_6
*hdr6
;
3449 hdr6
= (struct scsi_mode_header_6
*)data
->mode_buf
;
3450 data_len
= hdr6
->data_length
;
3451 data_len
+= sizeof(hdr6
->data_length
);
3455 * Complain if there is more mode data available than we
3456 * allocated space for. This could potentially happen if
3457 * we miscalculated the page length for some reason, if the
3458 * drive returns multiple block descriptors, or if it sets
3459 * the data length incorrectly.
3461 if (data_len
> data
->alloc_len
) {
3462 xpt_print(periph
->path
, "allocated modepage %d length "
3463 "%d < returned length %d\n", page
, data
->alloc_len
,
3472 * All MODE_SELECT requests in the cd(4) driver MUST go through this
3473 * routine. See comments in cd6byteworkaround() for details.
3476 cdsetmode(struct cam_periph
*periph
, struct cd_mode_params
*data
)
3478 struct ccb_scsiio
*csio
;
3479 struct cd_softc
*softc
;
3481 int cdb_size
, param_len
;
3484 softc
= (struct cd_softc
*)periph
->softc
;
3486 ccb
= cdgetccb(periph
, /* priority */ 1);
3493 * If the data is formatted for the 10 byte version of the mode
3494 * select parameter list, we need to use the 10 byte CDB.
3495 * Otherwise, we use whatever the stored minimum command size.
3497 if (data
->cdb_size
== 10)
3498 cdb_size
= data
->cdb_size
;
3500 cdb_size
= softc
->minimum_command_size
;
3502 if (cdb_size
>= 10) {
3503 struct scsi_mode_header_10
*mode_header
;
3506 mode_header
= (struct scsi_mode_header_10
*)data
->mode_buf
;
3508 data_len
= scsi_2btoul(mode_header
->data_length
);
3510 scsi_ulto2b(0, mode_header
->data_length
);
3512 * SONY drives do not allow a mode select with a medium_type
3513 * value that has just been returned by a mode sense; use a
3514 * medium_type of 0 (Default) instead.
3516 mode_header
->medium_type
= 0;
3519 * Pass back whatever the drive passed to us, plus the size
3520 * of the data length field.
3522 param_len
= data_len
+ sizeof(mode_header
->data_length
);
3525 struct scsi_mode_header_6
*mode_header
;
3527 mode_header
= (struct scsi_mode_header_6
*)data
->mode_buf
;
3529 param_len
= mode_header
->data_length
+ 1;
3531 mode_header
->data_length
= 0;
3533 * SONY drives do not allow a mode select with a medium_type
3534 * value that has just been returned by a mode sense; use a
3535 * medium_type of 0 (Default) instead.
3537 mode_header
->medium_type
= 0;
3540 /* Don't say we've got more room than we actually allocated */
3541 param_len
= min(param_len
, data
->alloc_len
);
3543 scsi_mode_select_len(csio
,
3545 /* cbfcnp */ cddone
,
3546 /* tag_action */ MSG_SIMPLE_Q_TAG
,
3547 /* scsi_page_fmt */ 1,
3549 /* param_buf */ data
->mode_buf
,
3550 /* param_len */ param_len
,
3551 /* minimum_cmd_size */ cdb_size
,
3552 /* sense_len */ SSD_FULL_SIZE
,
3553 /* timeout */ 50000);
3555 /* See comments in cdgetmode() and cd6byteworkaround(). */
3556 STAILQ_INSERT_TAIL(&softc
->mode_queue
, data
, links
);
3558 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3559 /*sense_flags*/SF_RETRY_UA
);
3561 xpt_release_ccb(ccb
);
3563 STAILQ_REMOVE(&softc
->mode_queue
, data
, cd_mode_params
, links
);
3571 cdplay(struct cam_periph
*periph
, u_int32_t blk
, u_int32_t len
)
3573 struct ccb_scsiio
*csio
;
3579 ccb
= cdgetccb(periph
, /* priority */ 1);
3582 * Use the smallest possible command to perform the operation.
3584 if ((len
& 0xffff0000) == 0) {
3586 * We can fit in a 10 byte cdb.
3588 struct scsi_play_10
*scsi_cmd
;
3590 scsi_cmd
= (struct scsi_play_10
*)&csio
->cdb_io
.cdb_bytes
;
3591 bzero (scsi_cmd
, sizeof(*scsi_cmd
));
3592 scsi_cmd
->op_code
= PLAY_10
;
3593 scsi_ulto4b(blk
, (u_int8_t
*)scsi_cmd
->blk_addr
);
3594 scsi_ulto2b(len
, (u_int8_t
*)scsi_cmd
->xfer_len
);
3595 cdb_len
= sizeof(*scsi_cmd
);
3597 struct scsi_play_12
*scsi_cmd
;
3599 scsi_cmd
= (struct scsi_play_12
*)&csio
->cdb_io
.cdb_bytes
;
3600 bzero (scsi_cmd
, sizeof(*scsi_cmd
));
3601 scsi_cmd
->op_code
= PLAY_12
;
3602 scsi_ulto4b(blk
, (u_int8_t
*)scsi_cmd
->blk_addr
);
3603 scsi_ulto4b(len
, (u_int8_t
*)scsi_cmd
->xfer_len
);
3604 cdb_len
= sizeof(*scsi_cmd
);
3609 /*flags*/CAM_DIR_NONE
,
3613 /*sense_len*/SSD_FULL_SIZE
,
3615 /*timeout*/50 * 1000);
3617 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3618 /*sense_flags*/SF_RETRY_UA
);
3620 xpt_release_ccb(ccb
);
3626 cdplaymsf(struct cam_periph
*periph
, u_int32_t startm
, u_int32_t starts
,
3627 u_int32_t startf
, u_int32_t endm
, u_int32_t ends
, u_int32_t endf
)
3629 struct scsi_play_msf
*scsi_cmd
;
3630 struct ccb_scsiio
*csio
;
3636 ccb
= cdgetccb(periph
, /* priority */ 1);
3642 /* cbfcnp */ cddone
,
3643 /* flags */ CAM_DIR_NONE
,
3644 /* tag_action */ MSG_SIMPLE_Q_TAG
,
3645 /* data_ptr */ NULL
,
3647 /* sense_len */ SSD_FULL_SIZE
,
3648 sizeof(struct scsi_play_msf
),
3649 /* timeout */ 50000);
3651 scsi_cmd
= (struct scsi_play_msf
*)&csio
->cdb_io
.cdb_bytes
;
3652 bzero (scsi_cmd
, sizeof(*scsi_cmd
));
3654 scsi_cmd
->op_code
= PLAY_MSF
;
3655 scsi_cmd
->start_m
= startm
;
3656 scsi_cmd
->start_s
= starts
;
3657 scsi_cmd
->start_f
= startf
;
3658 scsi_cmd
->end_m
= endm
;
3659 scsi_cmd
->end_s
= ends
;
3660 scsi_cmd
->end_f
= endf
;
3662 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3663 /*sense_flags*/SF_RETRY_UA
);
3665 xpt_release_ccb(ccb
);
3672 cdplaytracks(struct cam_periph
*periph
, u_int32_t strack
, u_int32_t sindex
,
3673 u_int32_t etrack
, u_int32_t eindex
)
3675 struct scsi_play_track
*scsi_cmd
;
3676 struct ccb_scsiio
*csio
;
3682 ccb
= cdgetccb(periph
, /* priority */ 1);
3688 /* cbfcnp */ cddone
,
3689 /* flags */ CAM_DIR_NONE
,
3690 /* tag_action */ MSG_SIMPLE_Q_TAG
,
3691 /* data_ptr */ NULL
,
3693 /* sense_len */ SSD_FULL_SIZE
,
3694 sizeof(struct scsi_play_track
),
3695 /* timeout */ 50000);
3697 scsi_cmd
= (struct scsi_play_track
*)&csio
->cdb_io
.cdb_bytes
;
3698 bzero (scsi_cmd
, sizeof(*scsi_cmd
));
3700 scsi_cmd
->op_code
= PLAY_TRACK
;
3701 scsi_cmd
->start_track
= strack
;
3702 scsi_cmd
->start_index
= sindex
;
3703 scsi_cmd
->end_track
= etrack
;
3704 scsi_cmd
->end_index
= eindex
;
3706 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3707 /*sense_flags*/SF_RETRY_UA
);
3709 xpt_release_ccb(ccb
);
3715 cdpause(struct cam_periph
*periph
, u_int32_t go
)
3717 struct scsi_pause
*scsi_cmd
;
3718 struct ccb_scsiio
*csio
;
3724 ccb
= cdgetccb(periph
, /* priority */ 1);
3730 /* cbfcnp */ cddone
,
3731 /* flags */ CAM_DIR_NONE
,
3732 /* tag_action */ MSG_SIMPLE_Q_TAG
,
3733 /* data_ptr */ NULL
,
3735 /* sense_len */ SSD_FULL_SIZE
,
3736 sizeof(struct scsi_pause
),
3737 /* timeout */ 50000);
3739 scsi_cmd
= (struct scsi_pause
*)&csio
->cdb_io
.cdb_bytes
;
3740 bzero (scsi_cmd
, sizeof(*scsi_cmd
));
3742 scsi_cmd
->op_code
= PAUSE
;
3743 scsi_cmd
->resume
= go
;
3745 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3746 /*sense_flags*/SF_RETRY_UA
);
3748 xpt_release_ccb(ccb
);
3754 cdstartunit(struct cam_periph
*periph
, int load
)
3761 ccb
= cdgetccb(periph
, /* priority */ 1);
3763 scsi_start_stop(&ccb
->csio
,
3765 /* cbfcnp */ cddone
,
3766 /* tag_action */ MSG_SIMPLE_Q_TAG
,
3768 /* load_eject */ load
,
3769 /* immediate */ FALSE
,
3770 /* sense_len */ SSD_FULL_SIZE
,
3771 /* timeout */ 50000);
3773 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3774 /*sense_flags*/SF_RETRY_UA
);
3776 xpt_release_ccb(ccb
);
3782 cdstopunit(struct cam_periph
*periph
, u_int32_t eject
)
3789 ccb
= cdgetccb(periph
, /* priority */ 1);
3791 scsi_start_stop(&ccb
->csio
,
3793 /* cbfcnp */ cddone
,
3794 /* tag_action */ MSG_SIMPLE_Q_TAG
,
3796 /* load_eject */ eject
,
3797 /* immediate */ FALSE
,
3798 /* sense_len */ SSD_FULL_SIZE
,
3799 /* timeout */ 50000);
3801 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3802 /*sense_flags*/SF_RETRY_UA
);
3804 xpt_release_ccb(ccb
);
3810 cdsetspeed(struct cam_periph
*periph
, u_int32_t rdspeed
, u_int32_t wrspeed
)
3812 struct scsi_set_speed
*scsi_cmd
;
3813 struct ccb_scsiio
*csio
;
3818 ccb
= cdgetccb(periph
, /* priority */ 1);
3821 /* Preserve old behavior: units in multiples of CDROM speed */
3829 /* cbfcnp */ cddone
,
3830 /* flags */ CAM_DIR_NONE
,
3831 /* tag_action */ MSG_SIMPLE_Q_TAG
,
3832 /* data_ptr */ NULL
,
3834 /* sense_len */ SSD_FULL_SIZE
,
3835 sizeof(struct scsi_set_speed
),
3836 /* timeout */ 50000);
3838 scsi_cmd
= (struct scsi_set_speed
*)&csio
->cdb_io
.cdb_bytes
;
3839 bzero(scsi_cmd
, sizeof(*scsi_cmd
));
3841 scsi_cmd
->opcode
= SET_CD_SPEED
;
3842 scsi_ulto2b(rdspeed
, scsi_cmd
->readspeed
);
3843 scsi_ulto2b(wrspeed
, scsi_cmd
->writespeed
);
3845 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3846 /*sense_flags*/SF_RETRY_UA
);
3848 xpt_release_ccb(ccb
);
3854 cdreportkey(struct cam_periph
*periph
, struct dvd_authinfo
*authinfo
)
3866 ccb
= cdgetccb(periph
, /* priority */ 1);
3868 switch (authinfo
->format
) {
3869 case DVD_REPORT_AGID
:
3870 length
= sizeof(struct scsi_report_key_data_agid
);
3872 case DVD_REPORT_CHALLENGE
:
3873 length
= sizeof(struct scsi_report_key_data_challenge
);
3875 case DVD_REPORT_KEY1
:
3876 length
= sizeof(struct scsi_report_key_data_key1_key2
);
3878 case DVD_REPORT_TITLE_KEY
:
3879 length
= sizeof(struct scsi_report_key_data_title
);
3880 /* The lba field is only set for the title key */
3881 lba
= authinfo
->lba
;
3883 case DVD_REPORT_ASF
:
3884 length
= sizeof(struct scsi_report_key_data_asf
);
3886 case DVD_REPORT_RPC
:
3887 length
= sizeof(struct scsi_report_key_data_rpc
);
3889 case DVD_INVALIDATE_AGID
:
3895 break; /* NOTREACHED */
3899 databuf
= kmalloc(length
, M_DEVBUF
, M_INTWAIT
| M_ZERO
);
3905 scsi_report_key(&ccb
->csio
,
3907 /* cbfcnp */ cddone
,
3908 /* tag_action */ MSG_SIMPLE_Q_TAG
,
3910 /* agid */ authinfo
->agid
,
3911 /* key_format */ authinfo
->format
,
3912 /* data_ptr */ databuf
,
3913 /* dxfer_len */ length
,
3914 /* sense_len */ SSD_FULL_SIZE
,
3915 /* timeout */ 50000);
3917 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
3918 /*sense_flags*/SF_RETRY_UA
);
3923 if (ccb
->csio
.resid
!= 0) {
3924 xpt_print(periph
->path
, "warning, residual for report key "
3925 "command is %d\n", ccb
->csio
.resid
);
3928 switch(authinfo
->format
) {
3929 case DVD_REPORT_AGID
: {
3930 struct scsi_report_key_data_agid
*agid_data
;
3932 agid_data
= (struct scsi_report_key_data_agid
*)databuf
;
3934 authinfo
->agid
= (agid_data
->agid
& RKD_AGID_MASK
) >>
3938 case DVD_REPORT_CHALLENGE
: {
3939 struct scsi_report_key_data_challenge
*chal_data
;
3941 chal_data
= (struct scsi_report_key_data_challenge
*)databuf
;
3943 bcopy(chal_data
->challenge_key
, authinfo
->keychal
,
3944 min(sizeof(chal_data
->challenge_key
),
3945 sizeof(authinfo
->keychal
)));
3948 case DVD_REPORT_KEY1
: {
3949 struct scsi_report_key_data_key1_key2
*key1_data
;
3951 key1_data
= (struct scsi_report_key_data_key1_key2
*)databuf
;
3953 bcopy(key1_data
->key1
, authinfo
->keychal
,
3954 min(sizeof(key1_data
->key1
), sizeof(authinfo
->keychal
)));
3957 case DVD_REPORT_TITLE_KEY
: {
3958 struct scsi_report_key_data_title
*title_data
;
3960 title_data
= (struct scsi_report_key_data_title
*)databuf
;
3962 authinfo
->cpm
= (title_data
->byte0
& RKD_TITLE_CPM
) >>
3963 RKD_TITLE_CPM_SHIFT
;
3964 authinfo
->cp_sec
= (title_data
->byte0
& RKD_TITLE_CP_SEC
) >>
3965 RKD_TITLE_CP_SEC_SHIFT
;
3966 authinfo
->cgms
= (title_data
->byte0
& RKD_TITLE_CMGS_MASK
) >>
3967 RKD_TITLE_CMGS_SHIFT
;
3968 bcopy(title_data
->title_key
, authinfo
->keychal
,
3969 min(sizeof(title_data
->title_key
),
3970 sizeof(authinfo
->keychal
)));
3973 case DVD_REPORT_ASF
: {
3974 struct scsi_report_key_data_asf
*asf_data
;
3976 asf_data
= (struct scsi_report_key_data_asf
*)databuf
;
3978 authinfo
->asf
= asf_data
->success
& RKD_ASF_SUCCESS
;
3981 case DVD_REPORT_RPC
: {
3982 struct scsi_report_key_data_rpc
*rpc_data
;
3984 rpc_data
= (struct scsi_report_key_data_rpc
*)databuf
;
3986 authinfo
->reg_type
= (rpc_data
->byte4
& RKD_RPC_TYPE_MASK
) >>
3988 authinfo
->vend_rsts
=
3989 (rpc_data
->byte4
& RKD_RPC_VENDOR_RESET_MASK
) >>
3990 RKD_RPC_VENDOR_RESET_SHIFT
;
3991 authinfo
->user_rsts
= rpc_data
->byte4
& RKD_RPC_USER_RESET_MASK
;
3992 authinfo
->region
= rpc_data
->region_mask
;
3993 authinfo
->rpc_scheme
= rpc_data
->rpc_scheme1
;
3996 case DVD_INVALIDATE_AGID
:
3999 /* This should be impossible, since we checked above */
4002 break; /* NOTREACHED */
4005 if (databuf
!= NULL
)
4006 kfree(databuf
, M_DEVBUF
);
4008 xpt_release_ccb(ccb
);
4014 cdsendkey(struct cam_periph
*periph
, struct dvd_authinfo
*authinfo
)
4024 ccb
= cdgetccb(periph
, /* priority */ 1);
4026 switch(authinfo
->format
) {
4027 case DVD_SEND_CHALLENGE
: {
4028 struct scsi_report_key_data_challenge
*challenge_data
;
4030 length
= sizeof(*challenge_data
);
4032 challenge_data
= kmalloc(length
, M_DEVBUF
, M_INTWAIT
| M_ZERO
);
4034 databuf
= (u_int8_t
*)challenge_data
;
4036 scsi_ulto2b(length
- sizeof(challenge_data
->data_len
),
4037 challenge_data
->data_len
);
4039 bcopy(authinfo
->keychal
, challenge_data
->challenge_key
,
4040 min(sizeof(authinfo
->keychal
),
4041 sizeof(challenge_data
->challenge_key
)));
4044 case DVD_SEND_KEY2
: {
4045 struct scsi_report_key_data_key1_key2
*key2_data
;
4047 length
= sizeof(*key2_data
);
4049 key2_data
= kmalloc(length
, M_DEVBUF
, M_INTWAIT
| M_ZERO
);
4051 databuf
= (u_int8_t
*)key2_data
;
4053 scsi_ulto2b(length
- sizeof(key2_data
->data_len
),
4054 key2_data
->data_len
);
4056 bcopy(authinfo
->keychal
, key2_data
->key1
,
4057 min(sizeof(authinfo
->keychal
), sizeof(key2_data
->key1
)));
4061 case DVD_SEND_RPC
: {
4062 struct scsi_send_key_data_rpc
*rpc_data
;
4064 length
= sizeof(*rpc_data
);
4066 rpc_data
= kmalloc(length
, M_DEVBUF
, M_INTWAIT
| M_ZERO
);
4068 databuf
= (u_int8_t
*)rpc_data
;
4070 scsi_ulto2b(length
- sizeof(rpc_data
->data_len
),
4071 rpc_data
->data_len
);
4073 rpc_data
->region_code
= authinfo
->region
;
4079 break; /* NOTREACHED */
4082 scsi_send_key(&ccb
->csio
,
4084 /* cbfcnp */ cddone
,
4085 /* tag_action */ MSG_SIMPLE_Q_TAG
,
4086 /* agid */ authinfo
->agid
,
4087 /* key_format */ authinfo
->format
,
4088 /* data_ptr */ databuf
,
4089 /* dxfer_len */ length
,
4090 /* sense_len */ SSD_FULL_SIZE
,
4091 /* timeout */ 50000);
4093 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
4094 /*sense_flags*/SF_RETRY_UA
);
4098 if (databuf
!= NULL
)
4099 kfree(databuf
, M_DEVBUF
);
4101 xpt_release_ccb(ccb
);
4107 cdreaddvdstructure(struct cam_periph
*periph
, struct dvd_struct
*dvdstruct
)
4117 /* The address is reserved for many of the formats */
4120 ccb
= cdgetccb(periph
, /* priority */ 1);
4122 switch(dvdstruct
->format
) {
4123 case DVD_STRUCT_PHYSICAL
:
4124 length
= sizeof(struct scsi_read_dvd_struct_data_physical
);
4126 case DVD_STRUCT_COPYRIGHT
:
4127 length
= sizeof(struct scsi_read_dvd_struct_data_copyright
);
4129 case DVD_STRUCT_DISCKEY
:
4130 length
= sizeof(struct scsi_read_dvd_struct_data_disc_key
);
4132 case DVD_STRUCT_BCA
:
4133 length
= sizeof(struct scsi_read_dvd_struct_data_bca
);
4135 case DVD_STRUCT_MANUFACT
:
4136 length
= sizeof(struct scsi_read_dvd_struct_data_manufacturer
);
4138 case DVD_STRUCT_CMI
:
4142 length
= sizeof(struct scsi_read_dvd_struct_data_copy_manage
);
4143 address
= dvdstruct
->address
;
4145 break; /* NOTREACHED */
4146 case DVD_STRUCT_PROTDISCID
:
4147 length
= sizeof(struct scsi_read_dvd_struct_data_prot_discid
);
4149 case DVD_STRUCT_DISCKEYBLOCK
:
4150 length
= sizeof(struct scsi_read_dvd_struct_data_disc_key_blk
);
4152 case DVD_STRUCT_DDS
:
4153 length
= sizeof(struct scsi_read_dvd_struct_data_dds
);
4155 case DVD_STRUCT_MEDIUM_STAT
:
4156 length
= sizeof(struct scsi_read_dvd_struct_data_medium_status
);
4158 case DVD_STRUCT_SPARE_AREA
:
4159 length
= sizeof(struct scsi_read_dvd_struct_data_spare_area
);
4161 case DVD_STRUCT_RMD_LAST
:
4165 length
= sizeof(struct scsi_read_dvd_struct_data_rmd_borderout
);
4166 address
= dvdstruct
->address
;
4168 break; /* NOTREACHED */
4169 case DVD_STRUCT_RMD_RMA
:
4173 length
= sizeof(struct scsi_read_dvd_struct_data_rmd
);
4174 address
= dvdstruct
->address
;
4176 break; /* NOTREACHED */
4177 case DVD_STRUCT_PRERECORDED
:
4178 length
= sizeof(struct scsi_read_dvd_struct_data_leadin
);
4180 case DVD_STRUCT_UNIQUEID
:
4181 length
= sizeof(struct scsi_read_dvd_struct_data_disc_id
);
4183 case DVD_STRUCT_DCB
:
4187 length
= sizeof(struct scsi_read_dvd_struct_data_dcb
);
4188 address
= dvdstruct
->address
;
4190 break; /* NOTREACHED */
4191 case DVD_STRUCT_LIST
:
4193 * This is the maximum allocation length for the READ DVD
4194 * STRUCTURE command. There's nothing in the MMC3 spec
4195 * that indicates a limit in the amount of data that can
4196 * be returned from this call, other than the limits
4197 * imposed by the 2-byte length variables.
4204 break; /* NOTREACHED */
4208 databuf
= kmalloc(length
, M_DEVBUF
, M_INTWAIT
| M_ZERO
);
4213 scsi_read_dvd_structure(&ccb
->csio
,
4215 /* cbfcnp */ cddone
,
4216 /* tag_action */ MSG_SIMPLE_Q_TAG
,
4218 /* layer_number */ dvdstruct
->layer_num
,
4219 /* key_format */ dvdstruct
->format
,
4220 /* agid */ dvdstruct
->agid
,
4221 /* data_ptr */ databuf
,
4222 /* dxfer_len */ length
,
4223 /* sense_len */ SSD_FULL_SIZE
,
4224 /* timeout */ 50000);
4226 error
= cdrunccb(ccb
, cderror
, /*cam_flags*/CAM_RETRY_SELTO
,
4227 /*sense_flags*/SF_RETRY_UA
);
4232 switch(dvdstruct
->format
) {
4233 case DVD_STRUCT_PHYSICAL
: {
4234 struct scsi_read_dvd_struct_data_layer_desc
*inlayer
;
4235 struct dvd_layer
*outlayer
;
4236 struct scsi_read_dvd_struct_data_physical
*phys_data
;
4239 (struct scsi_read_dvd_struct_data_physical
*)databuf
;
4240 inlayer
= &phys_data
->layer_desc
;
4241 outlayer
= (struct dvd_layer
*)&dvdstruct
->data
;
4243 dvdstruct
->length
= sizeof(*inlayer
);
4245 outlayer
->book_type
= (inlayer
->book_type_version
&
4246 RDSD_BOOK_TYPE_MASK
) >> RDSD_BOOK_TYPE_SHIFT
;
4247 outlayer
->book_version
= (inlayer
->book_type_version
&
4248 RDSD_BOOK_VERSION_MASK
);
4249 outlayer
->disc_size
= (inlayer
->disc_size_max_rate
&
4250 RDSD_DISC_SIZE_MASK
) >> RDSD_DISC_SIZE_SHIFT
;
4251 outlayer
->max_rate
= (inlayer
->disc_size_max_rate
&
4252 RDSD_MAX_RATE_MASK
);
4253 outlayer
->nlayers
= (inlayer
->layer_info
&
4254 RDSD_NUM_LAYERS_MASK
) >> RDSD_NUM_LAYERS_SHIFT
;
4255 outlayer
->track_path
= (inlayer
->layer_info
&
4256 RDSD_TRACK_PATH_MASK
) >> RDSD_TRACK_PATH_SHIFT
;
4257 outlayer
->layer_type
= (inlayer
->layer_info
&
4258 RDSD_LAYER_TYPE_MASK
);
4259 outlayer
->linear_density
= (inlayer
->density
&
4260 RDSD_LIN_DENSITY_MASK
) >> RDSD_LIN_DENSITY_SHIFT
;
4261 outlayer
->track_density
= (inlayer
->density
&
4262 RDSD_TRACK_DENSITY_MASK
);
4263 outlayer
->bca
= (inlayer
->bca
& RDSD_BCA_MASK
) >>
4265 outlayer
->start_sector
= scsi_3btoul(inlayer
->main_data_start
);
4266 outlayer
->end_sector
= scsi_3btoul(inlayer
->main_data_end
);
4267 outlayer
->end_sector_l0
=
4268 scsi_3btoul(inlayer
->end_sector_layer0
);
4271 case DVD_STRUCT_COPYRIGHT
: {
4272 struct scsi_read_dvd_struct_data_copyright
*copy_data
;
4274 copy_data
= (struct scsi_read_dvd_struct_data_copyright
*)
4277 dvdstruct
->cpst
= copy_data
->cps_type
;
4278 dvdstruct
->rmi
= copy_data
->region_info
;
4279 dvdstruct
->length
= 0;
4285 * Tell the user what the overall length is, no matter
4286 * what we can actually fit in the data buffer.
4288 dvdstruct
->length
= length
- ccb
->csio
.resid
-
4289 sizeof(struct scsi_read_dvd_struct_data_header
);
4292 * But only actually copy out the smaller of what we read
4293 * in or what the structure can take.
4295 bcopy(databuf
+ sizeof(struct scsi_read_dvd_struct_data_header
),
4297 min(sizeof(dvdstruct
->data
), dvdstruct
->length
));
4302 if (databuf
!= NULL
)
4303 kfree(databuf
, M_DEVBUF
);
4305 xpt_release_ccb(ccb
);
4311 scsi_report_key(struct ccb_scsiio
*csio
, u_int32_t retries
,
4312 void (*cbfcnp
)(struct cam_periph
*, union ccb
*),
4313 u_int8_t tag_action
, u_int32_t lba
, u_int8_t agid
,
4314 u_int8_t key_format
, u_int8_t
*data_ptr
, u_int32_t dxfer_len
,
4315 u_int8_t sense_len
, u_int32_t timeout
)
4317 struct scsi_report_key
*scsi_cmd
;
4319 scsi_cmd
= (struct scsi_report_key
*)&csio
->cdb_io
.cdb_bytes
;
4320 bzero(scsi_cmd
, sizeof(*scsi_cmd
));
4321 scsi_cmd
->opcode
= REPORT_KEY
;
4322 scsi_ulto4b(lba
, scsi_cmd
->lba
);
4323 scsi_ulto2b(dxfer_len
, scsi_cmd
->alloc_len
);
4324 scsi_cmd
->agid_keyformat
= (agid
<< RK_KF_AGID_SHIFT
) |
4325 (key_format
& RK_KF_KEYFORMAT_MASK
);
4330 /*flags*/ (dxfer_len
== 0) ? CAM_DIR_NONE
: CAM_DIR_IN
,
4332 /*data_ptr*/ data_ptr
,
4333 /*dxfer_len*/ dxfer_len
,
4340 scsi_send_key(struct ccb_scsiio
*csio
, u_int32_t retries
,
4341 void (*cbfcnp
)(struct cam_periph
*, union ccb
*),
4342 u_int8_t tag_action
, u_int8_t agid
, u_int8_t key_format
,
4343 u_int8_t
*data_ptr
, u_int32_t dxfer_len
, u_int8_t sense_len
,
4346 struct scsi_send_key
*scsi_cmd
;
4348 scsi_cmd
= (struct scsi_send_key
*)&csio
->cdb_io
.cdb_bytes
;
4349 bzero(scsi_cmd
, sizeof(*scsi_cmd
));
4350 scsi_cmd
->opcode
= SEND_KEY
;
4352 scsi_ulto2b(dxfer_len
, scsi_cmd
->param_len
);
4353 scsi_cmd
->agid_keyformat
= (agid
<< RK_KF_AGID_SHIFT
) |
4354 (key_format
& RK_KF_KEYFORMAT_MASK
);
4359 /*flags*/ CAM_DIR_OUT
,
4361 /*data_ptr*/ data_ptr
,
4362 /*dxfer_len*/ dxfer_len
,
4370 scsi_read_dvd_structure(struct ccb_scsiio
*csio
, u_int32_t retries
,
4371 void (*cbfcnp
)(struct cam_periph
*, union ccb
*),
4372 u_int8_t tag_action
, u_int32_t address
,
4373 u_int8_t layer_number
, u_int8_t format
, u_int8_t agid
,
4374 u_int8_t
*data_ptr
, u_int32_t dxfer_len
,
4375 u_int8_t sense_len
, u_int32_t timeout
)
4377 struct scsi_read_dvd_structure
*scsi_cmd
;
4379 scsi_cmd
= (struct scsi_read_dvd_structure
*)&csio
->cdb_io
.cdb_bytes
;
4380 bzero(scsi_cmd
, sizeof(*scsi_cmd
));
4381 scsi_cmd
->opcode
= READ_DVD_STRUCTURE
;
4383 scsi_ulto4b(address
, scsi_cmd
->address
);
4384 scsi_cmd
->layer_number
= layer_number
;
4385 scsi_cmd
->format
= format
;
4386 scsi_ulto2b(dxfer_len
, scsi_cmd
->alloc_len
);
4387 /* The AGID is the top two bits of this byte */
4388 scsi_cmd
->agid
= agid
<< 6;
4393 /*flags*/ CAM_DIR_IN
,
4395 /*data_ptr*/ data_ptr
,
4396 /*dxfer_len*/ dxfer_len
,