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