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