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