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