cd.c revision 1.43
1/*	$NetBSD: cd.c,v 1.43 1994/11/22 03:23:49 mycroft Exp $	*/
2
3/*
4 * Copyright (c) 1994 Charles 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 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 <sys/types.h>
50#include <sys/param.h>
51#include <sys/systm.h>
52#include <sys/kernel.h>
53#include <sys/dkbad.h>
54#include <sys/conf.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
67#include <scsi/scsi_all.h>
68#include <scsi/scsi_cd.h>
69#include <scsi/scsi_disk.h>	/* rw_big and start_stop come from there */
70#include <scsi/scsiconf.h>
71
72#ifdef	DDB
73int	Debugger();
74#else	/* DDB */
75#define Debugger()
76#endif	/* DDB */
77
78#define	CDOUTSTANDING	2
79#define	CDRETRIES	1
80
81#define	CDUNIT(z)			DISKUNIT(z)
82#define	CDPART(z)			DISKPART(z)
83#define	MAKECDDEV(maj, unit, part)	MAKEDISKDEV(maj, unit, part)
84
85struct cd_data {
86	struct device sc_dev;
87	struct dkdevice sc_dk;
88
89	int flags;
90#define	CDF_LOCKED	0x01
91#define	CDF_WANTED	0x02
92#define	CDF_BSDLABEL	0x04
93	struct scsi_link *sc_link;	/* address of scsi low level switch */
94	u_int32 ad_info;	/* info about the adapter */
95	u_int32 cmdscount;	/* cmds allowed outstanding by board */
96	struct cd_parms {
97		u_int32 blksize;
98		u_long disksize;	/* total number sectors */
99	} params;
100	u_int32 xfer_block_wait;
101	struct buf buf_queue;
102};
103
104void cdattach __P((struct device *, struct device *, void *));
105
106struct cfdriver cdcd = {
107	NULL, "cd", scsi_targmatch, cdattach, DV_DISK, sizeof(struct cd_data)
108};
109
110void cdgetdisklabel __P((struct cd_data *));
111int cd_get_parms __P((struct cd_data *, int));
112void cdstrategy __P((struct buf *));
113void cdstart __P((struct cd_data *));
114
115struct dkdriver cddkdriver = { cdstrategy };
116
117struct scsi_device cd_switch = {
118	NULL,			/* use default error handler */
119	cdstart,		/* we have a queue, which is started by this */
120	NULL,			/* we do not have an async handler */
121	NULL,			/* use default 'done' routine */
122	"cd",			/* we are to be refered to by this name */
123	0			/* no device specific flags */
124};
125
126#define CD_STOP		0
127#define CD_START	1
128#define CD_EJECT	-2
129
130/*
131 * The routine called by the low level scsi routine when it discovers
132 * A device suitable for this driver
133 */
134void
135cdattach(parent, self, aux)
136	struct device *parent, *self;
137	void *aux;
138{
139	struct cd_data *cd = (void *)self;
140	struct cd_parms *dp = &cd->params;
141	struct scsi_link *sc_link = aux;
142
143	SC_DEBUG(sc_link, SDEV_DB2, ("cdattach: "));
144
145	/*
146	 * Store information needed to contact our base driver
147	 */
148	cd->sc_link = sc_link;
149	sc_link->device = &cd_switch;
150	sc_link->device_softc = cd;
151
152	cd->sc_dk.dk_driver = &cddkdriver;
153#if !defined(i386) || defined(NEWCONFIG)
154	dk_establish(&cd->sc_dk, &cd->sc_dev);
155#endif
156
157	if (cd->sc_link->adapter->adapter_info) {
158		cd->ad_info = ((*(cd->sc_link->adapter->adapter_info)) (sc_link->adapter_softc));
159		cd->cmdscount = cd->ad_info & AD_INF_MAX_CMDS;
160		if (cd->cmdscount > CDOUTSTANDING)
161			cd->cmdscount = CDOUTSTANDING;
162	} else {
163		cd->ad_info = 1;
164		cd->cmdscount = 1;
165	}
166	sc_link->opennings = cd->cmdscount;
167
168	/*
169	 * Use the subdriver to request information regarding
170	 * the drive. We cannot use interrupts yet, so the
171	 * request must specify this.
172	 */
173	cd_get_parms(cd, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
174	if (dp->disksize)
175		printf(": cd present, %d x %d byte records\n",
176		    cd->params.disksize, cd->params.blksize);
177	else
178		printf(": drive empty\n");
179}
180
181/*
182 * open the device. Make sure the partition info is a up-to-date as can be.
183 */
184int
185cdopen(dev, flag, fmt)
186	dev_t dev;
187	int flag, fmt;
188{
189	int error;
190	int unit, part;
191	struct cd_data *cd;
192	struct scsi_link *sc_link;
193
194	unit = CDUNIT(dev);
195	if (unit >= cdcd.cd_ndevs)
196		return ENXIO;
197	cd = cdcd.cd_devs[unit];
198	if (!cd)
199		return ENXIO;
200
201	part = CDPART(dev);
202	sc_link = cd->sc_link;
203
204	SC_DEBUG(sc_link, SDEV_DB1,
205	    ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
206	    cdcd.cd_ndevs, part));
207
208	while ((cd->flags & CDF_LOCKED) != 0) {
209		cd->flags |= CDF_WANTED;
210		if ((error = tsleep(cd, PRIBIO | PCATCH, "cdopn", 0)) != 0)
211			return error;
212	}
213
214	if (cd->sc_dk.dk_openmask != 0) {
215		/*
216		 * If any partition is open, but the disk has been invalidated,
217		 * disallow further opens.
218		 */
219		if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0)
220			return ENXIO;
221	} else {
222		cd->flags |= CDF_LOCKED;
223
224		/*
225		 * Check that it is still responding and ok.
226		 * if the media has been changed this will result in a
227		 * "unit attention" error which the error code will
228		 * disregard because the SDEV_OPEN flag is not yet set.
229		 */
230		scsi_test_unit_ready(sc_link, SCSI_SILENT);
231
232		/*
233		 * In case it is a funny one, tell it to start
234		 * not needed for some drives
235		 */
236		scsi_start(sc_link, SSS_START, SCSI_ERR_OK | SCSI_SILENT);
237
238		/*
239		 * Check that it is still responding and ok.
240		 */
241		sc_link->flags |= SDEV_OPEN;	/* unit attn errors are now errors */
242		if (scsi_test_unit_ready(sc_link, 0) != 0) {
243			SC_DEBUG(sc_link, SDEV_DB3, ("device not responding\n"));
244			error = ENXIO;
245			goto bad;
246		}
247		SC_DEBUG(sc_link, SDEV_DB3, ("device ok\n"));
248
249		/* Lock the pack in. */
250		scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
251
252		if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
253			cd->flags &= ~CDF_BSDLABEL;
254			sc_link->flags |= SDEV_MEDIA_LOADED;
255
256			/* Load the physical device parameters. */
257			if (cd_get_parms(cd, 0) != 0) {
258				error = ENXIO;
259				goto bad2;
260			}
261			SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
262
263			/* Fabricate a disk label. */
264			cdgetdisklabel(cd);
265			SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated "));
266		}
267
268		cd->flags &= ~CDF_LOCKED;
269		if ((cd->flags & CDF_WANTED) != 0) {
270			cd->flags &= ~CDF_WANTED;
271			wakeup(cd);
272		}
273	}
274
275	/* Check that the partition exists. */
276	if (part != RAW_PART &&
277	    (part >= cd->sc_dk.dk_label.d_npartitions ||
278	     cd->sc_dk.dk_label.d_partitions[part].p_fstype == FS_UNUSED)) {
279		error = ENXIO;
280		goto bad;
281	}
282
283	/* Insure only one open at a time. */
284	switch (fmt) {
285	case S_IFCHR:
286		cd->sc_dk.dk_copenmask |= (1 << part);
287		break;
288	case S_IFBLK:
289		cd->sc_dk.dk_bopenmask |= (1 << part);
290		break;
291	}
292	cd->sc_dk.dk_openmask = cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
293
294	SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
295	return 0;
296
297bad2:
298	sc_link->flags &= ~SDEV_MEDIA_LOADED;
299
300bad:
301	if (cd->sc_dk.dk_openmask == 0) {
302		scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
303		sc_link->flags &= ~SDEV_OPEN;
304	}
305
306	cd->flags &= ~CDF_LOCKED;
307	if ((cd->flags & CDF_WANTED) != 0) {
308		cd->flags &= ~CDF_WANTED;
309		wakeup(cd);
310	}
311
312	return error;
313}
314
315/*
316 * close the device.. only called if we are the LAST
317 * occurence of an open device
318 */
319int
320cdclose(dev, flag, fmt)
321	dev_t dev;
322	int flag, fmt;
323{
324	struct cd_data *cd = cdcd.cd_devs[CDUNIT(dev)];
325	int part = CDPART(dev);
326	int s;
327
328	switch (fmt) {
329	case S_IFCHR:
330		cd->sc_dk.dk_copenmask &= ~(1 << part);
331		break;
332	case S_IFBLK:
333		cd->sc_dk.dk_bopenmask &= ~(1 << part);
334		break;
335	}
336	cd->sc_dk.dk_openmask = cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
337
338	if (cd->sc_dk.dk_openmask == 0) {
339		cd->flags |= CDF_LOCKED;
340
341#if 0
342		s = splbio();
343		while (...) {
344			cd->flags |= CDF_WAITING;
345			if ((error = tsleep(cd, PRIBIO | PCATCH, "cdcls", 0)) != 0)
346				return error;
347		}
348		splx(s);
349#endif
350
351		scsi_prevent(cd->sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
352		cd->sc_link->flags &= ~SDEV_OPEN;
353
354		cd->flags &= ~CDF_LOCKED;
355		if ((cd->flags & CDF_WANTED) != 0) {
356			cd->flags &= ~CDF_WANTED;
357			wakeup(cd);
358		}
359	}
360
361	return 0;
362}
363
364/*
365 * trim the size of the transfer if needed,
366 * called by physio
367 * basically the smaller of our max and the scsi driver's
368 * minphys (note we have no max ourselves)
369 *
370 * Trim buffer length if buffer-size is bigger than page size
371 */
372void
373cdminphys(bp)
374	struct buf *bp;
375{
376	register struct cd_data *cd = cdcd.cd_devs[CDUNIT(bp->b_dev)];
377
378	(cd->sc_link->adapter->scsi_minphys) (bp);
379}
380
381/*
382 * Actually translate the requested transfer into one the physical driver can
383 * understand.  The transfer is described by a buf and will include only one
384 * physical transfer.
385 */
386void
387cdstrategy(bp)
388	struct buf *bp;
389{
390	struct cd_data *cd = cdcd.cd_devs[CDUNIT(bp->b_dev)];
391	int opri;
392
393	SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdstrategy "));
394	SC_DEBUG(cd->sc_link, SDEV_DB1,
395	    ("%d bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));
396	cdminphys(bp);
397	/*
398	 * If the device has been made invalid, error out
399	 * maybe the media changed
400	 */
401	if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED)) {
402		bp->b_error = EIO;
403		goto bad;
404	}
405	/*
406	 * can't ever write to a CD
407	 */
408	if ((bp->b_flags & B_READ) == 0) {
409		bp->b_error = EROFS;
410		goto bad;
411	}
412	/*
413	 * If it's a null transfer, return immediately
414	 */
415	if (bp->b_bcount == 0)
416		goto done;
417	/*
418	 * Decide which unit and partition we are talking about
419	 */
420	if (CDPART(bp->b_dev) != RAW_PART) {
421		if ((cd->flags & CDF_BSDLABEL) == 0) {
422			bp->b_error = EIO;
423			goto bad;
424		}
425		/*
426		 * do bounds checking, adjust transfer. if error, process.
427		 * if end of partition, just return
428		 */
429		if (bounds_check_with_label(bp, &cd->sc_dk.dk_label, 1) <= 0)
430			goto done;
431		/* otherwise, process transfer request */
432	}
433
434	opri = splbio();
435
436	/*
437	 * Place it in the queue of disk activities for this disk
438	 */
439	disksort(&cd->buf_queue, bp);
440
441	/*
442	 * Tell the device to get going on the transfer if it's
443	 * not doing anything, otherwise just wait for completion
444	 */
445	cdstart(cd);
446
447	splx(opri);
448	return;
449
450bad:
451	bp->b_flags |= B_ERROR;
452done:
453	/*
454	 * Correctly set the buf to indicate a completed xfer
455	 */
456	bp->b_resid = bp->b_bcount;
457	biodone(bp);
458}
459
460/*
461 * cdstart looks to see if there is a buf waiting for the device
462 * and that the device is not already busy. If both are true,
463 * It deques the buf and creates a scsi command to perform the
464 * transfer in the buf. The transfer request will call scsi_done
465 * on completion, which will in turn call this routine again
466 * so that the next queued transfer is performed.
467 * The bufs are queued by the strategy routine (cdstrategy)
468 *
469 * This routine is also called after other non-queued requests
470 * have been made of the scsi driver, to ensure that the queue
471 * continues to be drained.
472 *
473 * must be called at the correct (highish) spl level
474 * cdstart() is called at splbio from cdstrategy and scsi_done
475 */
476void
477cdstart(cd)
478	register struct cd_data *cd;
479{
480	register struct scsi_link *sc_link = cd->sc_link;
481	struct buf *bp = 0;
482	struct buf *dp;
483	struct scsi_rw_big cmd;
484	int blkno, nblks;
485	struct partition *p;
486
487	SC_DEBUG(sc_link, SDEV_DB2, ("cdstart "));
488	/*
489	 * See if there is a buf to do and we are not already
490	 * doing one
491	 */
492	while (sc_link->opennings) {
493		/*
494		 * there is excess capacity, but a special waits
495		 * It'll need the adapter as soon as we clear out of the
496		 * way and let it run (user level wait).
497		 */
498		if (sc_link->flags & SDEV_WAITING) {
499			sc_link->flags &= ~SDEV_WAITING;
500			wakeup((caddr_t)sc_link);
501			return;
502		}
503
504		/*
505		 * See if there is a buf with work for us to do..
506		 */
507		dp = &cd->buf_queue;
508		if ((bp = dp->b_actf) == NULL)	/* yes, an assign */
509			return;
510		dp->b_actf = bp->b_actf;
511
512		/*
513		 * If the deivce has become invalid, abort all the
514		 * reads and writes until all files have been closed and
515		 * re-openned
516		 */
517		if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
518			bp->b_error = EIO;
519			bp->b_flags |= B_ERROR;
520			biodone(bp);
521			continue;
522		}
523
524		/*
525		 * We have a buf, now we should make a command
526		 *
527		 * First, translate the block to absolute and put it in terms
528		 * of the logical blocksize of the device.  Really a bit silly
529		 * until we have real partitions, but.
530		 */
531		blkno =
532		    bp->b_blkno / (cd->sc_dk.dk_label.d_secsize / DEV_BSIZE);
533		if (CDPART(bp->b_dev) != RAW_PART) {
534			p = &cd->sc_dk.dk_label.d_partitions[CDPART(bp->b_dev)];
535			blkno += p->p_offset;
536		}
537		nblks = howmany(bp->b_bcount, cd->sc_dk.dk_label.d_secsize);
538
539		/*
540		 *  Fill out the scsi command
541		 */
542		bzero(&cmd, sizeof(cmd));
543		cmd.op_code = (bp->b_flags & B_READ) ? READ_BIG : WRITE_BIG;
544		cmd.addr_3 = (blkno & 0xff000000) >> 24;
545		cmd.addr_2 = (blkno & 0xff0000) >> 16;
546		cmd.addr_1 = (blkno & 0xff00) >> 8;
547		cmd.addr_0 = blkno & 0xff;
548		cmd.length2 = (nblks & 0xff00) >> 8;
549		cmd.length1 = (nblks & 0xff);
550
551		/*
552		 * Call the routine that chats with the adapter.
553		 * Note: we cannot sleep as we may be an interrupt
554		 */
555		if (scsi_scsi_cmd(sc_link, (struct scsi_generic *)&cmd,
556		    sizeof(cmd), (u_char *) bp->b_data, bp->b_bcount,
557		    CDRETRIES, 30000, bp, SCSI_NOSLEEP |
558		    ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT))
559		    != SUCCESSFULLY_QUEUED)
560			printf("%s: not queued", cd->sc_dev.dv_xname);
561	}
562}
563
564/*
565 * Perform special action on behalf of the user.
566 * Knows about the internals of this device
567 */
568int
569cdioctl(dev, cmd, addr, flag)
570	dev_t dev;
571	u_long cmd;
572	caddr_t addr;
573	int flag;
574{
575	struct cd_data *cd = cdcd.cd_devs[CDUNIT(dev)];
576	int error;
577
578	SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%x ", cmd));
579
580	/*
581	 * If the device is not valid.. abandon ship
582	 */
583	if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED))
584		return EIO;
585
586	switch (cmd) {
587	case DIOCSBAD:
588		return EINVAL;
589
590	case DIOCGDINFO:
591		*(struct disklabel *)addr = cd->sc_dk.dk_label;
592		return 0;
593
594	case DIOCGPART:
595		((struct partinfo *)addr)->disklab = &cd->sc_dk.dk_label;
596		((struct partinfo *)addr)->part =
597		    &cd->sc_dk.dk_label.d_partitions[CDPART(dev)];
598		return 0;
599
600	case DIOCWDINFO:
601	case DIOCSDINFO:
602		if ((flag & FWRITE) == 0)
603			return EBADF;
604		error = setdisklabel(&cd->sc_dk.dk_label,
605		    (struct disklabel *)addr,
606		    /*(cd->flags & CDF_BSDLABEL) ? cd->sc_dk.dk_openmask : */0,
607		    &cd->sc_dk.dk_cpulabel);
608		if (error == 0)
609			cd->flags |= CDF_BSDLABEL;
610		return error;
611
612	case DIOCWLABEL:
613		return EBADF;
614
615	case CDIOCPLAYTRACKS: {
616		struct ioc_play_track *args = (struct ioc_play_track *)addr;
617		struct cd_mode_data data;
618		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
619			return error;
620		data.page.audio.flags &= ~CD_PA_SOTC;
621		data.page.audio.flags |= CD_PA_IMMED;
622		if (error = cd_set_mode(cd, &data))
623			return error;
624		return cd_play_tracks(cd, args->start_track, args->start_index,
625		    args->end_track, args->end_index);
626	}
627	case CDIOCPLAYMSF: {
628		struct ioc_play_msf *args
629		= (struct ioc_play_msf *)addr;
630		struct cd_mode_data data;
631		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
632			return error;
633		data.page.audio.flags &= ~CD_PA_SOTC;
634		data.page.audio.flags |= CD_PA_IMMED;
635		if (error = cd_set_mode(cd, &data))
636			return error;
637		return cd_play_msf(cd, args->start_m, args->start_s,
638		    args->start_f, args->end_m, args->end_s, args->end_f);
639	}
640	case CDIOCPLAYBLOCKS: {
641		struct ioc_play_blocks *args
642		= (struct ioc_play_blocks *)addr;
643		struct cd_mode_data data;
644		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
645			return error;
646		data.page.audio.flags &= ~CD_PA_SOTC;
647		data.page.audio.flags |= CD_PA_IMMED;
648		if (error = cd_set_mode(cd, &data))
649			return error;
650		return cd_play(cd, args->blk, args->len);
651	}
652	case CDIOCREADSUBCHANNEL: {
653		struct ioc_read_subchannel *args
654		= (struct ioc_read_subchannel *)addr;
655		struct cd_sub_channel_info data;
656		u_int32 len = args->data_len;
657		if (len > sizeof(data) ||
658		    len < sizeof(struct cd_sub_channel_header))
659			return EINVAL;
660		if (error = cd_read_subchannel(cd, args->address_format,
661		    args->data_format, args->track, &data, len))
662			return error;
663		len = min(len, ((data.header.data_len[0] << 8) +
664		    data.header.data_len[1] +
665		    sizeof(struct cd_sub_channel_header)));
666		return copyout(&data, args->data, len);
667	}
668	case CDIOREADTOCHEADER: {
669		struct ioc_toc_header th;
670		if (error = cd_read_toc(cd, 0, 0, &th, sizeof(th)))
671			return error;
672		th.len = ntohs(th.len);
673		bcopy(&th, addr, sizeof(th));
674		return 0;
675	}
676	case CDIOREADTOCENTRYS: {
677		struct cd_toc {
678			struct ioc_toc_header header;
679			struct cd_toc_entry entries[65];
680		} data;
681		struct ioc_read_toc_entry *te =
682		(struct ioc_read_toc_entry *)addr;
683		struct ioc_toc_header *th;
684		u_int32 len = te->data_len;
685		th = &data.header;
686
687		if (len > sizeof(data.entries) ||
688		    len < sizeof(struct cd_toc_entry))
689			return EINVAL;
690		if (error = cd_read_toc(cd, te->address_format,
691		    te->starting_track, (struct cd_toc_entry *)&data,
692		    len + sizeof(struct ioc_toc_header)))
693			return error;
694		len = min(len, ntohs(th->len) - (sizeof(th->starting_track) +
695		    sizeof(th->ending_track)));
696		return copyout(data.entries, te->data, len);
697	}
698	case CDIOCSETPATCH: {
699		struct ioc_patch *arg = (struct ioc_patch *)addr;
700		struct cd_mode_data data;
701		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
702			return error;
703		data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
704		data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
705		data.page.audio.port[2].channels = arg->patch[2];
706		data.page.audio.port[3].channels = arg->patch[3];
707		return cd_set_mode(cd, &data);
708	}
709	case CDIOCGETVOL: {
710		struct ioc_vol *arg = (struct ioc_vol *)addr;
711		struct cd_mode_data data;
712		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
713			return error;
714		arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
715		arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
716		arg->vol[2] = data.page.audio.port[2].volume;
717		arg->vol[3] = data.page.audio.port[3].volume;
718		return 0;
719	}
720	case CDIOCSETVOL: {
721		struct ioc_vol *arg = (struct ioc_vol *)addr;
722		struct cd_mode_data data;
723		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
724			return error;
725		data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
726		data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
727		data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1;
728		data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
729		data.page.audio.port[2].volume = arg->vol[2];
730		data.page.audio.port[3].volume = arg->vol[3];
731		return cd_set_mode(cd, &data);
732	}
733	case CDIOCSETMONO: {
734		struct ioc_vol *arg = (struct ioc_vol *)addr;
735		struct cd_mode_data data;
736		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
737			return error;
738		data.page.audio.port[LEFT_PORT].channels =
739		    LEFT_CHANNEL | RIGHT_CHANNEL | 4 | 8;
740		data.page.audio.port[RIGHT_PORT].channels =
741		    LEFT_CHANNEL | RIGHT_CHANNEL;
742		data.page.audio.port[2].channels = 0;
743		data.page.audio.port[3].channels = 0;
744		return cd_set_mode(cd, &data);
745	}
746	case CDIOCSETSTEREO: {
747		struct ioc_vol *arg = (struct ioc_vol *)addr;
748		struct cd_mode_data data;
749		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
750			return error;
751		data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
752		data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
753		data.page.audio.port[2].channels = 0;
754		data.page.audio.port[3].channels = 0;
755		return cd_set_mode(cd, &data);
756	}
757	case CDIOCSETMUTE: {
758		struct ioc_vol *arg = (struct ioc_vol *)addr;
759		struct cd_mode_data data;
760		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
761			return error;
762		data.page.audio.port[LEFT_PORT].channels = 0;
763		data.page.audio.port[RIGHT_PORT].channels = 0;
764		data.page.audio.port[2].channels = 0;
765		data.page.audio.port[3].channels = 0;
766		return cd_set_mode(cd, &data);
767	}
768	case CDIOCSETLEFT: {
769		struct ioc_vol *arg = (struct ioc_vol *)addr;
770		struct cd_mode_data data;
771		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
772			return error;
773		data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
774		data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
775		data.page.audio.port[2].channels = 0;
776		data.page.audio.port[3].channels = 0;
777		return cd_set_mode(cd, &data);
778	}
779	case CDIOCSETRIGHT: {
780		struct ioc_vol *arg = (struct ioc_vol *)addr;
781		struct cd_mode_data data;
782		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
783			return error;
784		data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
785		data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
786		data.page.audio.port[2].channels = 0;
787		data.page.audio.port[3].channels = 0;
788		return cd_set_mode(cd, &data);
789	}
790	case CDIOCRESUME:
791		return cd_pause(cd, 1);
792	case CDIOCPAUSE:
793		return cd_pause(cd, 0);
794	case CDIOCSTART:
795		return scsi_start(cd->sc_link, SSS_START, 0);
796	case CDIOCSTOP:
797		return scsi_start(cd->sc_link, SSS_STOP, 0);
798	case CDIOCEJECT:
799		return scsi_start(cd->sc_link, SSS_LOEJ, 0);
800	case CDIOCALLOW:
801		return scsi_prevent(cd->sc_link, PR_ALLOW, 0);
802	case CDIOCPREVENT:
803		return scsi_prevent(cd->sc_link, PR_PREVENT, 0);
804	case CDIOCSETDEBUG:
805		cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
806		return 0;
807	case CDIOCCLRDEBUG:
808		cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
809		return 0;
810	case CDIOCRESET:
811		return cd_reset(cd);
812	default:
813		if (CDPART(dev) != RAW_PART)
814			return ENOTTY;
815		return scsi_do_ioctl(cd->sc_link, dev, cmd, addr, flag);
816	}
817
818#ifdef DIAGNOSTIC
819	panic("cdioctl: impossible");
820#endif
821}
822
823/*
824 * Load the label information on the named device
825 * Actually fabricate a disklabel
826 *
827 * EVENTUALLY take information about different
828 * data tracks from the TOC and put it in the disklabel
829 */
830void
831cdgetdisklabel(cd)
832	struct cd_data *cd;
833{
834
835	if ((cd->flags & CDF_BSDLABEL) != 0)
836		return;
837
838	bzero(&cd->sc_dk.dk_label, sizeof(struct disklabel));
839	bzero(&cd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
840
841	cd->sc_dk.dk_label.d_secsize = cd->params.blksize;
842	cd->sc_dk.dk_label.d_ntracks = 1;
843	cd->sc_dk.dk_label.d_nsectors = 100;
844	cd->sc_dk.dk_label.d_ncylinders = (cd->params.disksize / 100) + 1;
845	cd->sc_dk.dk_label.d_secpercyl =
846	    cd->sc_dk.dk_label.d_ntracks * cd->sc_dk.dk_label.d_nsectors;
847
848	strncpy(cd->sc_dk.dk_label.d_typename, "SCSI CD-ROM", 16);
849	cd->sc_dk.dk_label.d_type = DTYPE_SCSI;
850	strncpy(cd->sc_dk.dk_label.d_packname, "ficticious", 16);
851	cd->sc_dk.dk_label.d_secperunit = cd->params.disksize;
852	cd->sc_dk.dk_label.d_rpm = 300;
853	cd->sc_dk.dk_label.d_interleave = 1;
854	cd->sc_dk.dk_label.d_flags = D_REMOVABLE;
855
856	cd->sc_dk.dk_label.d_partitions[0].p_offset = 0;
857	cd->sc_dk.dk_label.d_partitions[0].p_size =
858	    cd->sc_dk.dk_label.d_secperunit *
859	    (cd->sc_dk.dk_label.d_secsize / DEV_BSIZE);
860	cd->sc_dk.dk_label.d_partitions[0].p_fstype = FS_ISO9660;
861	cd->sc_dk.dk_label.d_npartitions = 1;
862
863	cd->sc_dk.dk_label.d_magic = DISKMAGIC;
864	cd->sc_dk.dk_label.d_magic2 = DISKMAGIC;
865	cd->sc_dk.dk_label.d_checksum = dkcksum(&cd->sc_dk.dk_label);
866
867	cd->flags |= CDF_BSDLABEL;
868}
869
870/*
871 * Find out from the device what it's capacity is
872 */
873u_int32
874cd_size(cd, flags)
875	struct cd_data *cd;
876	int flags;
877{
878	struct scsi_read_cd_cap_data rdcap;
879	struct scsi_read_cd_capacity scsi_cmd;
880	u_int32 size, blksize;
881	int error;
882
883	/*
884	 * make up a scsi command and ask the scsi driver to do
885	 * it for you.
886	 */
887	bzero(&scsi_cmd, sizeof(scsi_cmd));
888	scsi_cmd.op_code = READ_CD_CAPACITY;
889
890	/*
891	 * If the command works, interpret the result as a 4 byte
892	 * number of blocks and a blocksize
893	 */
894	error = scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
895	    sizeof(scsi_cmd), (u_char *)&rdcap, sizeof(rdcap), CDRETRIES,
896	    20000, NULL, SCSI_DATA_IN | flags);
897	if (error == EBUSY) {
898		if (!(flags & SCSI_SILENT))
899			printf("%s: waiting for drive to spin up\n",
900			    cd->sc_dev.dv_xname);
901		if (flags & SCSI_NOSLEEP)
902			delay(2000000);
903		else
904			tsleep(cd, PRIBIO + 1, "cd_size", 2 * hz);
905		error = scsi_scsi_cmd(cd->sc_link,
906		    (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
907		    (u_char *)&rdcap, sizeof(rdcap), CDRETRIES, 20000, NULL,
908		    SCSI_DATA_IN | flags);
909	}
910
911	if (error) {
912		if (!(flags & SCSI_SILENT))
913			printf("%s: could not get size\n",
914			    cd->sc_dev.dv_xname);
915		return 0;
916	}
917
918	blksize = (rdcap.length_3 << 24) + (rdcap.length_2 << 16) +
919	    (rdcap.length_1 << 8) + rdcap.length_0;
920	if (blksize < 512)
921		blksize = 2048;	/* some drives lie ! */
922	cd->params.blksize = blksize;
923
924	size = (rdcap.addr_3 << 24) + (rdcap.addr_2 << 16) +
925	    (rdcap.addr_1 << 8) + rdcap.addr_0 + 1;
926	if (size < 100)
927		size = 400000;	/* ditto */
928	cd->params.disksize = size;
929
930	return size;
931}
932
933/*
934 * Get the requested page into the buffer given
935 */
936int
937cd_get_mode(cd, data, page)
938	struct cd_data *cd;
939	struct cd_mode_data *data;
940	int page;
941{
942	struct scsi_mode_sense scsi_cmd;
943	int error;
944
945	bzero(&scsi_cmd, sizeof(scsi_cmd));
946	bzero(data, sizeof(*data));
947	scsi_cmd.op_code = MODE_SENSE;
948	scsi_cmd.page = page;
949	scsi_cmd.length = sizeof(*data) & 0xff;
950	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
951	    sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000,
952	    NULL, SCSI_DATA_IN);
953}
954
955/*
956 * Get the requested page into the buffer given
957 */
958int
959cd_set_mode(cd, data)
960	struct cd_data *cd;
961	struct cd_mode_data *data;
962{
963	struct scsi_mode_select scsi_cmd;
964
965	bzero(&scsi_cmd, sizeof(scsi_cmd));
966	scsi_cmd.op_code = MODE_SELECT;
967	scsi_cmd.byte2 |= SMS_PF;
968	scsi_cmd.length = sizeof(*data) & 0xff;
969	data->header.data_length = 0;
970	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
971	    sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000,
972	    NULL, SCSI_DATA_OUT);
973}
974
975/*
976 * Get scsi driver to send a "start playing" command
977 */
978int
979cd_play(cd, blkno, nblks)
980	struct cd_data *cd;
981	int blkno, nblks;
982{
983	struct scsi_play scsi_cmd;
984
985	bzero(&scsi_cmd, sizeof(scsi_cmd));
986	scsi_cmd.op_code = PLAY;
987	scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
988	scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
989	scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
990	scsi_cmd.blk_addr[3] = blkno & 0xff;
991	scsi_cmd.xfer_len[0] = (nblks >> 8) & 0xff;
992	scsi_cmd.xfer_len[1] = nblks & 0xff;
993	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
994	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 200000, NULL, 0);
995}
996
997/*
998 * Get scsi driver to send a "start playing" command
999 */
1000int
1001cd_play_big(cd, blkno, nblks)
1002	struct cd_data *cd;
1003	int blkno, nblks;
1004{
1005	struct scsi_play_big scsi_cmd;
1006
1007	bzero(&scsi_cmd, sizeof(scsi_cmd));
1008	scsi_cmd.op_code = PLAY_BIG;
1009	scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
1010	scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
1011	scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
1012	scsi_cmd.blk_addr[3] = blkno & 0xff;
1013	scsi_cmd.xfer_len[0] = (nblks >> 24) & 0xff;
1014	scsi_cmd.xfer_len[1] = (nblks >> 16) & 0xff;
1015	scsi_cmd.xfer_len[2] = (nblks >> 8) & 0xff;
1016	scsi_cmd.xfer_len[3] = nblks & 0xff;
1017	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1018	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
1019}
1020
1021/*
1022 * Get scsi driver to send a "start playing" command
1023 */
1024int
1025cd_play_tracks(cd, strack, sindex, etrack, eindex)
1026	struct cd_data *cd;
1027	int strack, sindex, etrack, eindex;
1028{
1029	struct scsi_play_track scsi_cmd;
1030
1031	bzero(&scsi_cmd, sizeof(scsi_cmd));
1032	scsi_cmd.op_code = PLAY_TRACK;
1033	scsi_cmd.start_track = strack;
1034	scsi_cmd.start_index = sindex;
1035	scsi_cmd.end_track = etrack;
1036	scsi_cmd.end_index = eindex;
1037	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1038	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
1039}
1040
1041/*
1042 * Get scsi driver to send a "play msf" command
1043 */
1044int
1045cd_play_msf(cd, startm, starts, startf, endm, ends, endf)
1046	struct cd_data *cd;
1047	int startm, starts, startf, endm, ends, endf;
1048{
1049	struct scsi_play_msf scsi_cmd;
1050
1051	bzero(&scsi_cmd, sizeof(scsi_cmd));
1052	scsi_cmd.op_code = PLAY_MSF;
1053	scsi_cmd.start_m = startm;
1054	scsi_cmd.start_s = starts;
1055	scsi_cmd.start_f = startf;
1056	scsi_cmd.end_m = endm;
1057	scsi_cmd.end_s = ends;
1058	scsi_cmd.end_f = endf;
1059	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1060	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
1061}
1062
1063/*
1064 * Get scsi driver to send a "start up" command
1065 */
1066int
1067cd_pause(cd, go)
1068	struct cd_data *cd;
1069	int go;
1070{
1071	struct scsi_pause scsi_cmd;
1072
1073	bzero(&scsi_cmd, sizeof(scsi_cmd));
1074	scsi_cmd.op_code = PAUSE;
1075	scsi_cmd.resume = go;
1076	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1077	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
1078}
1079
1080/*
1081 * Get scsi driver to send a "RESET" command
1082 */
1083int
1084cd_reset(cd)
1085	struct cd_data *cd;
1086{
1087
1088	return scsi_scsi_cmd(cd->sc_link, 0, 0, 0, 0, CDRETRIES, 2000, NULL,
1089	    SCSI_RESET);
1090}
1091
1092/*
1093 * Read subchannel
1094 */
1095int
1096cd_read_subchannel(cd, mode, format, track, data, len)
1097	struct cd_data *cd;
1098	int mode, format, len;
1099	struct cd_sub_channel_info *data;
1100{
1101	struct scsi_read_subchannel scsi_cmd;
1102
1103	bzero(&scsi_cmd, sizeof(scsi_cmd));
1104	scsi_cmd.op_code = READ_SUBCHANNEL;
1105	if (mode == CD_MSF_FORMAT)
1106		scsi_cmd.byte2 |= CD_MSF;
1107	scsi_cmd.byte3 = SRS_SUBQ;
1108	scsi_cmd.subchan_format = format;
1109	scsi_cmd.track = track;
1110	scsi_cmd.data_len[0] = (len) >> 8;
1111	scsi_cmd.data_len[1] = (len) & 0xff;
1112	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1113	    sizeof(struct scsi_read_subchannel), (u_char *)data, len,
1114	    CDRETRIES, 5000, NULL, SCSI_DATA_IN);
1115}
1116
1117/*
1118 * Read table of contents
1119 */
1120int
1121cd_read_toc(cd, mode, start, data, len)
1122	struct cd_data *cd;
1123	int mode, start, len;
1124	struct cd_toc_entry *data;
1125{
1126	struct scsi_read_toc scsi_cmd;
1127	int ntoc;
1128
1129	bzero(&scsi_cmd, sizeof(scsi_cmd));
1130	/*if (len!=sizeof(struct ioc_toc_header))
1131	 * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
1132	 * else */
1133	ntoc = len;
1134	scsi_cmd.op_code = READ_TOC;
1135	if (mode == CD_MSF_FORMAT)
1136		scsi_cmd.byte2 |= CD_MSF;
1137	scsi_cmd.from_track = start;
1138	scsi_cmd.data_len[0] = (ntoc) >> 8;
1139	scsi_cmd.data_len[1] = (ntoc) & 0xff;
1140	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1141	    sizeof(struct scsi_read_toc), (u_char *)data, len, CDRETRIES,
1142	    5000, NULL, SCSI_DATA_IN);
1143}
1144
1145#define b2tol(a)	(((unsigned)(a##_1) << 8) + (unsigned)a##_0)
1146
1147/*
1148 * Get the scsi driver to send a full inquiry to the device and use the
1149 * results to fill out the disk parameter structure.
1150 */
1151int
1152cd_get_parms(cd, flags)
1153	struct cd_data *cd;
1154	int flags;
1155{
1156
1157	/*
1158	 * give a number of sectors so that sec * trks * cyls
1159	 * is <= disk_size
1160	 */
1161	if (cd_size(cd, flags) == 0)
1162		return ENXIO;
1163
1164	return 0;
1165}
1166
1167int
1168cdsize(dev)
1169	dev_t dev;
1170{
1171
1172	return -1;
1173}
1174
1175int
1176cddump()
1177{
1178
1179	/* Not implemented. */
1180	return EINVAL;
1181}
1182