cd.c revision 1.155
1/*	$NetBSD: cd.c,v 1.155 2001/08/20 11:31:10 ad Exp $	*/
2
3/*-
4 * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *        This product includes software developed by the NetBSD
21 *        Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 *    contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39/*
40 * Originally written by Julian Elischer (julian@tfs.com)
41 * for TRW Financial Systems for use under the MACH(2.5) operating system.
42 *
43 * TRW Financial Systems, in accordance with their agreement with Carnegie
44 * Mellon University, makes this software available to CMU to distribute
45 * or use in any manner that they see fit as long as this message is kept with
46 * the software. For this reason TFS also grants any other persons or
47 * organisations permission to use or modify this software.
48 *
49 * TFS supplies this software to be publicly redistributed
50 * on the understanding that TFS is not responsible for the correct
51 * functioning of this software in any circumstances.
52 *
53 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
54 */
55
56#include "rnd.h"
57
58#include <sys/types.h>
59#include <sys/param.h>
60#include <sys/systm.h>
61#include <sys/kernel.h>
62#include <sys/file.h>
63#include <sys/stat.h>
64#include <sys/ioctl.h>
65#include <sys/buf.h>
66#include <sys/uio.h>
67#include <sys/malloc.h>
68#include <sys/errno.h>
69#include <sys/device.h>
70#include <sys/disklabel.h>
71#include <sys/disk.h>
72#include <sys/cdio.h>
73#include <sys/dvdio.h>
74#include <sys/scsiio.h>
75#include <sys/proc.h>
76#include <sys/conf.h>
77#include <sys/vnode.h>
78#if NRND > 0
79#include <sys/rnd.h>
80#endif
81
82#include <dev/scsipi/scsipi_all.h>
83#include <dev/scsipi/scsipi_cd.h>
84#include <dev/scsipi/scsipi_disk.h>	/* rw_big and start_stop come */
85					/* from there */
86#include <dev/scsipi/scsi_disk.h>	/* rw comes from there */
87#include <dev/scsipi/scsipiconf.h>
88#include <dev/scsipi/cdvar.h>
89
90#include "cd.h"		/* NCD_SCSIBUS and NCD_ATAPIBUS come from here */
91
92#define	CDUNIT(z)			DISKUNIT(z)
93#define	CDPART(z)			DISKPART(z)
94#define	CDMINOR(unit, part)		DISKMINOR(unit, part)
95#define	MAKECDDEV(maj, unit, part)	MAKEDISKDEV(maj, unit, part)
96
97#define MAXTRACK	99
98#define CD_BLOCK_OFFSET	150
99#define CD_FRAMES	75
100#define CD_SECS		60
101
102struct cd_toc {
103	struct ioc_toc_header header;
104	struct cd_toc_entry entries[MAXTRACK+1]; /* One extra for the */
105						 /* leadout */
106};
107
108int	cdlock __P((struct cd_softc *));
109void	cdunlock __P((struct cd_softc *));
110void	cdstart __P((struct scsipi_periph *));
111void	cdminphys __P((struct buf *));
112void	cdgetdefaultlabel __P((struct cd_softc *, struct disklabel *));
113void	cdgetdisklabel __P((struct cd_softc *));
114void	cddone __P((struct scsipi_xfer *));
115void	cdbounce __P((struct buf *));
116int	cd_interpret_sense __P((struct scsipi_xfer *));
117u_long	cd_size __P((struct cd_softc *, int));
118void	lba2msf __P((u_long, u_char *, u_char *, u_char *));
119u_long	msf2lba __P((u_char, u_char, u_char));
120int	cd_play __P((struct cd_softc *, int, int));
121int	cd_play_tracks __P((struct cd_softc *, int, int, int, int));
122int	cd_play_msf __P((struct cd_softc *, int, int, int, int, int, int));
123int	cd_pause __P((struct cd_softc *, int));
124int	cd_reset __P((struct cd_softc *));
125int	cd_read_subchannel __P((struct cd_softc *, int, int, int,
126	    struct cd_sub_channel_info *, int, int));
127int	cd_read_toc __P((struct cd_softc *, int, int, void *, int, int, int));
128int	cd_get_parms __P((struct cd_softc *, int));
129int	cd_load_toc __P((struct cd_softc *, struct cd_toc *, int));
130int	dvd_auth __P((struct cd_softc *, dvd_authinfo *));
131int	dvd_read_physical __P((struct cd_softc *, dvd_struct *));
132int	dvd_read_copyright __P((struct cd_softc *, dvd_struct *));
133int	dvd_read_disckey __P((struct cd_softc *, dvd_struct *));
134int	dvd_read_bca __P((struct cd_softc *, dvd_struct *));
135int	dvd_read_manufact __P((struct cd_softc *, dvd_struct *));
136int	dvd_read_struct __P((struct cd_softc *, dvd_struct *));
137
138extern struct cfdriver cd_cd;
139
140struct dkdriver cddkdriver = { cdstrategy };
141
142const struct scsipi_periphsw cd_switch = {
143	cd_interpret_sense,	/* use our error handler first */
144	cdstart,		/* we have a queue, which is started by this */
145	NULL,			/* we do not have an async handler */
146	cddone,			/* deal with stats at interrupt time */
147};
148
149/*
150 * The routine called by the low level scsi routine when it discovers
151 * A device suitable for this driver
152 */
153void
154cdattach(parent, cd, periph, ops)
155	struct device *parent;
156	struct cd_softc *cd;
157	struct scsipi_periph *periph;
158	const struct cd_ops *ops;
159{
160	SC_DEBUG(periph, SCSIPI_DB2, ("cdattach: "));
161
162	BUFQ_INIT(&cd->buf_queue);
163
164	/*
165	 * Store information needed to contact our base driver
166	 */
167	cd->sc_periph = periph;
168	cd->sc_ops = ops;
169
170	periph->periph_dev = &cd->sc_dev;
171	periph->periph_switch = &cd_switch;
172
173	/*
174	 * Increase our openings to the maximum-per-periph
175	 * supported by the adapter.  This will either be
176	 * clamped down or grown by the adapter if necessary.
177	 */
178	periph->periph_openings =
179	    SCSIPI_CHAN_MAX_PERIPH(periph->periph_channel);
180	periph->periph_flags |= PERIPH_GROW_OPENINGS;
181
182	/*
183	 * Initialize and attach the disk structure.
184	 */
185  	cd->sc_dk.dk_driver = &cddkdriver;
186	cd->sc_dk.dk_name = cd->sc_dev.dv_xname;
187	disk_attach(&cd->sc_dk);
188
189#ifdef __BROKEN_DK_ESTABLISH
190	dk_establish(&cd->sc_dk, &cd->sc_dev);		/* XXX */
191#endif
192
193	printf("\n");
194
195#if NRND > 0
196	rnd_attach_source(&cd->rnd_source, cd->sc_dev.dv_xname,
197			  RND_TYPE_DISK, 0);
198#endif
199}
200
201int
202cdactivate(self, act)
203	struct device *self;
204	enum devact act;
205{
206	int rv = 0;
207
208	switch (act) {
209	case DVACT_ACTIVATE:
210		rv = EOPNOTSUPP;
211		break;
212
213	case DVACT_DEACTIVATE:
214		/*
215		 * Nothing to do; we key off the device's DVF_ACTIVE.
216		 */
217		break;
218	}
219	return (rv);
220}
221
222int
223cddetach(self, flags)
224	struct device *self;
225	int flags;
226{
227	struct cd_softc *cd = (struct cd_softc *) self;
228	struct buf *bp;
229	int s, bmaj, cmaj, i, mn;
230
231	/* locate the major number */
232	for (bmaj = 0; bmaj <= nblkdev; bmaj++)
233		if (bdevsw[bmaj].d_open == cdopen)
234			break;
235	for (cmaj = 0; cmaj <= nchrdev; cmaj++)
236		if (cdevsw[cmaj].d_open == cdopen)
237			break;
238
239	s = splbio();
240
241	/* Kill off any queued buffers. */
242	while ((bp = BUFQ_FIRST(&cd->buf_queue)) != NULL) {
243		BUFQ_REMOVE(&cd->buf_queue, bp);
244		bp->b_error = EIO;
245		bp->b_flags |= B_ERROR;
246		bp->b_resid = bp->b_bcount;
247		biodone(bp);
248	}
249
250	/* Kill off any pending commands. */
251	scsipi_kill_pending(cd->sc_periph);
252
253	splx(s);
254
255	/* Nuke the vnodes for any open instances */
256	for (i = 0; i < MAXPARTITIONS; i++) {
257		mn = CDMINOR(self->dv_unit, i);
258		vdevgone(bmaj, mn, mn, VBLK);
259		vdevgone(cmaj, mn, mn, VCHR);
260	}
261
262	/* Detach from the disk list. */
263	disk_detach(&cd->sc_dk);
264
265#if 0
266	/* Get rid of the shutdown hook. */
267	if (cd->sc_sdhook != NULL)
268		shutdownhook_disestablish(cd->sc_sdhook);
269#endif
270
271#if NRND > 0
272	/* Unhook the entropy source. */
273	rnd_detach_source(&cd->rnd_source);
274#endif
275
276	return (0);
277}
278
279/*
280 * Wait interruptibly for an exclusive lock.
281 *
282 * XXX
283 * Several drivers do this; it should be abstracted and made MP-safe.
284 */
285int
286cdlock(cd)
287	struct cd_softc *cd;
288{
289	int error;
290
291	while ((cd->flags & CDF_LOCKED) != 0) {
292		cd->flags |= CDF_WANTED;
293		if ((error = tsleep(cd, PRIBIO | PCATCH, "cdlck", 0)) != 0)
294			return (error);
295	}
296	cd->flags |= CDF_LOCKED;
297	return (0);
298}
299
300/*
301 * Unlock and wake up any waiters.
302 */
303void
304cdunlock(cd)
305	struct cd_softc *cd;
306{
307
308	cd->flags &= ~CDF_LOCKED;
309	if ((cd->flags & CDF_WANTED) != 0) {
310		cd->flags &= ~CDF_WANTED;
311		wakeup(cd);
312	}
313}
314
315/*
316 * open the device. Make sure the partition info is a up-to-date as can be.
317 */
318int
319cdopen(dev, flag, fmt, p)
320	dev_t dev;
321	int flag, fmt;
322	struct proc *p;
323{
324	struct cd_softc *cd;
325	struct scsipi_periph *periph;
326	struct scsipi_adapter *adapt;
327	struct cd_sub_channel_info data;
328	int unit, part;
329	int error;
330
331	unit = CDUNIT(dev);
332	if (unit >= cd_cd.cd_ndevs)
333		return (ENXIO);
334	cd = cd_cd.cd_devs[unit];
335	if (cd == NULL)
336		return (ENXIO);
337
338	periph = cd->sc_periph;
339	adapt = periph->periph_channel->chan_adapter;
340	part = CDPART(dev);
341
342	SC_DEBUG(periph, SCSIPI_DB1,
343	    ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
344	    cd_cd.cd_ndevs, CDPART(dev)));
345
346	/*
347	 * If this is the first open of this device, add a reference
348	 * to the adapter.
349	 */
350	if (cd->sc_dk.dk_openmask == 0 &&
351	    (error = scsipi_adapter_addref(adapt)) != 0)
352		return (error);
353
354	if ((error = cdlock(cd)) != 0)
355		goto bad4;
356
357	if ((periph->periph_flags & PERIPH_OPEN) != 0) {
358		/*
359		 * If any partition is open, but the disk has been invalidated,
360		 * disallow further opens.
361		 */
362		if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0 &&
363			(part != RAW_PART || fmt != S_IFCHR )) {
364			error = EIO;
365			goto bad3;
366		}
367	} else {
368		/* Check that it is still responding and ok. */
369		error = scsipi_test_unit_ready(periph,
370		    XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE |
371		    XS_CTL_SILENT_NODEV);
372		SC_DEBUG(periph, SCSIPI_DB1,
373		    ("cdopen: scsipi_test_unit_ready, error=%d\n", error));
374		if (error) {
375			if (part != RAW_PART || fmt != S_IFCHR)
376				goto bad3;
377			else
378				goto out;
379		}
380
381		/* Don't try to start the unit if audio is playing. */
382		error = cd_read_subchannel(cd, CD_LBA_FORMAT,
383		    CD_CURRENT_POSITION, 0, &data, sizeof(data),
384		    XS_CTL_DATA_ONSTACK);
385		if ((data.header.audio_status != CD_AS_PLAY_IN_PROGRESS &&
386		    data.header.audio_status != CD_AS_PLAY_PAUSED) || error) {
387			/*
388			 * Start the pack spinning if necessary. Always
389			 * allow the raw parition to be opened, for raw
390			 * IOCTLs. Data transfers will check for
391			 * SDEV_MEDIA_LOADED.
392			 */
393			error = scsipi_start(periph, SSS_START,
394			    XS_CTL_IGNORE_ILLEGAL_REQUEST |
395			    XS_CTL_IGNORE_MEDIA_CHANGE |
396			    XS_CTL_SILENT);
397			SC_DEBUG(periph, SCSIPI_DB1,
398			    ("cdopen: scsipi_start, error=%d\n", error));
399			if (error) {
400				if (part != RAW_PART || fmt != S_IFCHR)
401					goto bad3;
402				else
403					goto out;
404			}
405		}
406
407		periph->periph_flags |= PERIPH_OPEN;
408
409		/* Lock the pack in. */
410		error = scsipi_prevent(periph, PR_PREVENT,
411		    XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE);
412		SC_DEBUG(periph, SCSIPI_DB1,
413		    ("cdopen: scsipi_prevent, error=%d\n", error));
414		if (error)
415			goto bad;
416
417		if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
418			periph->periph_flags |= PERIPH_MEDIA_LOADED;
419
420			/* Load the physical device parameters. */
421			if (cd_get_parms(cd, 0) != 0) {
422				error = ENXIO;
423				goto bad2;
424			}
425			SC_DEBUG(periph, SCSIPI_DB3, ("Params loaded "));
426
427			/* Fabricate a disk label. */
428			cdgetdisklabel(cd);
429			SC_DEBUG(periph, SCSIPI_DB3, ("Disklabel fabricated "));
430		}
431	}
432
433	/* Check that the partition exists. */
434	if (part != RAW_PART &&
435	    (part >= cd->sc_dk.dk_label->d_npartitions ||
436	    cd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
437		error = ENXIO;
438		goto bad;
439	}
440
441out:	/* Insure only one open at a time. */
442	switch (fmt) {
443	case S_IFCHR:
444		cd->sc_dk.dk_copenmask |= (1 << part);
445		break;
446	case S_IFBLK:
447		cd->sc_dk.dk_bopenmask |= (1 << part);
448		break;
449	}
450	cd->sc_dk.dk_openmask =
451	    cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
452
453	SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
454	cdunlock(cd);
455	return (0);
456
457bad2:
458	periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
459
460bad:
461	if (cd->sc_dk.dk_openmask == 0) {
462		scsipi_prevent(periph, PR_ALLOW,
463		    XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE);
464		periph->periph_flags &= ~PERIPH_OPEN;
465	}
466
467bad3:
468	cdunlock(cd);
469bad4:
470	if (cd->sc_dk.dk_openmask == 0)
471		scsipi_adapter_delref(adapt);
472	return (error);
473}
474
475/*
476 * close the device.. only called if we are the LAST
477 * occurence of an open device
478 */
479int
480cdclose(dev, flag, fmt, p)
481	dev_t dev;
482	int flag, fmt;
483	struct proc *p;
484{
485	struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(dev)];
486	struct scsipi_periph *periph = cd->sc_periph;
487	struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
488	int part = CDPART(dev);
489	int error;
490
491	if ((error = cdlock(cd)) != 0)
492		return (error);
493
494	switch (fmt) {
495	case S_IFCHR:
496		cd->sc_dk.dk_copenmask &= ~(1 << part);
497		break;
498	case S_IFBLK:
499		cd->sc_dk.dk_bopenmask &= ~(1 << part);
500		break;
501	}
502	cd->sc_dk.dk_openmask =
503	    cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
504
505	if (cd->sc_dk.dk_openmask == 0) {
506		scsipi_wait_drain(periph);
507
508		scsipi_prevent(periph, PR_ALLOW,
509		    XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE |
510		    XS_CTL_IGNORE_NOT_READY);
511		periph->periph_flags &= ~PERIPH_OPEN;
512
513		scsipi_wait_drain(periph);
514
515		scsipi_adapter_delref(adapt);
516	}
517
518	cdunlock(cd);
519	return (0);
520}
521
522/*
523 * Actually translate the requested transfer into one the physical driver can
524 * understand.  The transfer is described by a buf and will include only one
525 * physical transfer.
526 */
527void
528cdstrategy(bp)
529	struct buf *bp;
530{
531	struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(bp->b_dev)];
532	struct disklabel *lp;
533	struct scsipi_periph *periph = cd->sc_periph;
534	daddr_t blkno;
535	int s;
536
537	SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cdstrategy "));
538	SC_DEBUG(cd->sc_periph, SCSIPI_DB1,
539	    ("%ld bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));
540	/*
541	 * If the device has been made invalid, error out
542	 * maybe the media changed
543	 */
544	if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
545		if (periph->periph_flags & PERIPH_OPEN)
546			bp->b_error = EIO;
547		else
548			bp->b_error = ENODEV;
549		goto bad;
550	}
551
552	lp = cd->sc_dk.dk_label;
553
554	/*
555	 * The transfer must be a whole number of blocks, offset must not
556	 * be negative.
557	 */
558	if ((bp->b_bcount % lp->d_secsize) != 0 ||
559	    bp->b_blkno < 0 ) {
560		bp->b_error = EINVAL;
561		goto bad;
562	}
563	/*
564	 * If it's a null transfer, return immediately
565	 */
566	if (bp->b_bcount == 0)
567		goto done;
568
569	/*
570	 * Do bounds checking, adjust transfer. if error, process.
571	 * If end of partition, just return.
572	 */
573	if (CDPART(bp->b_dev) != RAW_PART &&
574	    bounds_check_with_label(bp, lp,
575	    (cd->flags & (CDF_WLABEL|CDF_LABELLING)) != 0) <= 0)
576		goto done;
577
578	/*
579	 * Now convert the block number to absolute and put it in
580	 * terms of the device's logical block size.
581	 */
582	blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
583	if (CDPART(bp->b_dev) != RAW_PART)
584		blkno += lp->d_partitions[CDPART(bp->b_dev)].p_offset;
585
586	bp->b_rawblkno = blkno;
587
588	/*
589	 * If the disklabel sector size does not match the device
590	 * sector size we may need to do some extra work.
591	 */
592	if (lp->d_secsize != cd->params.blksize) {
593
594		/*
595		 * If the xfer is not a multiple of the device block size
596		 * or it is not block aligned, we need to bounce it.
597		 */
598		if ((bp->b_bcount % cd->params.blksize) != 0 ||
599			((blkno * lp->d_secsize) % cd->params.blksize) != 0) {
600			struct buf *nbp;
601			void *bounce = NULL;
602			long count;
603
604			if ((bp->b_flags & B_READ) == 0) {
605
606				/* XXXX We don't support bouncing writes. */
607				bp->b_error = EACCES;
608				goto bad;
609			}
610			count = ((blkno * lp->d_secsize) % cd->params.blksize);
611			/* XXX Store starting offset in bp->b_rawblkno */
612			bp->b_rawblkno = count;
613
614			count += bp->b_bcount;
615			count = roundup(count, cd->params.blksize);
616
617			blkno = ((blkno * lp->d_secsize) / cd->params.blksize);
618			s = splbio();
619			nbp = pool_get(&bufpool, PR_NOWAIT);
620			splx(s);
621			if (!nbp) {
622				/* No memory -- fail the iop. */
623				bp->b_error = ENOMEM;
624				goto bad;
625			}
626			bounce = malloc(count, M_DEVBUF, M_NOWAIT);
627			if (!bounce) {
628				/* No memory -- fail the iop. */
629				s = splbio();
630				pool_put(&bufpool, nbp);
631				splx(s);
632				bp->b_error = ENOMEM;
633				goto bad;
634			}
635
636			/* Set up the IOP to the bounce buffer. */
637			nbp->b_error = 0;
638			nbp->b_proc = bp->b_proc;
639			nbp->b_vp = NULLVP;
640
641			nbp->b_bcount = count;
642			nbp->b_bufsize = count;
643			nbp->b_data = bounce;
644
645			LIST_INIT(&nbp->b_dep);
646			nbp->b_rawblkno = blkno;
647
648			/* We need to do a read-modify-write operation */
649			nbp->b_flags = bp->b_flags | B_READ | B_CALL;
650			nbp->b_iodone = cdbounce;
651
652			/* Put ptr to orig buf in b_private and use new buf */
653			nbp->b_private = bp;
654			bp = nbp;
655
656		} else {
657			/* Xfer is aligned -- just adjust the start block */
658			bp->b_rawblkno = (blkno * lp->d_secsize) /
659				cd->params.blksize;
660		}
661	}
662	s = splbio();
663
664	/*
665	 * Place it in the queue of disk activities for this disk.
666	 *
667	 * XXX Only do disksort() if the current operating mode does not
668	 * XXX include tagged queueing.
669	 */
670	disksort_blkno(&cd->buf_queue, bp);
671
672	/*
673	 * Tell the device to get going on the transfer if it's
674	 * not doing anything, otherwise just wait for completion
675	 */
676	cdstart(cd->sc_periph);
677
678	splx(s);
679	return;
680
681bad:
682	bp->b_flags |= B_ERROR;
683done:
684	/*
685	 * Correctly set the buf to indicate a completed xfer
686	 */
687	bp->b_resid = bp->b_bcount;
688	biodone(bp);
689}
690
691/*
692 * cdstart looks to see if there is a buf waiting for the device
693 * and that the device is not already busy. If both are true,
694 * It deques the buf and creates a scsi command to perform the
695 * transfer in the buf. The transfer request will call scsipi_done
696 * on completion, which will in turn call this routine again
697 * so that the next queued transfer is performed.
698 * The bufs are queued by the strategy routine (cdstrategy)
699 *
700 * This routine is also called after other non-queued requests
701 * have been made of the scsi driver, to ensure that the queue
702 * continues to be drained.
703 *
704 * must be called at the correct (highish) spl level
705 * cdstart() is called at splbio from cdstrategy and scsipi_done
706 */
707void
708cdstart(periph)
709	struct scsipi_periph *periph;
710{
711	struct cd_softc *cd = (void *)periph->periph_dev;
712	struct buf *bp = 0;
713	struct scsipi_rw_big cmd_big;
714#if NCD_SCSIBUS > 0
715	struct scsi_rw cmd_small;
716#endif
717	struct scsipi_generic *cmdp;
718	int flags, nblks, cmdlen, error;
719
720	SC_DEBUG(periph, SCSIPI_DB2, ("cdstart "));
721	/*
722	 * Check if the device has room for another command
723	 */
724	while (periph->periph_active < periph->periph_openings) {
725		/*
726		 * there is excess capacity, but a special waits
727		 * It'll need the adapter as soon as we clear out of the
728		 * way and let it run (user level wait).
729		 */
730		if (periph->periph_flags & PERIPH_WAITING) {
731			periph->periph_flags &= ~PERIPH_WAITING;
732			wakeup((caddr_t)periph);
733			return;
734		}
735
736		/*
737		 * See if there is a buf with work for us to do..
738		 */
739		if ((bp = BUFQ_FIRST(&cd->buf_queue)) == NULL)
740			return;
741		BUFQ_REMOVE(&cd->buf_queue, bp);
742
743		/*
744		 * If the device has become invalid, abort all the
745		 * reads and writes until all files have been closed and
746		 * re-opened
747		 */
748		if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
749			bp->b_error = EIO;
750			bp->b_flags |= B_ERROR;
751			bp->b_resid = bp->b_bcount;
752			biodone(bp);
753			continue;
754		}
755
756		/*
757		 * We have a buf, now we should make a command.
758		 */
759
760		nblks = howmany(bp->b_bcount, cd->params.blksize);
761
762#if NCD_SCSIBUS > 0
763		/*
764		 *  Fill out the scsi command.  If the transfer will
765		 *  fit in a "small" cdb, use it.
766		 */
767		if (((bp->b_rawblkno & 0x1fffff) == bp->b_rawblkno) &&
768		    ((nblks & 0xff) == nblks) &&
769		    !(periph->periph_quirks & PQUIRK_ONLYBIG) &&
770		    scsipi_periph_bustype(periph) == SCSIPI_BUSTYPE_SCSI) {
771			/*
772			 * We can fit in a small cdb.
773			 */
774			memset(&cmd_small, 0, sizeof(cmd_small));
775			cmd_small.opcode = (bp->b_flags & B_READ) ?
776			    SCSI_READ_COMMAND : SCSI_WRITE_COMMAND;
777			_lto3b(bp->b_rawblkno, cmd_small.addr);
778			cmd_small.length = nblks & 0xff;
779			cmdlen = sizeof(cmd_small);
780			cmdp = (struct scsipi_generic *)&cmd_small;
781		} else
782#endif
783		{
784			/*
785			 * Need a large cdb.
786			 */
787			memset(&cmd_big, 0, sizeof(cmd_big));
788			cmd_big.opcode = (bp->b_flags & B_READ) ?
789			    READ_BIG : WRITE_BIG;
790			_lto4b(bp->b_rawblkno, cmd_big.addr);
791			_lto2b(nblks, cmd_big.length);
792			cmdlen = sizeof(cmd_big);
793			cmdp = (struct scsipi_generic *)&cmd_big;
794		}
795
796		/* Instrumentation. */
797		disk_busy(&cd->sc_dk);
798
799		/*
800		 * Figure out what flags to use.
801		 */
802		flags = XS_CTL_NOSLEEP|XS_CTL_ASYNC;
803		if (bp->b_flags & B_READ)
804			flags |= XS_CTL_DATA_IN;
805		else
806			flags |= XS_CTL_DATA_OUT;
807		if (bp->b_flags & B_ORDERED)
808			flags |= XS_CTL_ORDERED_TAG;
809		else
810			flags |= XS_CTL_SIMPLE_TAG;
811
812		/*
813		 * Call the routine that chats with the adapter.
814		 * Note: we cannot sleep as we may be an interrupt
815		 */
816		error = scsipi_command(periph, cmdp, cmdlen,
817		    (u_char *)bp->b_data, bp->b_bcount,
818		    CDRETRIES, 30000, bp, flags);
819		if (error) {
820			disk_unbusy(&cd->sc_dk, 0);
821			printf("%s: not queued, error %d\n",
822			    cd->sc_dev.dv_xname, error);
823		}
824	}
825}
826
827void
828cddone(xs)
829	struct scsipi_xfer *xs;
830{
831	struct cd_softc *cd = (void *)xs->xs_periph->periph_dev;
832
833	if (xs->bp != NULL) {
834		disk_unbusy(&cd->sc_dk, xs->bp->b_bcount - xs->bp->b_resid);
835#if NRND > 0
836		rnd_add_uint32(&cd->rnd_source, xs->bp->b_rawblkno);
837#endif
838	}
839}
840
841void
842cdbounce(bp)
843	struct buf *bp;
844{
845	struct buf *obp = (struct buf *)bp->b_private;
846
847	if (bp->b_flags & B_ERROR) {
848		/* EEK propagate the error and free the memory */
849		goto done;
850	}
851	if (obp->b_flags & B_READ) {
852		/* Copy data to the final destination and free the buf. */
853		memcpy(obp->b_data, bp->b_data+obp->b_rawblkno,
854			obp->b_bcount);
855	} else {
856		/*
857		 * XXXX This is a CD-ROM -- READ ONLY -- why do we bother with
858		 * XXXX any of this write stuff?
859		 */
860		if (bp->b_flags & B_READ) {
861			struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(bp->b_dev)];
862			struct buf *nbp;
863			int s;
864
865			/* Read part of RMW complete. */
866			memcpy(bp->b_data+obp->b_rawblkno, obp->b_data,
867				obp->b_bcount);
868
869			s = splbio();
870
871			/* We need to alloc a new buf. */
872			nbp = pool_get(&bufpool, PR_NOWAIT);
873			if (!nbp) {
874				splx(s);
875				/* No buf available. */
876				bp->b_flags |= B_ERROR;
877				bp->b_error = ENOMEM;
878				bp->b_resid = bp->b_bcount;
879			}
880
881			/* Set up the IOP to the bounce buffer. */
882			nbp->b_error = 0;
883			nbp->b_proc = bp->b_proc;
884			nbp->b_vp = NULLVP;
885
886			nbp->b_bcount = bp->b_bcount;
887			nbp->b_bufsize = bp->b_bufsize;
888			nbp->b_data = bp->b_data;
889
890			LIST_INIT(&nbp->b_dep);
891			nbp->b_rawblkno = bp->b_rawblkno;
892
893			/* We need to do a read-modify-write operation */
894			nbp->b_flags = obp->b_flags | B_CALL;
895			nbp->b_iodone = cdbounce;
896
897			/* Put ptr to orig buf in b_private and use new buf */
898			nbp->b_private = obp;
899
900			/*
901			 * Place it in the queue of disk activities for this
902			 * disk.
903			 *
904			 * XXX Only do disksort() if the current operating mode
905			 * XXX does not include tagged queueing.
906			 */
907			disksort_blkno(&cd->buf_queue, nbp);
908
909			/*
910			 * Tell the device to get going on the transfer if it's
911			 * not doing anything, otherwise just wait for
912			 * completion
913			 */
914			cdstart(cd->sc_periph);
915
916			splx(s);
917			return;
918
919		}
920	}
921done:
922	obp->b_flags |= (bp->b_flags&(B_EINTR|B_ERROR));
923	obp->b_error = bp->b_error;
924	obp->b_resid = bp->b_resid;
925	free(bp->b_data, M_DEVBUF);
926	biodone(obp);
927}
928
929int cd_interpret_sense(xs)
930	struct scsipi_xfer *xs;
931{
932	struct scsipi_periph *periph = xs->xs_periph;
933	struct scsipi_sense_data *sense = &xs->sense.scsi_sense;
934	int retval = EJUSTRETURN;
935
936	/*
937	 * If it isn't a extended or extended/deferred error, let
938	 * the generic code handle it.
939	 */
940	if ((sense->error_code & SSD_ERRCODE) != 0x70 &&
941	    (sense->error_code & SSD_ERRCODE) != 0x71) {	/* DEFERRED */
942		return (retval);
943	}
944
945	switch (sense->flags & SSD_KEY) {
946		/*
947		 * If we got a "Unit not ready" (SKEY_NOT_READY) and
948		 * "Logical Unit Is In The Process of Becoming Ready" (Sense
949		 * code 0x04,0x01), then wait a bit for the drive to spin up
950		 */
951		case SKEY_NOT_READY:
952			if (sense->add_sense_code == 0x4 &&
953			    sense->add_sense_code_qual == 0x01)	{
954				/*
955				 * Sleep for 5 seconds to wait for the drive to spin up
956				 */
957				SC_DEBUG(periph, SCSIPI_DB1, ("Waiting 5 sec for CD "
958								"spinup\n"));
959				scsipi_periph_freeze(periph, 1);
960				callout_reset(&periph->periph_callout,
961						5 * hz, scsipi_periph_timed_thaw, periph);
962				retval = ERESTART;
963			}
964			break;
965
966		/*
967		 * If we receive notification that the medium has changed,
968		 * then retry the operation.
969		 */
970		case SKEY_UNIT_ATTENTION:
971			if (sense->add_sense_code == 0x28 &&
972			    sense->add_sense_code_qual == 0x00)
973				retval = ERESTART;
974			break;
975		default:
976			break;
977	}
978
979	return (retval);
980}
981
982void
983cdminphys(bp)
984	struct buf *bp;
985{
986	struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(bp->b_dev)];
987	long max;
988
989	/*
990	 * If the device is ancient, we want to make sure that
991	 * the transfer fits into a 6-byte cdb.
992	 *
993	 * XXX Note that the SCSI-I spec says that 256-block transfers
994	 * are allowed in a 6-byte read/write, and are specified
995	 * by settng the "length" to 0.  However, we're conservative
996	 * here, allowing only 255-block transfers in case an
997	 * ancient device gets confused by length == 0.  A length of 0
998	 * in a 10-byte read/write actually means 0 blocks.
999	 */
1000	if (cd->flags & CDF_ANCIENT) {
1001		max = cd->sc_dk.dk_label->d_secsize * 0xff;
1002
1003		if (bp->b_bcount > max)
1004			bp->b_bcount = max;
1005	}
1006
1007	(*cd->sc_periph->periph_channel->chan_adapter->adapt_minphys)(bp);
1008}
1009
1010int
1011cdread(dev, uio, ioflag)
1012	dev_t dev;
1013	struct uio *uio;
1014	int ioflag;
1015{
1016
1017	return (physio(cdstrategy, NULL, dev, B_READ, cdminphys, uio));
1018}
1019
1020int
1021cdwrite(dev, uio, ioflag)
1022	dev_t dev;
1023	struct uio *uio;
1024	int ioflag;
1025{
1026
1027	return (physio(cdstrategy, NULL, dev, B_WRITE, cdminphys, uio));
1028}
1029
1030/*
1031 * conversion between minute-seconde-frame and logical block adress
1032 * adresses format
1033 */
1034void
1035lba2msf (lba, m, s, f)
1036	u_long lba;
1037	u_char *m, *s, *f;
1038{
1039	u_long tmp;
1040
1041	tmp = lba + CD_BLOCK_OFFSET;	/* offset of first logical frame */
1042	tmp &= 0xffffff;		/* negative lbas use only 24 bits */
1043	*m = tmp / (CD_SECS * CD_FRAMES);
1044	tmp %= (CD_SECS * CD_FRAMES);
1045	*s = tmp / CD_FRAMES;
1046	*f = tmp % CD_FRAMES;
1047}
1048
1049u_long
1050msf2lba (m, s, f)
1051	u_char m, s, f;
1052{
1053
1054	return ((((m * CD_SECS) + s) * CD_FRAMES + f) - CD_BLOCK_OFFSET);
1055}
1056
1057
1058/*
1059 * Perform special action on behalf of the user.
1060 * Knows about the internals of this device
1061 */
1062int
1063cdioctl(dev, cmd, addr, flag, p)
1064	dev_t dev;
1065	u_long cmd;
1066	caddr_t addr;
1067	int flag;
1068	struct proc *p;
1069{
1070	struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(dev)];
1071	struct scsipi_periph *periph = cd->sc_periph;
1072	int part = CDPART(dev);
1073	int error;
1074#ifdef __HAVE_OLD_DISKLABEL
1075	struct disklabel newlabel;
1076#endif
1077
1078	SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cdioctl 0x%lx ", cmd));
1079
1080	/*
1081	 * If the device is not valid, some IOCTLs can still be
1082	 * handled on the raw partition. Check this here.
1083	 */
1084	if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
1085		switch (cmd) {
1086		case DIOCWLABEL:
1087		case DIOCLOCK:
1088		case ODIOCEJECT:
1089		case DIOCEJECT:
1090		case SCIOCIDENTIFY:
1091		case OSCIOCIDENTIFY:
1092		case SCIOCCOMMAND:
1093		case SCIOCDEBUG:
1094		case CDIOCGETVOL:
1095		case CDIOCSETVOL:
1096		case CDIOCSETMONO:
1097		case CDIOCSETSTEREO:
1098		case CDIOCSETMUTE:
1099		case CDIOCSETLEFT:
1100		case CDIOCSETRIGHT:
1101		case CDIOCCLOSE:
1102		case CDIOCEJECT:
1103		case CDIOCALLOW:
1104		case CDIOCPREVENT:
1105		case CDIOCSETDEBUG:
1106		case CDIOCCLRDEBUG:
1107		case CDIOCRESET:
1108		case SCIOCRESET:
1109		case CDIOCLOADUNLOAD:
1110		case DVD_AUTH:
1111		case DVD_READ_STRUCT:
1112			if (part == RAW_PART)
1113				break;
1114		/* FALLTHROUGH */
1115		default:
1116			if ((periph->periph_flags & PERIPH_OPEN) == 0)
1117				return (ENODEV);
1118			else
1119				return (EIO);
1120		}
1121	}
1122
1123	switch (cmd) {
1124	case DIOCGDINFO:
1125		*(struct disklabel *)addr = *(cd->sc_dk.dk_label);
1126		return (0);
1127#ifdef __HAVE_OLD_DISKLABEL
1128	case ODIOCGDINFO:
1129		newlabel = *(cd->sc_dk.dk_label);
1130		if (newlabel.d_npartitions > OLDMAXPARTITIONS)
1131			return ENOTTY;
1132		memcpy(addr, &newlabel, sizeof (struct olddisklabel));
1133		return (0);
1134#endif
1135
1136	case DIOCGPART:
1137		((struct partinfo *)addr)->disklab = cd->sc_dk.dk_label;
1138		((struct partinfo *)addr)->part =
1139		    &cd->sc_dk.dk_label->d_partitions[part];
1140		return (0);
1141
1142	case DIOCWDINFO:
1143	case DIOCSDINFO:
1144#ifdef __HAVE_OLD_DISKLABEL
1145	case ODIOCWDINFO:
1146	case ODIOCSDINFO:
1147#endif
1148	{
1149		struct disklabel *lp;
1150
1151#ifdef __HAVE_OLD_DISKLABEL
1152		if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
1153			memset(&newlabel, 0, sizeof newlabel);
1154			memcpy(&newlabel, addr, sizeof (struct olddisklabel));
1155			lp = &newlabel;
1156		} else
1157#endif
1158		lp = (struct disklabel *)addr;
1159
1160		if ((flag & FWRITE) == 0)
1161			return (EBADF);
1162
1163		if ((error = cdlock(cd)) != 0)
1164			return (error);
1165		cd->flags |= CDF_LABELLING;
1166
1167		error = setdisklabel(cd->sc_dk.dk_label,
1168		    lp, /*cd->sc_dk.dk_openmask : */0,
1169		    cd->sc_dk.dk_cpulabel);
1170		if (error == 0) {
1171			/* XXX ? */
1172		}
1173
1174		cd->flags &= ~CDF_LABELLING;
1175		cdunlock(cd);
1176		return (error);
1177	}
1178
1179	case DIOCWLABEL:
1180		return (EBADF);
1181
1182	case DIOCGDEFLABEL:
1183		cdgetdefaultlabel(cd, (struct disklabel *)addr);
1184		return (0);
1185
1186#ifdef __HAVE_OLD_DISKLABEL
1187	case ODIOCGDEFLABEL:
1188		cdgetdefaultlabel(cd, &newlabel);
1189		if (newlabel.d_npartitions > OLDMAXPARTITIONS)
1190			return ENOTTY;
1191		memcpy(addr, &newlabel, sizeof (struct olddisklabel));
1192		return (0);
1193#endif
1194
1195	case CDIOCPLAYTRACKS: {
1196		struct ioc_play_track *args = (struct ioc_play_track *)addr;
1197
1198		if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd, 0)) != 0)
1199			return (error);
1200		return (cd_play_tracks(cd, args->start_track,
1201		    args->start_index, args->end_track, args->end_index));
1202	}
1203	case CDIOCPLAYMSF: {
1204		struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
1205
1206		if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd, 0)) != 0)
1207			return (error);
1208		return (cd_play_msf(cd, args->start_m, args->start_s,
1209		    args->start_f, args->end_m, args->end_s, args->end_f));
1210	}
1211	case CDIOCPLAYBLOCKS: {
1212		struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
1213
1214		if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd, 0)) != 0)
1215			return (error);
1216		return (cd_play(cd, args->blk, args->len));
1217	}
1218	case CDIOCREADSUBCHANNEL: {
1219		struct ioc_read_subchannel *args =
1220		    (struct ioc_read_subchannel *)addr;
1221		struct cd_sub_channel_info data;
1222		int len = args->data_len;
1223
1224		if (len > sizeof(data) ||
1225		    len < sizeof(struct cd_sub_channel_header))
1226			return (EINVAL);
1227		error = cd_read_subchannel(cd, args->address_format,
1228		    args->data_format, args->track, &data, len,
1229		    XS_CTL_DATA_ONSTACK);
1230		if (error)
1231			return (error);
1232		len = min(len, _2btol(data.header.data_len) +
1233		    sizeof(struct cd_sub_channel_header));
1234		return (copyout(&data, args->data, len));
1235	}
1236	case CDIOREADTOCHEADER: {
1237		struct ioc_toc_header th;
1238
1239		if ((error = cd_read_toc(cd, 0, 0, &th, sizeof(th),
1240		    XS_CTL_DATA_ONSTACK, 0)) != 0)
1241			return (error);
1242		if (cd->sc_periph->periph_quirks & PQUIRK_LITTLETOC) {
1243#if BYTE_ORDER == BIG_ENDIAN
1244			bswap((u_int8_t *)&th.len, sizeof(th.len));
1245#endif
1246		} else
1247			th.len = ntohs(th.len);
1248		memcpy(addr, &th, sizeof(th));
1249		return (0);
1250	}
1251	case CDIOREADTOCENTRYS: {
1252		struct cd_toc toc;
1253		struct ioc_read_toc_entry *te =
1254		    (struct ioc_read_toc_entry *)addr;
1255		struct ioc_toc_header *th;
1256		struct cd_toc_entry *cte;
1257		int len = te->data_len;
1258		int ntracks;
1259
1260		th = &toc.header;
1261
1262		if (len > sizeof(toc.entries) ||
1263		    len < sizeof(struct cd_toc_entry))
1264			return (EINVAL);
1265		error = cd_read_toc(cd, te->address_format, te->starting_track,
1266		    &toc, len + sizeof(struct ioc_toc_header),
1267		    XS_CTL_DATA_ONSTACK, 0);
1268		if (error)
1269			return (error);
1270		if (te->address_format == CD_LBA_FORMAT)
1271			for (ntracks =
1272			    th->ending_track - th->starting_track + 1;
1273			    ntracks >= 0; ntracks--) {
1274				cte = &toc.entries[ntracks];
1275				cte->addr_type = CD_LBA_FORMAT;
1276				if (periph->periph_quirks & PQUIRK_LITTLETOC) {
1277#if BYTE_ORDER == BIG_ENDIAN
1278					bswap((u_int8_t*)&cte->addr,
1279					    sizeof(cte->addr));
1280#endif
1281				} else
1282					cte->addr.lba = ntohl(cte->addr.lba);
1283			}
1284		if (periph->periph_quirks & PQUIRK_LITTLETOC) {
1285#if BYTE_ORDER == BIG_ENDIAN
1286			bswap((u_int8_t*)&th->len, sizeof(th->len));
1287#endif
1288		} else
1289			th->len = ntohs(th->len);
1290		len = min(len, th->len - (sizeof(th->starting_track) +
1291		    sizeof(th->ending_track)));
1292		return (copyout(toc.entries, te->data, len));
1293	}
1294	case CDIOREADMSADDR: {
1295		struct cd_toc toc;
1296		int sessno = *(int*)addr;
1297		struct cd_toc_entry *cte;
1298
1299		if (sessno != 0)
1300			return (EINVAL);
1301
1302		error = cd_read_toc(cd, 0, 0, &toc,
1303		  sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry),
1304		  XS_CTL_DATA_ONSTACK,
1305		  0x40 /* control word for "get MS info" */);
1306
1307		if (error)
1308			return (error);
1309
1310		cte = &toc.entries[0];
1311		if (periph->periph_quirks & PQUIRK_LITTLETOC) {
1312#if BYTE_ORDER == BIG_ENDIAN
1313			bswap((u_int8_t*)&cte->addr, sizeof(cte->addr));
1314#endif
1315		} else
1316			cte->addr.lba = ntohl(cte->addr.lba);
1317		if (periph->periph_quirks & PQUIRK_LITTLETOC) {
1318#if BYTE_ORDER == BIG_ENDIAN
1319			bswap((u_int8_t*)&toc.header.len,
1320			    sizeof(toc.header.len));
1321#endif
1322		} else
1323			toc.header.len = ntohs(toc.header.len);
1324
1325		*(int*)addr = (toc.header.len >= 10 && cte->track > 1) ?
1326			cte->addr.lba : 0;
1327		return 0;
1328	}
1329	case CDIOCSETPATCH: {
1330		struct ioc_patch *arg = (struct ioc_patch *)addr;
1331
1332		return ((*cd->sc_ops->cdo_setchan)(cd, arg->patch[0],
1333		    arg->patch[1], arg->patch[2], arg->patch[3], 0));
1334	}
1335	case CDIOCGETVOL: {
1336		struct ioc_vol *arg = (struct ioc_vol *)addr;
1337
1338		return ((*cd->sc_ops->cdo_getvol)(cd, arg, 0));
1339	}
1340	case CDIOCSETVOL: {
1341		struct ioc_vol *arg = (struct ioc_vol *)addr;
1342
1343		return ((*cd->sc_ops->cdo_setvol)(cd, arg, 0));
1344	}
1345
1346	case CDIOCSETMONO:
1347		return ((*cd->sc_ops->cdo_setchan)(cd, BOTH_CHANNEL,
1348		    BOTH_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
1349
1350	case CDIOCSETSTEREO:
1351		return ((*cd->sc_ops->cdo_setchan)(cd, LEFT_CHANNEL,
1352		    RIGHT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
1353
1354	case CDIOCSETMUTE:
1355		return ((*cd->sc_ops->cdo_setchan)(cd, MUTE_CHANNEL,
1356		    MUTE_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
1357
1358	case CDIOCSETLEFT:
1359		return ((*cd->sc_ops->cdo_setchan)(cd, LEFT_CHANNEL,
1360		    LEFT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
1361
1362	case CDIOCSETRIGHT:
1363		return ((*cd->sc_ops->cdo_setchan)(cd, RIGHT_CHANNEL,
1364		    RIGHT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
1365
1366	case CDIOCRESUME:
1367		return (cd_pause(cd, PA_RESUME));
1368	case CDIOCPAUSE:
1369		return (cd_pause(cd, PA_PAUSE));
1370	case CDIOCSTART:
1371		return (scsipi_start(periph, SSS_START, 0));
1372	case CDIOCSTOP:
1373		return (scsipi_start(periph, SSS_STOP, 0));
1374	case CDIOCCLOSE:
1375		return (scsipi_start(periph, SSS_START|SSS_LOEJ,
1376		    XS_CTL_IGNORE_NOT_READY | XS_CTL_IGNORE_MEDIA_CHANGE));
1377	case DIOCEJECT:
1378		if (*(int *)addr == 0) {
1379			/*
1380			 * Don't force eject: check that we are the only
1381			 * partition open. If so, unlock it.
1382			 */
1383			if ((cd->sc_dk.dk_openmask & ~(1 << part)) == 0 &&
1384			    cd->sc_dk.dk_bopenmask + cd->sc_dk.dk_copenmask ==
1385			    cd->sc_dk.dk_openmask) {
1386				error = scsipi_prevent(periph, PR_ALLOW,
1387				    XS_CTL_IGNORE_NOT_READY);
1388				if (error)
1389					return (error);
1390			} else {
1391				return (EBUSY);
1392			}
1393		}
1394		/* FALLTHROUGH */
1395	case CDIOCEJECT: /* FALLTHROUGH */
1396	case ODIOCEJECT:
1397		return (scsipi_start(periph, SSS_STOP|SSS_LOEJ, 0));
1398	case CDIOCALLOW:
1399		return (scsipi_prevent(periph, PR_ALLOW, 0));
1400	case CDIOCPREVENT:
1401		return (scsipi_prevent(periph, PR_PREVENT, 0));
1402	case DIOCLOCK:
1403		return (scsipi_prevent(periph,
1404		    (*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0));
1405	case CDIOCSETDEBUG:
1406		cd->sc_periph->periph_dbflags |= (SCSIPI_DB1 | SCSIPI_DB2);
1407		return (0);
1408	case CDIOCCLRDEBUG:
1409		cd->sc_periph->periph_dbflags &= ~(SCSIPI_DB1 | SCSIPI_DB2);
1410		return (0);
1411	case CDIOCRESET:
1412	case SCIOCRESET:
1413		return (cd_reset(cd));
1414	case CDIOCLOADUNLOAD: {
1415		struct ioc_load_unload *args = (struct ioc_load_unload *)addr;
1416
1417		return ((*cd->sc_ops->cdo_load_unload)(cd, args->options,
1418			args->slot));
1419	case DVD_AUTH:
1420		return (dvd_auth(cd, (dvd_authinfo *)addr));
1421	case DVD_READ_STRUCT:
1422		return (dvd_read_struct(cd, (dvd_struct *)addr));
1423	}
1424
1425	default:
1426		if (part != RAW_PART)
1427			return (ENOTTY);
1428		return (scsipi_do_ioctl(periph, dev, cmd, addr, flag, p));
1429	}
1430
1431#ifdef DIAGNOSTIC
1432	panic("cdioctl: impossible");
1433#endif
1434}
1435
1436void
1437cdgetdefaultlabel(cd, lp)
1438	struct cd_softc *cd;
1439	struct disklabel *lp;
1440{
1441
1442	memset(lp, 0, sizeof(struct disklabel));
1443
1444	lp->d_secsize = cd->params.blksize;
1445	lp->d_ntracks = 1;
1446	lp->d_nsectors = 100;
1447	lp->d_ncylinders = (cd->params.disksize / 100) + 1;
1448	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1449
1450	switch (scsipi_periph_bustype(cd->sc_periph)) {
1451#if NCD_SCSIBUS > 0
1452	case SCSIPI_BUSTYPE_SCSI:
1453		lp->d_type = DTYPE_SCSI;
1454		break;
1455#endif
1456#if NCD_ATAPIBUS > 0
1457	case SCSIPI_BUSTYPE_ATAPI:
1458		lp->d_type = DTYPE_ATAPI;
1459		break;
1460#endif
1461	}
1462	strncpy(lp->d_typename, cd->name, 16);
1463	strncpy(lp->d_packname, "fictitious", 16);
1464	lp->d_secperunit = cd->params.disksize;
1465	lp->d_rpm = 300;
1466	lp->d_interleave = 1;
1467	lp->d_flags = D_REMOVABLE;
1468
1469	lp->d_partitions[0].p_offset = 0;
1470	lp->d_partitions[0].p_size =
1471	    lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
1472	lp->d_partitions[0].p_fstype = FS_ISO9660;
1473	lp->d_partitions[RAW_PART].p_offset = 0;
1474	lp->d_partitions[RAW_PART].p_size =
1475	    lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
1476	lp->d_partitions[RAW_PART].p_fstype = FS_ISO9660;
1477	lp->d_npartitions = RAW_PART + 1;
1478
1479	lp->d_magic = DISKMAGIC;
1480	lp->d_magic2 = DISKMAGIC;
1481	lp->d_checksum = dkcksum(lp);
1482}
1483
1484/*
1485 * Load the label information on the named device
1486 * Actually fabricate a disklabel
1487 *
1488 * EVENTUALLY take information about different
1489 * data tracks from the TOC and put it in the disklabel
1490 */
1491void
1492cdgetdisklabel(cd)
1493	struct cd_softc *cd;
1494{
1495	struct disklabel *lp = cd->sc_dk.dk_label;
1496	char *errstring;
1497
1498	memset(cd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
1499
1500	cdgetdefaultlabel(cd, lp);
1501
1502	/*
1503	 * Call the generic disklabel extraction routine
1504	 */
1505	errstring = readdisklabel(MAKECDDEV(0, cd->sc_dev.dv_unit, RAW_PART),
1506	    cdstrategy, lp, cd->sc_dk.dk_cpulabel);
1507	if (errstring) {
1508		printf("%s: %s\n", cd->sc_dev.dv_xname, errstring);
1509		goto error;
1510	}
1511	return;
1512
1513error:
1514	/* Reset to default label -- should print a warning */
1515	memset(cd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
1516
1517	cdgetdefaultlabel(cd, lp);
1518}
1519
1520/*
1521 * Find out from the device what it's capacity is
1522 */
1523u_long
1524cd_size(cd, flags)
1525	struct cd_softc *cd;
1526	int flags;
1527{
1528	struct scsipi_read_cd_cap_data rdcap;
1529	struct scsipi_read_cd_capacity scsipi_cmd;
1530	int blksize;
1531	u_long size;
1532
1533	if (cd->sc_periph->periph_quirks & PQUIRK_NOCAPACITY) {
1534		/*
1535		 * the drive doesn't support the READ_CD_CAPACITY command
1536		 * use a fake size
1537		 */
1538		cd->params.blksize = 2048;
1539		cd->params.disksize = 400000;
1540		return (400000);
1541	}
1542
1543	/*
1544	 * make up a scsi command and ask the scsi driver to do
1545	 * it for you.
1546	 */
1547	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
1548	scsipi_cmd.opcode = READ_CD_CAPACITY;
1549
1550	/*
1551	 * If the command works, interpret the result as a 4 byte
1552	 * number of blocks and a blocksize
1553	 */
1554	if (scsipi_command(cd->sc_periph,
1555	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
1556	    (u_char *)&rdcap, sizeof(rdcap), CDRETRIES, 30000, NULL,
1557	    flags | XS_CTL_DATA_IN | XS_CTL_DATA_IN) != 0)
1558		return (0);
1559
1560	blksize = _4btol(rdcap.length);
1561	if ((blksize < 512) || ((blksize & 511) != 0))
1562		blksize = 2048;	/* some drives lie ! */
1563	cd->params.blksize = blksize;
1564
1565	size = _4btol(rdcap.addr) + 1;
1566	if (size < 100)
1567		size = 400000;	/* ditto */
1568	cd->params.disksize = size;
1569
1570	SC_DEBUG(cd->sc_periph, SCSIPI_DB2,
1571	    ("cd_size: %d %ld\n", blksize, size));
1572	return (size);
1573}
1574
1575/*
1576 * Get scsi driver to send a "start playing" command
1577 */
1578int
1579cd_play(cd, blkno, nblks)
1580	struct cd_softc *cd;
1581	int blkno, nblks;
1582{
1583	struct scsipi_play scsipi_cmd;
1584
1585	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
1586	scsipi_cmd.opcode = PLAY;
1587	_lto4b(blkno, scsipi_cmd.blk_addr);
1588	_lto2b(nblks, scsipi_cmd.xfer_len);
1589	return (scsipi_command(cd->sc_periph,
1590	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
1591	    0, 0, CDRETRIES, 30000, NULL, 0));
1592}
1593
1594/*
1595 * Get scsi driver to send a "start playing" command
1596 */
1597int
1598cd_play_tracks(cd, strack, sindex, etrack, eindex)
1599	struct cd_softc *cd;
1600	int strack, sindex, etrack, eindex;
1601{
1602	struct cd_toc toc;
1603	int error;
1604
1605	if (!etrack)
1606		return (EIO);
1607	if (strack > etrack)
1608		return (EINVAL);
1609
1610	if ((error = cd_load_toc(cd, &toc, XS_CTL_DATA_ONSTACK)) != 0)
1611		return (error);
1612
1613	if (++etrack > (toc.header.ending_track+1))
1614		etrack = toc.header.ending_track+1;
1615
1616	strack -= toc.header.starting_track;
1617	etrack -= toc.header.starting_track;
1618	if (strack < 0)
1619		return (EINVAL);
1620
1621	return (cd_play_msf(cd, toc.entries[strack].addr.msf.minute,
1622	    toc.entries[strack].addr.msf.second,
1623	    toc.entries[strack].addr.msf.frame,
1624	    toc.entries[etrack].addr.msf.minute,
1625	    toc.entries[etrack].addr.msf.second,
1626	    toc.entries[etrack].addr.msf.frame));
1627}
1628
1629/*
1630 * Get scsi driver to send a "play msf" command
1631 */
1632int
1633cd_play_msf(cd, startm, starts, startf, endm, ends, endf)
1634	struct cd_softc *cd;
1635	int startm, starts, startf, endm, ends, endf;
1636{
1637	struct scsipi_play_msf scsipi_cmd;
1638
1639	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
1640	scsipi_cmd.opcode = PLAY_MSF;
1641	scsipi_cmd.start_m = startm;
1642	scsipi_cmd.start_s = starts;
1643	scsipi_cmd.start_f = startf;
1644	scsipi_cmd.end_m = endm;
1645	scsipi_cmd.end_s = ends;
1646	scsipi_cmd.end_f = endf;
1647	return (scsipi_command(cd->sc_periph,
1648	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
1649	    0, 0, CDRETRIES, 30000, NULL, 0));
1650}
1651
1652/*
1653 * Get scsi driver to send a "start up" command
1654 */
1655int
1656cd_pause(cd, go)
1657	struct cd_softc *cd;
1658	int go;
1659{
1660	struct scsipi_pause scsipi_cmd;
1661
1662	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
1663	scsipi_cmd.opcode = PAUSE;
1664	scsipi_cmd.resume = go & 0xff;
1665	return (scsipi_command(cd->sc_periph,
1666	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
1667	    0, 0, CDRETRIES, 30000, NULL, 0));
1668}
1669
1670/*
1671 * Get scsi driver to send a "RESET" command
1672 */
1673int
1674cd_reset(cd)
1675	struct cd_softc *cd;
1676{
1677
1678	return (scsipi_command(cd->sc_periph, 0, 0, 0, 0,
1679	    CDRETRIES, 30000, NULL, XS_CTL_RESET));
1680}
1681
1682/*
1683 * Read subchannel
1684 */
1685int
1686cd_read_subchannel(cd, mode, format, track, data, len, flags)
1687	struct cd_softc *cd;
1688	int mode, format, track, len;
1689	struct cd_sub_channel_info *data;
1690	int flags;
1691{
1692	struct scsipi_read_subchannel scsipi_cmd;
1693
1694	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
1695	scsipi_cmd.opcode = READ_SUBCHANNEL;
1696	if (mode == CD_MSF_FORMAT)
1697		scsipi_cmd.byte2 |= CD_MSF;
1698	scsipi_cmd.byte3 = SRS_SUBQ;
1699	scsipi_cmd.subchan_format = format;
1700	scsipi_cmd.track = track;
1701	_lto2b(len, scsipi_cmd.data_len);
1702	return (scsipi_command(cd->sc_periph,
1703	    (struct scsipi_generic *)&scsipi_cmd,
1704	    sizeof(struct scsipi_read_subchannel), (u_char *)data, len,
1705	    CDRETRIES, 30000, NULL, flags | XS_CTL_DATA_IN | XS_CTL_SILENT));
1706}
1707
1708/*
1709 * Read table of contents
1710 */
1711int
1712cd_read_toc(cd, mode, start, data, len, flags, control)
1713	struct cd_softc *cd;
1714	int mode, start, len, control;
1715	void *data;
1716	int flags;
1717{
1718	struct scsipi_read_toc scsipi_cmd;
1719	int ntoc;
1720
1721	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
1722#if 0
1723	if (len != sizeof(struct ioc_toc_header))
1724		ntoc = ((len) - sizeof(struct ioc_toc_header)) /
1725		    sizeof(struct cd_toc_entry);
1726	else
1727#endif
1728	ntoc = len;
1729	scsipi_cmd.opcode = READ_TOC;
1730	if (mode == CD_MSF_FORMAT)
1731		scsipi_cmd.byte2 |= CD_MSF;
1732	scsipi_cmd.from_track = start;
1733	_lto2b(ntoc, scsipi_cmd.data_len);
1734	scsipi_cmd.control = control;
1735	return (scsipi_command(cd->sc_periph,
1736	    (struct scsipi_generic *)&scsipi_cmd,
1737	    sizeof(struct scsipi_read_toc), (u_char *)data, len, CDRETRIES,
1738	    30000, NULL, flags | XS_CTL_DATA_IN));
1739}
1740
1741int
1742cd_load_toc(cd, toc, flags)
1743	struct cd_softc *cd;
1744	struct cd_toc *toc;
1745	int flags;
1746{
1747	int ntracks, len, error;
1748
1749	if ((error = cd_read_toc(cd, 0, 0, toc, sizeof(toc->header),
1750	    flags, 0)) != 0)
1751		return (error);
1752
1753	ntracks = toc->header.ending_track - toc->header.starting_track + 1;
1754	len = (ntracks + 1) * sizeof(struct cd_toc_entry) +
1755	    sizeof(toc->header);
1756	if ((error = cd_read_toc(cd, CD_MSF_FORMAT, 0, toc, len,
1757	    flags, 0)) != 0)
1758		return (error);
1759	return (0);
1760}
1761
1762/*
1763 * Get the scsi driver to send a full inquiry to the device and use the
1764 * results to fill out the disk parameter structure.
1765 */
1766int
1767cd_get_parms(cd, flags)
1768	struct cd_softc *cd;
1769	int flags;
1770{
1771
1772	/*
1773	 * give a number of sectors so that sec * trks * cyls
1774	 * is <= disk_size
1775	 */
1776	if (cd_size(cd, flags) == 0)
1777		return (ENXIO);
1778	return (0);
1779}
1780
1781int
1782cdsize(dev)
1783	dev_t dev;
1784{
1785
1786	/* CD-ROMs are read-only. */
1787	return (-1);
1788}
1789
1790int
1791cddump(dev, blkno, va, size)
1792	dev_t dev;
1793	daddr_t blkno;
1794	caddr_t va;
1795	size_t size;
1796{
1797
1798	/* Not implemented. */
1799	return (ENXIO);
1800}
1801
1802#define	dvd_copy_key(dst, src)		memcpy((dst), (src), sizeof(dvd_key))
1803#define	dvd_copy_challenge(dst, src)	memcpy((dst), (src), sizeof(dvd_challenge))
1804
1805int
1806dvd_auth(cd, a)
1807	struct cd_softc *cd;
1808	dvd_authinfo *a;
1809{
1810	struct scsipi_generic cmd;
1811	u_int8_t buf[20];
1812	int error;
1813
1814	memset(cmd.bytes, 0, 15);
1815	memset(buf, 0, sizeof(buf));
1816
1817	switch (a->type) {
1818	case DVD_LU_SEND_AGID:
1819		cmd.opcode = GPCMD_REPORT_KEY;
1820		cmd.bytes[8] = 8;
1821		cmd.bytes[9] = 0 | (0 << 6);
1822		error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 8,
1823		    CDRETRIES, 30000, NULL,
1824		    XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
1825		if (error)
1826			return (error);
1827		a->lsa.agid = buf[7] >> 6;
1828		return (0);
1829
1830	case DVD_LU_SEND_CHALLENGE:
1831		cmd.opcode = GPCMD_REPORT_KEY;
1832		cmd.bytes[8] = 16;
1833		cmd.bytes[9] = 1 | (a->lsc.agid << 6);
1834		error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 16,
1835		    CDRETRIES, 30000, NULL,
1836		    XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
1837		if (error)
1838			return (error);
1839		dvd_copy_challenge(a->lsc.chal, &buf[4]);
1840		return (0);
1841
1842	case DVD_LU_SEND_KEY1:
1843		cmd.opcode = GPCMD_REPORT_KEY;
1844		cmd.bytes[8] = 12;
1845		cmd.bytes[9] = 2 | (a->lsk.agid << 6);
1846		error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 12,
1847		    CDRETRIES, 30000, NULL,
1848		    XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
1849		if (error)
1850			return (error);
1851		dvd_copy_key(a->lsk.key, &buf[4]);
1852		return (0);
1853
1854	case DVD_LU_SEND_TITLE_KEY:
1855		cmd.opcode = GPCMD_REPORT_KEY;
1856		_lto4b(a->lstk.lba, &cmd.bytes[1]);
1857		cmd.bytes[8] = 12;
1858		cmd.bytes[9] = 4 | (a->lstk.agid << 6);
1859		error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 12,
1860		    CDRETRIES, 30000, NULL,
1861		    XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
1862		if (error)
1863			return (error);
1864		a->lstk.cpm = (buf[4] >> 7) & 1;
1865		a->lstk.cp_sec = (buf[4] >> 6) & 1;
1866		a->lstk.cgms = (buf[4] >> 4) & 3;
1867		dvd_copy_key(a->lstk.title_key, &buf[5]);
1868		return (0);
1869
1870	case DVD_LU_SEND_ASF:
1871		cmd.opcode = GPCMD_REPORT_KEY;
1872		cmd.bytes[8] = 8;
1873		cmd.bytes[9] = 5 | (a->lsasf.agid << 6);
1874		error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 8,
1875		    CDRETRIES, 30000, NULL,
1876		    XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
1877		if (error)
1878			return (error);
1879		a->lsasf.asf = buf[7] & 1;
1880		return (0);
1881
1882	case DVD_HOST_SEND_CHALLENGE:
1883		cmd.opcode = GPCMD_SEND_KEY;
1884		cmd.bytes[8] = 16;
1885		cmd.bytes[9] = 1 | (a->hsc.agid << 6);
1886		buf[1] = 14;
1887		dvd_copy_challenge(&buf[4], a->hsc.chal);
1888		error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 16,
1889		    CDRETRIES, 30000, NULL,
1890		    XS_CTL_DATA_OUT|XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
1891		if (error)
1892			return (error);
1893		a->type = DVD_LU_SEND_KEY1;
1894		return (0);
1895
1896	case DVD_HOST_SEND_KEY2:
1897		cmd.opcode = GPCMD_SEND_KEY;
1898		cmd.bytes[8] = 12;
1899		cmd.bytes[9] = 3 | (a->hsk.agid << 6);
1900		buf[1] = 10;
1901		dvd_copy_key(&buf[4], a->hsk.key);
1902		error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 12,
1903		    CDRETRIES, 30000, NULL,
1904		    XS_CTL_DATA_OUT|XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
1905		if (error) {
1906			a->type = DVD_AUTH_FAILURE;
1907			return (error);
1908		}
1909		a->type = DVD_AUTH_ESTABLISHED;
1910		return (0);
1911
1912	case DVD_INVALIDATE_AGID:
1913		cmd.opcode = GPCMD_REPORT_KEY;
1914		cmd.bytes[9] = 0x3f | (a->lsa.agid << 6);
1915		error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 16,
1916		    CDRETRIES, 30000, NULL, 0);
1917		if (error)
1918			return (error);
1919		return (0);
1920
1921	default:
1922		return (ENOTTY);
1923	}
1924}
1925
1926int
1927dvd_read_physical(cd, s)
1928	struct cd_softc *cd;
1929	dvd_struct *s;
1930{
1931	struct scsipi_generic cmd;
1932	u_int8_t buf[4 + 4 * 20], *bufp;
1933	int error;
1934	struct dvd_layer *layer;
1935	int i;
1936
1937	memset(cmd.bytes, 0, 15);
1938	memset(buf, 0, sizeof(buf));
1939	cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
1940	cmd.bytes[6] = s->type;
1941	_lto2b(sizeof(buf), &cmd.bytes[7]);
1942
1943	cmd.bytes[5] = s->physical.layer_num;
1944	error = scsipi_command(cd->sc_periph, &cmd, 12, buf, sizeof(buf),
1945	    CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
1946	if (error)
1947		return (error);
1948	for (i = 0, bufp = &buf[4], layer = &s->physical.layer[0]; i < 4;
1949	     i++, bufp += 20, layer++) {
1950		memset(layer, 0, sizeof(*layer));
1951                layer->book_version = bufp[0] & 0xf;
1952                layer->book_type = bufp[0] >> 4;
1953                layer->min_rate = bufp[1] & 0xf;
1954                layer->disc_size = bufp[1] >> 4;
1955                layer->layer_type = bufp[2] & 0xf;
1956                layer->track_path = (bufp[2] >> 4) & 1;
1957                layer->nlayers = (bufp[2] >> 5) & 3;
1958                layer->track_density = bufp[3] & 0xf;
1959                layer->linear_density = bufp[3] >> 4;
1960                layer->start_sector = _4btol(&bufp[4]);
1961                layer->end_sector = _4btol(&bufp[8]);
1962                layer->end_sector_l0 = _4btol(&bufp[12]);
1963                layer->bca = bufp[16] >> 7;
1964	}
1965	return (0);
1966}
1967
1968int
1969dvd_read_copyright(cd, s)
1970	struct cd_softc *cd;
1971	dvd_struct *s;
1972{
1973	struct scsipi_generic cmd;
1974	u_int8_t buf[8];
1975	int error;
1976
1977	memset(cmd.bytes, 0, 15);
1978	memset(buf, 0, sizeof(buf));
1979	cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
1980	cmd.bytes[6] = s->type;
1981	_lto2b(sizeof(buf), &cmd.bytes[7]);
1982
1983	cmd.bytes[5] = s->copyright.layer_num;
1984	error = scsipi_command(cd->sc_periph, &cmd, 12, buf, sizeof(buf),
1985	    CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
1986	if (error)
1987		return (error);
1988	s->copyright.cpst = buf[4];
1989	s->copyright.rmi = buf[5];
1990	return (0);
1991}
1992
1993int
1994dvd_read_disckey(cd, s)
1995	struct cd_softc *cd;
1996	dvd_struct *s;
1997{
1998	struct scsipi_generic cmd;
1999	u_int8_t buf[4 + 2048];
2000	int error;
2001
2002	memset(cmd.bytes, 0, 15);
2003	memset(buf, 0, sizeof(buf));
2004	cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
2005	cmd.bytes[6] = s->type;
2006	_lto2b(sizeof(buf), &cmd.bytes[7]);
2007
2008	cmd.bytes[9] = s->disckey.agid << 6;
2009	error = scsipi_command(cd->sc_periph, &cmd, 12, buf, sizeof(buf),
2010	    CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
2011	if (error)
2012		return (error);
2013	memcpy(s->disckey.value, &buf[4], 2048);
2014	return (0);
2015}
2016
2017int
2018dvd_read_bca(cd, s)
2019	struct cd_softc *cd;
2020	dvd_struct *s;
2021{
2022	struct scsipi_generic cmd;
2023	u_int8_t buf[4 + 188];
2024	int error;
2025
2026	memset(cmd.bytes, 0, 15);
2027	memset(buf, 0, sizeof(buf));
2028	cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
2029	cmd.bytes[6] = s->type;
2030	_lto2b(sizeof(buf), &cmd.bytes[7]);
2031
2032	error = scsipi_command(cd->sc_periph, &cmd, 12, buf, sizeof(buf),
2033	    CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
2034	if (error)
2035		return (error);
2036	s->bca.len = _2btol(&buf[0]);
2037	if (s->bca.len < 12 || s->bca.len > 188)
2038		return (EIO);
2039	memcpy(s->bca.value, &buf[4], s->bca.len);
2040	return (0);
2041}
2042
2043int
2044dvd_read_manufact(cd, s)
2045	struct cd_softc *cd;
2046	dvd_struct *s;
2047{
2048	struct scsipi_generic cmd;
2049	u_int8_t buf[4 + 2048];
2050	int error;
2051
2052	memset(cmd.bytes, 0, 15);
2053	memset(buf, 0, sizeof(buf));
2054	cmd.opcode = GPCMD_READ_DVD_STRUCTURE;
2055	cmd.bytes[6] = s->type;
2056	_lto2b(sizeof(buf), &cmd.bytes[7]);
2057
2058	error = scsipi_command(cd->sc_periph, &cmd, 12, buf, sizeof(buf),
2059	    CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
2060	if (error)
2061		return (error);
2062	s->manufact.len = _2btol(&buf[0]);
2063	if (s->manufact.len < 0 || s->manufact.len > 2048)
2064		return (EIO);
2065	memcpy(s->manufact.value, &buf[4], s->manufact.len);
2066	return (0);
2067}
2068
2069int
2070dvd_read_struct(cd, s)
2071	struct cd_softc *cd;
2072	dvd_struct *s;
2073{
2074
2075	switch (s->type) {
2076	case DVD_STRUCT_PHYSICAL:
2077		return (dvd_read_physical(cd, s));
2078	case DVD_STRUCT_COPYRIGHT:
2079		return (dvd_read_copyright(cd, s));
2080	case DVD_STRUCT_DISCKEY:
2081		return (dvd_read_disckey(cd, s));
2082	case DVD_STRUCT_BCA:
2083		return (dvd_read_bca(cd, s));
2084	case DVD_STRUCT_MANUFACT:
2085		return (dvd_read_manufact(cd, s));
2086	default:
2087		return (EINVAL);
2088	}
2089}
2090