cd.c revision 1.110
1/*	$NetBSD: cd.c,v 1.110 1998/01/15 02:21:31 cgd Exp $	*/
2
3/*
4 * Copyright (c) 1994, 1995, 1997 Charles M. Hannum.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by Charles M. Hannum.
17 * 4. The name of the author may not be used to endorse or promote products
18 *    derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * Originally written by Julian Elischer (julian@tfs.com)
34 * for TRW Financial Systems for use under the MACH(2.5) operating system.
35 *
36 * TRW Financial Systems, in accordance with their agreement with Carnegie
37 * Mellon University, makes this software available to CMU to distribute
38 * or use in any manner that they see fit as long as this message is kept with
39 * the software. For this reason TFS also grants any other persons or
40 * organisations permission to use or modify this software.
41 *
42 * TFS supplies this software to be publicly redistributed
43 * on the understanding that TFS is not responsible for the correct
44 * functioning of this software in any circumstances.
45 *
46 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
47 */
48
49#include "rnd.h"
50
51#include <sys/types.h>
52#include <sys/param.h>
53#include <sys/systm.h>
54#include <sys/kernel.h>
55#include <sys/file.h>
56#include <sys/stat.h>
57#include <sys/ioctl.h>
58#include <sys/buf.h>
59#include <sys/uio.h>
60#include <sys/malloc.h>
61#include <sys/errno.h>
62#include <sys/device.h>
63#include <sys/disklabel.h>
64#include <sys/disk.h>
65#include <sys/cdio.h>
66#include <sys/proc.h>
67#include <sys/conf.h>
68#if NRND > 0
69#include <sys/rnd.h>
70#endif
71
72#include <dev/scsipi/scsipi_all.h>
73#include <dev/scsipi/scsipi_cd.h>
74#include <dev/scsipi/scsipi_disk.h>	/* rw_big and start_stop come */
75					/* from there */
76#include <dev/scsipi/scsi_disk.h>	/* rw comes from there */
77#include <dev/scsipi/scsipiconf.h>
78#include <dev/scsipi/cdvar.h>
79
80#include "cd.h"		/* NCD_SCSIBUS and NCD_ATAPIBUS come from here */
81
82#define	CDOUTSTANDING	4
83
84#define	CDUNIT(z)			DISKUNIT(z)
85#define	CDPART(z)			DISKPART(z)
86#define	MAKECDDEV(maj, unit, part)	MAKEDISKDEV(maj, unit, part)
87
88#define MAXTRACK	99
89#define CD_BLOCK_OFFSET	150
90#define CD_FRAMES	75
91#define CD_SECS		60
92
93struct cd_toc {
94	struct ioc_toc_header header;
95	struct cd_toc_entry entries[MAXTRACK+1]; /* One extra for the */
96						 /* leadout */
97};
98
99int	cdlock __P((struct cd_softc *));
100void	cdunlock __P((struct cd_softc *));
101void	cdstart __P((void *));
102void	cdminphys __P((struct buf *));
103void	cdgetdefaultlabel __P((struct cd_softc *, struct disklabel *));
104void	cdgetdisklabel __P((struct cd_softc *));
105void	cddone __P((struct scsipi_xfer *));
106u_long	cd_size __P((struct cd_softc *, int));
107void	lba2msf __P((u_long, u_char *, u_char *, u_char *));
108u_long	msf2lba __P((u_char, u_char, u_char));
109int	cd_play __P((struct cd_softc *, int, int));
110int	cd_play_tracks __P((struct cd_softc *, int, int, int, int));
111int	cd_play_msf __P((struct cd_softc *, int, int, int, int, int, int));
112int	cd_pause __P((struct cd_softc *, int));
113int	cd_reset __P((struct cd_softc *));
114int	cd_read_subchannel __P((struct cd_softc *, int, int, int,
115	    struct cd_sub_channel_info *, int));
116int	cd_read_toc __P((struct cd_softc *, int, int, void *, int));
117int	cd_get_parms __P((struct cd_softc *, int));
118int	cd_load_toc __P((struct cd_softc *, struct cd_toc *));
119
120struct dkdriver cddkdriver = { cdstrategy };
121
122struct scsipi_device cd_switch = {
123	NULL,			/* use default error handler */
124	cdstart,		/* we have a queue, which is started by this */
125	NULL,			/* we do not have an async handler */
126	cddone,			/* deal with stats at interrupt time */
127};
128
129extern struct cfdriver cd_cd;
130
131/*
132 * The routine called by the low level scsi routine when it discovers
133 * A device suitable for this driver
134 */
135void
136cdattach(parent, cd, sc_link, ops)
137	struct device *parent;
138	struct cd_softc *cd;
139	struct scsipi_link *sc_link;
140	const struct cd_ops *ops;
141{
142	SC_DEBUG(sc_link, SDEV_DB2, ("cdattach: "));
143
144	/*
145	 * Store information needed to contact our base driver
146	 */
147	cd->sc_link = sc_link;
148	cd->sc_ops = ops;
149	sc_link->device = &cd_switch;
150	sc_link->device_softc = cd;
151	if (sc_link->openings > CDOUTSTANDING)
152		sc_link->openings = CDOUTSTANDING;
153
154	/*
155	 * Initialize and attach the disk structure.
156	 */
157  	cd->sc_dk.dk_driver = &cddkdriver;
158	cd->sc_dk.dk_name = cd->sc_dev.dv_xname;
159	disk_attach(&cd->sc_dk);
160
161#if !defined(i386)
162	dk_establish(&cd->sc_dk, &cd->sc_dev);		/* XXX */
163#endif
164
165	printf("\n");
166
167#if NRND > 0
168	rnd_attach_source(&cd->rnd_source, cd->sc_dev.dv_xname, RND_TYPE_DISK);
169#endif
170}
171
172/*
173 * Wait interruptibly for an exclusive lock.
174 *
175 * XXX
176 * Several drivers do this; it should be abstracted and made MP-safe.
177 */
178int
179cdlock(cd)
180	struct cd_softc *cd;
181{
182	int error;
183
184	while ((cd->flags & CDF_LOCKED) != 0) {
185		cd->flags |= CDF_WANTED;
186		if ((error = tsleep(cd, PRIBIO | PCATCH, "cdlck", 0)) != 0)
187			return (error);
188	}
189	cd->flags |= CDF_LOCKED;
190	return (0);
191}
192
193/*
194 * Unlock and wake up any waiters.
195 */
196void
197cdunlock(cd)
198	struct cd_softc *cd;
199{
200
201	cd->flags &= ~CDF_LOCKED;
202	if ((cd->flags & CDF_WANTED) != 0) {
203		cd->flags &= ~CDF_WANTED;
204		wakeup(cd);
205	}
206}
207
208/*
209 * open the device. Make sure the partition info is a up-to-date as can be.
210 */
211int
212cdopen(dev, flag, fmt, p)
213	dev_t dev;
214	int flag, fmt;
215	struct proc *p;
216{
217	struct cd_softc *cd;
218	struct scsipi_link *sc_link;
219	int unit, part;
220	int error;
221
222	unit = CDUNIT(dev);
223	if (unit >= cd_cd.cd_ndevs)
224		return (ENXIO);
225	cd = cd_cd.cd_devs[unit];
226	if (cd == NULL)
227		return (ENXIO);
228
229	sc_link = cd->sc_link;
230
231	SC_DEBUG(sc_link, SDEV_DB1,
232	    ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
233	    cd_cd.cd_ndevs, CDPART(dev)));
234
235	if ((error = cdlock(cd)) != 0)
236		return (error);
237
238	if (cd->sc_dk.dk_openmask != 0) {
239		/*
240		 * If any partition is open, but the disk has been invalidated,
241		 * disallow further opens.
242		 */
243		if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
244			error = EIO;
245			goto bad3;
246		}
247	} else {
248		/* Check that it is still responding and ok. */
249		error = scsipi_test_unit_ready(sc_link,
250		    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE |
251		    SCSI_IGNORE_NOT_READY);
252		SC_DEBUG(sc_link, SDEV_DB1,
253		    ("cdopen: scsipi_test_unit_ready, error=%d\n", error));
254		if (error)
255			goto bad3;
256
257		/* Start the pack spinning if necessary. */
258		error = scsipi_start(sc_link, SSS_START,
259		    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE |
260		    SCSI_SILENT);
261		SC_DEBUG(sc_link, SDEV_DB1,
262		    ("cdopen: scsipi_start, error=%d\n", error));
263		if (error)
264			goto bad3;
265
266		sc_link->flags |= SDEV_OPEN;
267
268		/* Lock the pack in. */
269		error = scsipi_prevent(sc_link, PR_PREVENT,
270		    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE);
271		SC_DEBUG(sc_link, SDEV_DB1,
272		    ("cdopen: scsipi_prevent, error=%d\n", error));
273		if (error)
274			goto bad;
275
276		if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
277			sc_link->flags |= SDEV_MEDIA_LOADED;
278
279			/* Load the physical device parameters. */
280			if (cd_get_parms(cd, 0) != 0) {
281				error = ENXIO;
282				goto bad2;
283			}
284			SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
285
286			/* Fabricate a disk label. */
287			cdgetdisklabel(cd);
288			SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated "));
289		}
290	}
291
292	part = CDPART(dev);
293
294	/* Check that the partition exists. */
295	if (part != RAW_PART &&
296	    (part >= cd->sc_dk.dk_label->d_npartitions ||
297	    cd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
298		error = ENXIO;
299		goto bad;
300	}
301
302	/* Insure only one open at a time. */
303	switch (fmt) {
304	case S_IFCHR:
305		cd->sc_dk.dk_copenmask |= (1 << part);
306		break;
307	case S_IFBLK:
308		cd->sc_dk.dk_bopenmask |= (1 << part);
309		break;
310	}
311	cd->sc_dk.dk_openmask =
312	    cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
313
314	SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
315	cdunlock(cd);
316	return (0);
317
318bad2:
319	sc_link->flags &= ~SDEV_MEDIA_LOADED;
320
321bad:
322	if (cd->sc_dk.dk_openmask == 0) {
323		scsipi_prevent(sc_link, PR_ALLOW,
324		    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE);
325		sc_link->flags &= ~SDEV_OPEN;
326	}
327
328bad3:
329	cdunlock(cd);
330	return (error);
331}
332
333/*
334 * close the device.. only called if we are the LAST
335 * occurence of an open device
336 */
337int
338cdclose(dev, flag, fmt, p)
339	dev_t dev;
340	int flag, fmt;
341	struct proc *p;
342{
343	struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(dev)];
344	int part = CDPART(dev);
345	int error;
346
347	if ((error = cdlock(cd)) != 0)
348		return (error);
349
350	switch (fmt) {
351	case S_IFCHR:
352		cd->sc_dk.dk_copenmask &= ~(1 << part);
353		break;
354	case S_IFBLK:
355		cd->sc_dk.dk_bopenmask &= ~(1 << part);
356		break;
357	}
358	cd->sc_dk.dk_openmask =
359	    cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
360
361	if (cd->sc_dk.dk_openmask == 0) {
362		/* XXXX Must wait for I/O to complete! */
363
364		scsipi_prevent(cd->sc_link, PR_ALLOW,
365		    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY);
366		cd->sc_link->flags &= ~SDEV_OPEN;
367	}
368
369	cdunlock(cd);
370	return (0);
371}
372
373/*
374 * Actually translate the requested transfer into one the physical driver can
375 * understand.  The transfer is described by a buf and will include only one
376 * physical transfer.
377 */
378void
379cdstrategy(bp)
380	struct buf *bp;
381{
382	struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(bp->b_dev)];
383	int opri;
384
385	SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdstrategy "));
386	SC_DEBUG(cd->sc_link, SDEV_DB1,
387	    ("%ld bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));
388	/*
389	 * The transfer must be a whole number of blocks.
390	 */
391	if ((bp->b_bcount % cd->sc_dk.dk_label->d_secsize) != 0) {
392		bp->b_error = EINVAL;
393		goto bad;
394	}
395	/*
396	 * If the device has been made invalid, error out
397	 * maybe the media changed
398	 */
399	if ((cd->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
400		bp->b_error = EIO;
401		goto bad;
402	}
403	/*
404	 * If it's a null transfer, return immediately
405	 */
406	if (bp->b_bcount == 0)
407		goto done;
408
409	/*
410	 * Do bounds checking, adjust transfer. if error, process.
411	 * If end of partition, just return.
412	 */
413	if (CDPART(bp->b_dev) != RAW_PART &&
414	    bounds_check_with_label(bp, cd->sc_dk.dk_label,
415	    (cd->flags & (CDF_WLABEL|CDF_LABELLING)) != 0) <= 0)
416		goto done;
417
418	opri = splbio();
419
420	/*
421	 * Place it in the queue of disk activities for this disk
422	 */
423	disksort(&cd->buf_queue, bp);
424
425	/*
426	 * Tell the device to get going on the transfer if it's
427	 * not doing anything, otherwise just wait for completion
428	 */
429	cdstart(cd);
430
431	splx(opri);
432	return;
433
434bad:
435	bp->b_flags |= B_ERROR;
436done:
437	/*
438	 * Correctly set the buf to indicate a completed xfer
439	 */
440	bp->b_resid = bp->b_bcount;
441	biodone(bp);
442}
443
444/*
445 * cdstart looks to see if there is a buf waiting for the device
446 * and that the device is not already busy. If both are true,
447 * It deques the buf and creates a scsi command to perform the
448 * transfer in the buf. The transfer request will call scsipi_done
449 * on completion, which will in turn call this routine again
450 * so that the next queued transfer is performed.
451 * The bufs are queued by the strategy routine (cdstrategy)
452 *
453 * This routine is also called after other non-queued requests
454 * have been made of the scsi driver, to ensure that the queue
455 * continues to be drained.
456 *
457 * must be called at the correct (highish) spl level
458 * cdstart() is called at splbio from cdstrategy and scsipi_done
459 */
460void
461cdstart(v)
462	register void *v;
463{
464	register struct cd_softc *cd = v;
465	register struct scsipi_link *sc_link = cd->sc_link;
466	struct disklabel *lp = cd->sc_dk.dk_label;
467	struct buf *bp = 0;
468	struct buf *dp;
469	struct scsipi_rw_big cmd_big;
470#if NCD_SCSIBUS > 0
471	struct scsi_rw cmd_small;
472#endif
473	struct scsipi_generic *cmdp;
474	int blkno, nblks, cmdlen;
475	struct partition *p;
476
477	SC_DEBUG(sc_link, SDEV_DB2, ("cdstart "));
478	/*
479	 * Check if the device has room for another command
480	 */
481	while (sc_link->openings > 0) {
482		/*
483		 * there is excess capacity, but a special waits
484		 * It'll need the adapter as soon as we clear out of the
485		 * way and let it run (user level wait).
486		 */
487		if (sc_link->flags & SDEV_WAITING) {
488			sc_link->flags &= ~SDEV_WAITING;
489			wakeup((caddr_t)sc_link);
490			return;
491		}
492
493		/*
494		 * See if there is a buf with work for us to do..
495		 */
496		dp = &cd->buf_queue;
497		if ((bp = dp->b_actf) == NULL)	/* yes, an assign */
498			return;
499		dp->b_actf = bp->b_actf;
500
501		/*
502		 * If the deivce has become invalid, abort all the
503		 * reads and writes until all files have been closed and
504		 * re-opened
505		 */
506		if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
507			bp->b_error = EIO;
508			bp->b_flags |= B_ERROR;
509			bp->b_resid = bp->b_bcount;
510			biodone(bp);
511			continue;
512		}
513
514		/*
515		 * We have a buf, now we should make a command
516		 *
517		 * First, translate the block to absolute and put it in terms
518		 * of the logical blocksize of the device.
519		 */
520		blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
521		if (CDPART(bp->b_dev) != RAW_PART) {
522			p = &lp->d_partitions[CDPART(bp->b_dev)];
523			blkno += p->p_offset;
524		}
525		nblks = howmany(bp->b_bcount, lp->d_secsize);
526
527#if NCD_SCSIBUS > 0
528		/*
529		 *  Fill out the scsi command.  If the transfer will
530		 *  fit in a "small" cdb, use it.
531		 */
532		if (((blkno & 0x1fffff) == blkno) &&
533		    ((nblks & 0xff) == nblks) && sc_link->type == BUS_SCSI) {
534			/*
535			 * We can fit in a small cdb.
536			 */
537			bzero(&cmd_small, sizeof(cmd_small));
538			cmd_small.opcode = (bp->b_flags & B_READ) ?
539			    SCSI_READ_COMMAND : SCSI_WRITE_COMMAND;
540			_lto3b(blkno, cmd_small.addr);
541			cmd_small.length = nblks & 0xff;
542			cmdlen = sizeof(cmd_small);
543			cmdp = (struct scsipi_generic *)&cmd_small;
544		} else
545#endif
546		{
547			/*
548			 * Need a large cdb.
549			 */
550			bzero(&cmd_big, sizeof(cmd_big));
551			cmd_big.opcode = (bp->b_flags & B_READ) ?
552			    READ_BIG : WRITE_BIG;
553			_lto4b(blkno, cmd_big.addr);
554			_lto2b(nblks, cmd_big.length);
555			cmdlen = sizeof(cmd_big);
556			cmdp = (struct scsipi_generic *)&cmd_big;
557		}
558
559		/* Instrumentation. */
560		disk_busy(&cd->sc_dk);
561
562		/*
563		 * Call the routine that chats with the adapter.
564		 * Note: we cannot sleep as we may be an interrupt
565		 */
566		if (scsipi_command(sc_link, cmdp, cmdlen, (u_char *)bp->b_data,
567		    bp->b_bcount, CDRETRIES, 30000, bp, SCSI_NOSLEEP |
568		    ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT))) {
569			disk_unbusy(&cd->sc_dk, 0);
570			printf("%s: not queued", cd->sc_dev.dv_xname);
571		}
572	}
573}
574
575void
576cddone(xs)
577	struct scsipi_xfer *xs;
578{
579	struct cd_softc *cd = xs->sc_link->device_softc;
580
581	if (xs->bp != NULL) {
582		disk_unbusy(&cd->sc_dk, xs->bp->b_bcount - xs->bp->b_resid);
583#if NRND > 0
584		rnd_add_uint32(&cd->rnd_source, xs->bp->b_blkno);
585#endif
586	}
587}
588
589void
590cdminphys(bp)
591	struct buf *bp;
592{
593	struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(bp->b_dev)];
594	long max;
595
596	/*
597	 * If the device is ancient, we want to make sure that
598	 * the transfer fits into a 6-byte cdb.
599	 *
600	 * XXX Note that the SCSI-I spec says that 256-block transfers
601	 * are allowed in a 6-byte read/write, and are specified
602	 * by settng the "length" to 0.  However, we're conservative
603	 * here, allowing only 255-block transfers in case an
604	 * ancient device gets confused by length == 0.  A length of 0
605	 * in a 10-byte read/write actually means 0 blocks.
606	 */
607	if (cd->flags & CDF_ANCIENT) {
608		max = cd->sc_dk.dk_label->d_secsize * 0xff;
609
610		if (bp->b_bcount > max)
611			bp->b_bcount = max;
612	}
613
614	(*cd->sc_link->adapter->scsipi_minphys)(bp);
615}
616
617int
618cdread(dev, uio, ioflag)
619	dev_t dev;
620	struct uio *uio;
621	int ioflag;
622{
623
624	return (physio(cdstrategy, NULL, dev, B_READ, cdminphys, uio));
625}
626
627int
628cdwrite(dev, uio, ioflag)
629	dev_t dev;
630	struct uio *uio;
631	int ioflag;
632{
633
634	return (physio(cdstrategy, NULL, dev, B_WRITE, cdminphys, uio));
635}
636
637/*
638 * conversion between minute-seconde-frame and logical block adress
639 * adresses format
640 */
641void
642lba2msf (lba, m, s, f)
643	u_long lba;
644	u_char *m, *s, *f;
645{
646	u_long tmp;
647
648	tmp = lba + CD_BLOCK_OFFSET;	/* offset of first logical frame */
649	tmp &= 0xffffff;		/* negative lbas use only 24 bits */
650	*m = tmp / (CD_SECS * CD_FRAMES);
651	tmp %= (CD_SECS * CD_FRAMES);
652	*s = tmp / CD_FRAMES;
653	*f = tmp % CD_FRAMES;
654}
655
656u_long
657msf2lba (m, s, f)
658	u_char m, s, f;
659{
660
661	return ((((m * CD_SECS) + s) * CD_FRAMES + f) - CD_BLOCK_OFFSET);
662}
663
664
665/*
666 * Perform special action on behalf of the user.
667 * Knows about the internals of this device
668 */
669int
670cdioctl(dev, cmd, addr, flag, p)
671	dev_t dev;
672	u_long cmd;
673	caddr_t addr;
674	int flag;
675	struct proc *p;
676{
677	struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(dev)];
678	int error;
679
680	SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%lx ", cmd));
681
682	/*
683	 * If the device is not valid.. abandon ship
684	 */
685	if ((cd->sc_link->flags & SDEV_MEDIA_LOADED) == 0)
686		return (EIO);
687
688	switch (cmd) {
689	case DIOCGDINFO:
690		*(struct disklabel *)addr = *(cd->sc_dk.dk_label);
691		return (0);
692
693	case DIOCGPART:
694		((struct partinfo *)addr)->disklab = cd->sc_dk.dk_label;
695		((struct partinfo *)addr)->part =
696		    &cd->sc_dk.dk_label->d_partitions[CDPART(dev)];
697		return (0);
698
699	case DIOCWDINFO:
700	case DIOCSDINFO:
701		if ((flag & FWRITE) == 0)
702			return (EBADF);
703
704		if ((error = cdlock(cd)) != 0)
705			return (error);
706		cd->flags |= CDF_LABELLING;
707
708		error = setdisklabel(cd->sc_dk.dk_label,
709		    (struct disklabel *)addr, /*cd->sc_dk.dk_openmask : */0,
710		    cd->sc_dk.dk_cpulabel);
711		if (error == 0) {
712			/* XXX ? */
713		}
714
715		cd->flags &= ~CDF_LABELLING;
716		cdunlock(cd);
717		return (error);
718
719	case DIOCWLABEL:
720		return (EBADF);
721
722	case DIOCGDEFLABEL:
723		cdgetdefaultlabel(cd, (struct disklabel *)addr);
724		return (0);
725
726	case CDIOCPLAYTRACKS: {
727		struct ioc_play_track *args = (struct ioc_play_track *)addr;
728
729		if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd, 0)) != 0)
730			return (error);
731		return (cd_play_tracks(cd, args->start_track,
732		    args->start_index, args->end_track, args->end_index));
733	}
734	case CDIOCPLAYMSF: {
735		struct ioc_play_msf *args = (struct ioc_play_msf *)addr;
736
737		if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd, 0)) != 0)
738			return (error);
739		return (cd_play_msf(cd, args->start_m, args->start_s,
740		    args->start_f, args->end_m, args->end_s, args->end_f));
741	}
742	case CDIOCPLAYBLOCKS: {
743		struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr;
744
745		if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd, 0)) != 0)
746			return (error);
747		return (cd_play(cd, args->blk, args->len));
748	}
749	case CDIOCREADSUBCHANNEL: {
750		struct ioc_read_subchannel *args =
751		    (struct ioc_read_subchannel *)addr;
752		struct cd_sub_channel_info data;
753		int len = args->data_len;
754
755		if (len > sizeof(data) ||
756		    len < sizeof(struct cd_sub_channel_header))
757			return (EINVAL);
758		error = cd_read_subchannel(cd, args->address_format,
759		    args->data_format, args->track, &data, len);
760		if (error)
761			return (error);
762		len = min(len, _2btol(data.header.data_len) +
763		    sizeof(struct cd_sub_channel_header));
764		return (copyout(&data, args->data, len));
765	}
766	case CDIOREADTOCHEADER: {
767		struct ioc_toc_header th;
768
769		if ((error = cd_read_toc(cd, 0, 0, &th, sizeof(th))) != 0)
770			return (error);
771		if (cd->sc_link->quirks & ADEV_LITTLETOC) {
772#if BYTE_ORDER == BIG_ENDIAN
773			bswap((u_int8_t *)&th.len, sizeof(th.len));
774#endif
775		} else
776			th.len = ntohs(th.len);
777		bcopy(&th, addr, sizeof(th));
778		return (0);
779	}
780	case CDIOREADTOCENTRYS: {
781		struct cd_toc toc;
782		struct ioc_read_toc_entry *te =
783		    (struct ioc_read_toc_entry *)addr;
784		struct ioc_toc_header *th;
785		struct cd_toc_entry *cte;
786		int len = te->data_len;
787		int ntracks;
788
789		th = &toc.header;
790
791		if (len > sizeof(toc.entries) ||
792		    len < sizeof(struct cd_toc_entry))
793			return (EINVAL);
794		error = cd_read_toc(cd, te->address_format, te->starting_track,
795		    &toc, len + sizeof(struct ioc_toc_header));
796		if (error)
797			return (error);
798		if (te->address_format == CD_LBA_FORMAT)
799			for (ntracks =
800			    th->ending_track - th->starting_track + 1;
801			    ntracks >= 0; ntracks--) {
802				cte = &toc.entries[ntracks];
803				cte->addr_type = CD_LBA_FORMAT;
804				if (cd->sc_link->quirks & ADEV_LITTLETOC) {
805#if BYTE_ORDER == BIG_ENDIAN
806					bswap((u_int8_t*)&cte->addr,
807					    sizeof(cte->addr));
808#endif
809				} else
810					cte->addr.lba = ntohl(cte->addr.lba);
811			}
812		if (cd->sc_link->quirks & ADEV_LITTLETOC) {
813#if BYTE_ORDER == BIG_ENDIAN
814			bswap((u_int8_t*)&th->len, sizeof(th->len));
815#endif
816		} else
817			th->len = ntohs(th->len);
818		len = min(len, th->len - (sizeof(th->starting_track) +
819		    sizeof(th->ending_track)));
820		return (copyout(toc.entries, te->data, len));
821	}
822	case CDIOCSETPATCH: {
823		struct ioc_patch *arg = (struct ioc_patch *)addr;
824
825		return ((*cd->sc_ops->cdo_setchan)(cd, arg->patch[0],
826		    arg->patch[1], arg->patch[2], arg->patch[3], 0));
827	}
828	case CDIOCGETVOL: {
829		struct ioc_vol *arg = (struct ioc_vol *)addr;
830
831		return ((*cd->sc_ops->cdo_getvol)(cd, arg, 0));
832	}
833	case CDIOCSETVOL: {
834		struct ioc_vol *arg = (struct ioc_vol *)addr;
835
836		return ((*cd->sc_ops->cdo_setvol)(cd, arg, 0));
837	}
838
839	case CDIOCSETMONO:
840		return ((*cd->sc_ops->cdo_setchan)(cd, BOTH_CHANNEL,
841		    BOTH_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
842
843	case CDIOCSETSTEREO:
844		return ((*cd->sc_ops->cdo_setchan)(cd, LEFT_CHANNEL,
845		    RIGHT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
846
847	case CDIOCSETMUTE:
848		return ((*cd->sc_ops->cdo_setchan)(cd, MUTE_CHANNEL,
849		    MUTE_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
850
851	case CDIOCSETLEFT:
852		return ((*cd->sc_ops->cdo_setchan)(cd, LEFT_CHANNEL,
853		    LEFT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
854
855	case CDIOCSETRIGHT:
856		return ((*cd->sc_ops->cdo_setchan)(cd, RIGHT_CHANNEL,
857		    RIGHT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL, 0));
858
859	case CDIOCRESUME:
860		return (cd_pause(cd, PA_RESUME));
861	case CDIOCPAUSE:
862		return (cd_pause(cd, PA_PAUSE));
863	case CDIOCSTART:
864		return (scsipi_start(cd->sc_link, SSS_START, 0));
865	case CDIOCSTOP:
866		return (scsipi_start(cd->sc_link, SSS_STOP, 0));
867	case CDIOCEJECT: /* FALLTHROUGH */
868	case DIOCEJECT:
869		return (scsipi_start(cd->sc_link, SSS_STOP|SSS_LOEJ, 0));
870	case CDIOCALLOW:
871		return (scsipi_prevent(cd->sc_link, PR_ALLOW, 0));
872	case CDIOCPREVENT:
873		return (scsipi_prevent(cd->sc_link, PR_PREVENT, 0));
874	case DIOCLOCK:
875		return (scsipi_prevent(cd->sc_link,
876		    (*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0));
877	case CDIOCSETDEBUG:
878		cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
879		return (0);
880	case CDIOCCLRDEBUG:
881		cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
882		return (0);
883	case CDIOCRESET:
884		return (cd_reset(cd));
885
886	default:
887		if (CDPART(dev) != RAW_PART)
888			return (ENOTTY);
889		return (scsipi_do_ioctl(cd->sc_link, dev, cmd, addr, flag, p));
890	}
891
892#ifdef DIAGNOSTIC
893	panic("cdioctl: impossible");
894#endif
895}
896
897void
898cdgetdefaultlabel(cd, lp)
899	struct cd_softc *cd;
900	struct disklabel *lp;
901{
902
903	bzero(lp, sizeof(struct disklabel));
904
905	lp->d_secsize = cd->params.blksize;
906	lp->d_ntracks = 1;
907	lp->d_nsectors = 100;
908	lp->d_ncylinders = (cd->params.disksize / 100) + 1;
909	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
910
911	strncpy(lp->d_typename, "SCSI CD-ROM", 16);
912	lp->d_type = DTYPE_SCSI;
913	strncpy(lp->d_packname, "fictitious", 16);
914	lp->d_secperunit = cd->params.disksize;
915	lp->d_rpm = 300;
916	lp->d_interleave = 1;
917	lp->d_flags = D_REMOVABLE;
918
919	lp->d_partitions[0].p_offset = 0;
920	lp->d_partitions[0].p_size =
921	    lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
922	lp->d_partitions[0].p_fstype = FS_ISO9660;
923	lp->d_partitions[RAW_PART].p_offset = 0;
924	lp->d_partitions[RAW_PART].p_size =
925	    lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
926	lp->d_partitions[RAW_PART].p_fstype = FS_ISO9660;
927	lp->d_npartitions = RAW_PART + 1;
928
929	lp->d_magic = DISKMAGIC;
930	lp->d_magic2 = DISKMAGIC;
931	lp->d_checksum = dkcksum(lp);
932}
933
934/*
935 * Load the label information on the named device
936 * Actually fabricate a disklabel
937 *
938 * EVENTUALLY take information about different
939 * data tracks from the TOC and put it in the disklabel
940 */
941void
942cdgetdisklabel(cd)
943	struct cd_softc *cd;
944{
945	struct disklabel *lp = cd->sc_dk.dk_label;
946
947	bzero(cd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
948
949	cdgetdefaultlabel(cd, lp);
950}
951
952/*
953 * Find out from the device what it's capacity is
954 */
955u_long
956cd_size(cd, flags)
957	struct cd_softc *cd;
958	int flags;
959{
960	struct scsipi_read_cd_cap_data rdcap;
961	struct scsipi_read_cd_capacity scsipi_cmd;
962	int blksize;
963	u_long size;
964
965	if (cd->sc_link->quirks & ADEV_NOCAPACITY) {
966		/*
967		 * the drive doesn't support the READ_CD_CAPACITY command
968		 * use a fake size
969		 */
970		cd->params.blksize = 2048;
971		cd->params.disksize = 400000;
972		return (400000);
973	}
974
975	/*
976	 * make up a scsi command and ask the scsi driver to do
977	 * it for you.
978	 */
979	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
980	scsipi_cmd.opcode = READ_CD_CAPACITY;
981
982	/*
983	 * If the command works, interpret the result as a 4 byte
984	 * number of blocks and a blocksize
985	 */
986	if (scsipi_command(cd->sc_link,
987	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
988	    (u_char *)&rdcap, sizeof(rdcap), CDRETRIES, 20000, NULL,
989	    flags | SCSI_DATA_IN) != 0)
990		return (0);
991
992	blksize = _4btol(rdcap.length);
993	if ((blksize < 512) || ((blksize & 511) != 0))
994		blksize = 2048;	/* some drives lie ! */
995	cd->params.blksize = blksize;
996
997	size = _4btol(rdcap.addr) + 1;
998	if (size < 100)
999		size = 400000;	/* ditto */
1000	cd->params.disksize = size;
1001
1002	SC_DEBUG(cd->sc_link, SDEV_DB2, ("cd_size: %d %ld\n", blksize, size));
1003	return (size);
1004}
1005
1006/*
1007 * Get scsi driver to send a "start playing" command
1008 */
1009int
1010cd_play(cd, blkno, nblks)
1011	struct cd_softc *cd;
1012	int blkno, nblks;
1013{
1014	struct scsipi_play scsipi_cmd;
1015
1016	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1017	scsipi_cmd.opcode = PLAY;
1018	_lto4b(blkno, scsipi_cmd.blk_addr);
1019	_lto2b(nblks, scsipi_cmd.xfer_len);
1020	return (scsipi_command(cd->sc_link,
1021	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
1022	    0, 0, CDRETRIES, 200000, NULL, 0));
1023}
1024
1025/*
1026 * Get scsi driver to send a "start playing" command
1027 */
1028int
1029cd_play_tracks(cd, strack, sindex, etrack, eindex)
1030	struct cd_softc *cd;
1031	int strack, sindex, etrack, eindex;
1032{
1033	struct cd_toc toc;
1034	int error;
1035
1036	if (!etrack)
1037		return (EIO);
1038	if (strack > etrack)
1039		return (EINVAL);
1040
1041	if ((error = cd_load_toc(cd, &toc)) != 0)
1042		return (error);
1043
1044	if (++etrack > (toc.header.ending_track+1))
1045		etrack = toc.header.ending_track+1;
1046
1047	strack -= toc.header.starting_track;
1048	etrack -= toc.header.starting_track;
1049	if (strack < 0)
1050		return (EINVAL);
1051
1052	return (cd_play_msf(cd, toc.entries[strack].addr.msf.minute,
1053	    toc.entries[strack].addr.msf.second,
1054	    toc.entries[strack].addr.msf.frame,
1055	    toc.entries[etrack].addr.msf.minute,
1056	    toc.entries[etrack].addr.msf.second,
1057	    toc.entries[etrack].addr.msf.frame));
1058}
1059
1060/*
1061 * Get scsi driver to send a "play msf" command
1062 */
1063int
1064cd_play_msf(cd, startm, starts, startf, endm, ends, endf)
1065	struct cd_softc *cd;
1066	int startm, starts, startf, endm, ends, endf;
1067{
1068	struct scsipi_play_msf scsipi_cmd;
1069
1070	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1071	scsipi_cmd.opcode = PLAY_MSF;
1072	scsipi_cmd.start_m = startm;
1073	scsipi_cmd.start_s = starts;
1074	scsipi_cmd.start_f = startf;
1075	scsipi_cmd.end_m = endm;
1076	scsipi_cmd.end_s = ends;
1077	scsipi_cmd.end_f = endf;
1078	return (scsipi_command(cd->sc_link,
1079	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
1080	    0, 0, CDRETRIES, 2000, NULL, 0));
1081}
1082
1083/*
1084 * Get scsi driver to send a "start up" command
1085 */
1086int
1087cd_pause(cd, go)
1088	struct cd_softc *cd;
1089	int go;
1090{
1091	struct scsipi_pause scsipi_cmd;
1092
1093	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1094	scsipi_cmd.opcode = PAUSE;
1095	scsipi_cmd.resume = go & 0xff;
1096	return (scsipi_command(cd->sc_link,
1097	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
1098	    0, 0, CDRETRIES, 2000, NULL, 0));
1099}
1100
1101/*
1102 * Get scsi driver to send a "RESET" command
1103 */
1104int
1105cd_reset(cd)
1106	struct cd_softc *cd;
1107{
1108
1109	return (scsipi_command(cd->sc_link, 0, 0, 0, 0,
1110	    CDRETRIES, 2000, NULL, SCSI_RESET));
1111}
1112
1113/*
1114 * Read subchannel
1115 */
1116int
1117cd_read_subchannel(cd, mode, format, track, data, len)
1118	struct cd_softc *cd;
1119	int mode, format, track, len;
1120	struct cd_sub_channel_info *data;
1121{
1122	struct scsipi_read_subchannel scsipi_cmd;
1123
1124	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1125	scsipi_cmd.opcode = READ_SUBCHANNEL;
1126	if (mode == CD_MSF_FORMAT)
1127		scsipi_cmd.byte2 |= CD_MSF;
1128	scsipi_cmd.byte3 = SRS_SUBQ;
1129	scsipi_cmd.subchan_format = format;
1130	scsipi_cmd.track = track;
1131	_lto2b(len, scsipi_cmd.data_len);
1132	return (scsipi_command(cd->sc_link,
1133	    (struct scsipi_generic *)&scsipi_cmd,
1134	    sizeof(struct scsipi_read_subchannel), (u_char *)data, len,
1135	    CDRETRIES, 5000, NULL, SCSI_DATA_IN|SCSI_SILENT));
1136}
1137
1138/*
1139 * Read table of contents
1140 */
1141int
1142cd_read_toc(cd, mode, start, data, len)
1143	struct cd_softc *cd;
1144	int mode, start, len;
1145	void *data;
1146{
1147	struct scsipi_read_toc scsipi_cmd;
1148	int ntoc;
1149
1150	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1151#if 0
1152	if (len != sizeof(struct ioc_toc_header))
1153		ntoc = ((len) - sizeof(struct ioc_toc_header)) /
1154		    sizeof(struct cd_toc_entry);
1155	else
1156#endif
1157	ntoc = len;
1158	scsipi_cmd.opcode = READ_TOC;
1159	if (mode == CD_MSF_FORMAT)
1160		scsipi_cmd.byte2 |= CD_MSF;
1161	scsipi_cmd.from_track = start;
1162	_lto2b(ntoc, scsipi_cmd.data_len);
1163	return (scsipi_command(cd->sc_link,
1164	    (struct scsipi_generic *)&scsipi_cmd,
1165	    sizeof(struct scsipi_read_toc), (u_char *)data, len, CDRETRIES,
1166	    5000, NULL, SCSI_DATA_IN));
1167}
1168
1169int
1170cd_load_toc(cd, toc)
1171	struct cd_softc *cd;
1172	struct cd_toc *toc;
1173{
1174	int ntracks, len, error;
1175
1176	if ((error = cd_read_toc(cd, 0, 0, toc, sizeof(toc->header))) != 0)
1177		return (error);
1178
1179	ntracks = toc->header.ending_track - toc->header.starting_track + 1;
1180	len = (ntracks + 1) * sizeof(struct cd_toc_entry) +
1181	    sizeof(toc->header);
1182	if ((error = cd_read_toc(cd, CD_MSF_FORMAT, 0, toc, len)) != 0)
1183		return (error);
1184	return (0);
1185}
1186
1187/*
1188 * Get the scsi driver to send a full inquiry to the device and use the
1189 * results to fill out the disk parameter structure.
1190 */
1191int
1192cd_get_parms(cd, flags)
1193	struct cd_softc *cd;
1194	int flags;
1195{
1196
1197	/*
1198	 * give a number of sectors so that sec * trks * cyls
1199	 * is <= disk_size
1200	 */
1201	if (cd_size(cd, flags) == 0)
1202		return (ENXIO);
1203	return (0);
1204}
1205
1206int
1207cdsize(dev)
1208	dev_t dev;
1209{
1210
1211	/* CD-ROMs are read-only. */
1212	return (-1);
1213}
1214
1215int
1216cddump(dev, blkno, va, size)
1217	dev_t dev;
1218	daddr_t blkno;
1219	caddr_t va;
1220	size_t size;
1221{
1222
1223	/* Not implemented. */
1224	return (ENXIO);
1225}
1226