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