cd.c revision 1.46
1/*	$NetBSD: cd.c,v 1.46 1994/12/16 04:38:30 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/conf.h>
54#include <sys/file.h>
55#include <sys/stat.h>
56#include <sys/ioctl.h>
57#include <sys/buf.h>
58#include <sys/uio.h>
59#include <sys/malloc.h>
60#include <sys/errno.h>
61#include <sys/device.h>
62#include <sys/disklabel.h>
63#include <sys/disk.h>
64#include <sys/cdio.h>
65
66#include <scsi/scsi_all.h>
67#include <scsi/scsi_cd.h>
68#include <scsi/scsi_disk.h>	/* rw_big and start_stop come from there */
69#include <scsi/scsiconf.h>
70
71#ifdef	DDB
72int	Debugger();
73#else	/* DDB */
74#define Debugger()
75#endif	/* DDB */
76
77#define	CDOUTSTANDING	2
78#define	CDRETRIES	1
79
80#define	CDUNIT(z)			DISKUNIT(z)
81#define	CDPART(z)			DISKPART(z)
82#define	MAKECDDEV(maj, unit, part)	MAKEDISKDEV(maj, unit, part)
83
84struct cd_data {
85	struct device sc_dev;
86	struct dkdevice sc_dk;
87
88	int flags;
89#define	CDF_LOCKED	0x01
90#define	CDF_WANTED	0x02
91#define	CDF_BSDLABEL	0x04
92	struct scsi_link *sc_link;	/* address of scsi low level switch */
93	u_int32 ad_info;	/* info about the adapter */
94	u_int32 cmdscount;	/* cmds allowed outstanding by board */
95	struct cd_parms {
96		u_int32 blksize;
97		u_long disksize;	/* total number sectors */
98	} params;
99	u_int32 xfer_block_wait;
100	struct buf buf_queue;
101};
102
103void cdattach __P((struct device *, struct device *, void *));
104
105struct cfdriver cdcd = {
106	NULL, "cd", scsi_targmatch, cdattach, DV_DISK, sizeof(struct cd_data)
107};
108
109void cdgetdisklabel __P((struct cd_data *));
110int cd_get_parms __P((struct cd_data *, int));
111void cdstrategy __P((struct buf *));
112void cdstart __P((struct cd_data *));
113
114struct dkdriver cddkdriver = { cdstrategy };
115
116struct scsi_device cd_switch = {
117	NULL,			/* use default error handler */
118	cdstart,		/* we have a queue, which is started by this */
119	NULL,			/* we do not have an async handler */
120	NULL,			/* use default 'done' routine */
121	"cd",			/* we are to be refered to by this name */
122	0			/* no device specific flags */
123};
124
125#define CD_STOP		0
126#define CD_START	1
127#define CD_EJECT	-2
128
129/*
130 * The routine called by the low level scsi routine when it discovers
131 * A device suitable for this driver
132 */
133void
134cdattach(parent, self, aux)
135	struct device *parent, *self;
136	void *aux;
137{
138	struct cd_data *cd = (void *)self;
139	struct cd_parms *dp = &cd->params;
140	struct scsi_link *sc_link = aux;
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	sc_link->device = &cd_switch;
149	sc_link->device_softc = cd;
150
151	cd->sc_dk.dk_driver = &cddkdriver;
152#if !defined(i386) || defined(NEWCONFIG)
153	dk_establish(&cd->sc_dk, &cd->sc_dev);
154#endif
155
156	if (cd->sc_link->adapter->adapter_info) {
157		cd->ad_info = ((*(cd->sc_link->adapter->adapter_info)) (sc_link->adapter_softc));
158		cd->cmdscount = cd->ad_info & AD_INF_MAX_CMDS;
159		if (cd->cmdscount > CDOUTSTANDING)
160			cd->cmdscount = CDOUTSTANDING;
161	} else {
162		cd->ad_info = 1;
163		cd->cmdscount = 1;
164	}
165	sc_link->opennings = cd->cmdscount;
166
167	/*
168	 * Use the subdriver to request information regarding
169	 * the drive. We cannot use interrupts yet, so the
170	 * request must specify this.
171	 */
172	cd_get_parms(cd, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
173	if (dp->disksize)
174		printf(": cd present, %d x %d byte records\n",
175		    cd->params.disksize, cd->params.blksize);
176	else
177		printf(": drive empty\n");
178}
179
180/*
181 * open the device. Make sure the partition info is a up-to-date as can be.
182 */
183int
184cdopen(dev, flag, fmt)
185	dev_t dev;
186	int flag, fmt;
187{
188	int error;
189	int unit, part;
190	struct cd_data *cd;
191	struct scsi_link *sc_link;
192
193	unit = CDUNIT(dev);
194	if (unit >= cdcd.cd_ndevs)
195		return ENXIO;
196	cd = cdcd.cd_devs[unit];
197	if (!cd)
198		return ENXIO;
199
200	part = CDPART(dev);
201	sc_link = cd->sc_link;
202
203	SC_DEBUG(sc_link, SDEV_DB1,
204	    ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
205	    cdcd.cd_ndevs, part));
206
207	while ((cd->flags & CDF_LOCKED) != 0) {
208		cd->flags |= CDF_WANTED;
209		if ((error = tsleep(cd, PRIBIO | PCATCH, "cdopn", 0)) != 0)
210			return error;
211	}
212
213	if (cd->sc_dk.dk_openmask != 0) {
214		/*
215		 * If any partition is open, but the disk has been invalidated,
216		 * disallow further opens.
217		 */
218		if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0)
219			return ENXIO;
220	} else {
221		cd->flags |= CDF_LOCKED;
222
223		/*
224		 * Check that it is still responding and ok.
225		 * if the media has been changed this will result in a
226		 * "unit attention" error which the error code will
227		 * disregard because the SDEV_OPEN flag is not yet set.
228		 */
229		scsi_test_unit_ready(sc_link, SCSI_SILENT);
230
231		/*
232		 * In case it is a funny one, tell it to start
233		 * not needed for some drives
234		 */
235		scsi_start(sc_link, SSS_START, SCSI_ERR_OK | SCSI_SILENT);
236
237		sc_link->flags |= SDEV_OPEN;	/* unit attn errors are now errors */
238
239		/*
240		 * Check that it is still responding and ok.
241		 */
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		cd->flags &= ~CDF_LOCKED;
306		if ((cd->flags & CDF_WANTED) != 0) {
307			cd->flags &= ~CDF_WANTED;
308			wakeup(cd);
309		}
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 DIOCGDINFO:
588		*(struct disklabel *)addr = cd->sc_dk.dk_label;
589		return 0;
590
591	case DIOCGPART:
592		((struct partinfo *)addr)->disklab = &cd->sc_dk.dk_label;
593		((struct partinfo *)addr)->part =
594		    &cd->sc_dk.dk_label.d_partitions[CDPART(dev)];
595		return 0;
596
597	case DIOCWDINFO:
598	case DIOCSDINFO:
599		if ((flag & FWRITE) == 0)
600			return EBADF;
601		error = setdisklabel(&cd->sc_dk.dk_label,
602		    (struct disklabel *)addr,
603		    /*(cd->flags & CDF_BSDLABEL) ? cd->sc_dk.dk_openmask : */0,
604		    &cd->sc_dk.dk_cpulabel);
605		if (error == 0)
606			cd->flags |= CDF_BSDLABEL;
607		return error;
608
609	case DIOCWLABEL:
610		return EBADF;
611
612	case CDIOCPLAYTRACKS: {
613		struct ioc_play_track *args = (struct ioc_play_track *)addr;
614		struct cd_mode_data data;
615		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
616			return error;
617		data.page.audio.flags &= ~CD_PA_SOTC;
618		data.page.audio.flags |= CD_PA_IMMED;
619		if (error = cd_set_mode(cd, &data))
620			return error;
621		return cd_play_tracks(cd, args->start_track, args->start_index,
622		    args->end_track, args->end_index);
623	}
624	case CDIOCPLAYMSF: {
625		struct ioc_play_msf *args
626		= (struct ioc_play_msf *)addr;
627		struct cd_mode_data data;
628		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
629			return error;
630		data.page.audio.flags &= ~CD_PA_SOTC;
631		data.page.audio.flags |= CD_PA_IMMED;
632		if (error = cd_set_mode(cd, &data))
633			return error;
634		return cd_play_msf(cd, args->start_m, args->start_s,
635		    args->start_f, args->end_m, args->end_s, args->end_f);
636	}
637	case CDIOCPLAYBLOCKS: {
638		struct ioc_play_blocks *args
639		= (struct ioc_play_blocks *)addr;
640		struct cd_mode_data data;
641		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
642			return error;
643		data.page.audio.flags &= ~CD_PA_SOTC;
644		data.page.audio.flags |= CD_PA_IMMED;
645		if (error = cd_set_mode(cd, &data))
646			return error;
647		return cd_play(cd, args->blk, args->len);
648	}
649	case CDIOCREADSUBCHANNEL: {
650		struct ioc_read_subchannel *args
651		= (struct ioc_read_subchannel *)addr;
652		struct cd_sub_channel_info data;
653		u_int32 len = args->data_len;
654		if (len > sizeof(data) ||
655		    len < sizeof(struct cd_sub_channel_header))
656			return EINVAL;
657		if (error = cd_read_subchannel(cd, args->address_format,
658		    args->data_format, args->track, &data, len))
659			return error;
660		len = min(len, ((data.header.data_len[0] << 8) +
661		    data.header.data_len[1] +
662		    sizeof(struct cd_sub_channel_header)));
663		return copyout(&data, args->data, len);
664	}
665	case CDIOREADTOCHEADER: {
666		struct ioc_toc_header th;
667		if (error = cd_read_toc(cd, 0, 0, &th, sizeof(th)))
668			return error;
669		th.len = ntohs(th.len);
670		bcopy(&th, addr, sizeof(th));
671		return 0;
672	}
673	case CDIOREADTOCENTRYS: {
674		struct cd_toc {
675			struct ioc_toc_header header;
676			struct cd_toc_entry entries[65];
677		} data;
678		struct ioc_read_toc_entry *te =
679		(struct ioc_read_toc_entry *)addr;
680		struct ioc_toc_header *th;
681		u_int32 len = te->data_len;
682		th = &data.header;
683
684		if (len > sizeof(data.entries) ||
685		    len < sizeof(struct cd_toc_entry))
686			return EINVAL;
687		if (error = cd_read_toc(cd, te->address_format,
688		    te->starting_track, (struct cd_toc_entry *)&data,
689		    len + sizeof(struct ioc_toc_header)))
690			return error;
691		len = min(len, ntohs(th->len) - (sizeof(th->starting_track) +
692		    sizeof(th->ending_track)));
693		return copyout(data.entries, te->data, len);
694	}
695	case CDIOCSETPATCH: {
696		struct ioc_patch *arg = (struct ioc_patch *)addr;
697		struct cd_mode_data data;
698		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
699			return error;
700		data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
701		data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
702		data.page.audio.port[2].channels = arg->patch[2];
703		data.page.audio.port[3].channels = arg->patch[3];
704		return cd_set_mode(cd, &data);
705	}
706	case CDIOCGETVOL: {
707		struct ioc_vol *arg = (struct ioc_vol *)addr;
708		struct cd_mode_data data;
709		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
710			return error;
711		arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
712		arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
713		arg->vol[2] = data.page.audio.port[2].volume;
714		arg->vol[3] = data.page.audio.port[3].volume;
715		return 0;
716	}
717	case CDIOCSETVOL: {
718		struct ioc_vol *arg = (struct ioc_vol *)addr;
719		struct cd_mode_data data;
720		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
721			return error;
722		data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
723		data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
724		data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1;
725		data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
726		data.page.audio.port[2].volume = arg->vol[2];
727		data.page.audio.port[3].volume = arg->vol[3];
728		return cd_set_mode(cd, &data);
729	}
730	case CDIOCSETMONO: {
731		struct ioc_vol *arg = (struct ioc_vol *)addr;
732		struct cd_mode_data data;
733		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
734			return error;
735		data.page.audio.port[LEFT_PORT].channels =
736		    LEFT_CHANNEL | RIGHT_CHANNEL | 4 | 8;
737		data.page.audio.port[RIGHT_PORT].channels =
738		    LEFT_CHANNEL | RIGHT_CHANNEL;
739		data.page.audio.port[2].channels = 0;
740		data.page.audio.port[3].channels = 0;
741		return cd_set_mode(cd, &data);
742	}
743	case CDIOCSETSTEREO: {
744		struct ioc_vol *arg = (struct ioc_vol *)addr;
745		struct cd_mode_data data;
746		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
747			return error;
748		data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
749		data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
750		data.page.audio.port[2].channels = 0;
751		data.page.audio.port[3].channels = 0;
752		return cd_set_mode(cd, &data);
753	}
754	case CDIOCSETMUTE: {
755		struct ioc_vol *arg = (struct ioc_vol *)addr;
756		struct cd_mode_data data;
757		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
758			return error;
759		data.page.audio.port[LEFT_PORT].channels = 0;
760		data.page.audio.port[RIGHT_PORT].channels = 0;
761		data.page.audio.port[2].channels = 0;
762		data.page.audio.port[3].channels = 0;
763		return cd_set_mode(cd, &data);
764	}
765	case CDIOCSETLEFT: {
766		struct ioc_vol *arg = (struct ioc_vol *)addr;
767		struct cd_mode_data data;
768		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
769			return error;
770		data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
771		data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
772		data.page.audio.port[2].channels = 0;
773		data.page.audio.port[3].channels = 0;
774		return cd_set_mode(cd, &data);
775	}
776	case CDIOCSETRIGHT: {
777		struct ioc_vol *arg = (struct ioc_vol *)addr;
778		struct cd_mode_data data;
779		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
780			return error;
781		data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
782		data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
783		data.page.audio.port[2].channels = 0;
784		data.page.audio.port[3].channels = 0;
785		return cd_set_mode(cd, &data);
786	}
787	case CDIOCRESUME:
788		return cd_pause(cd, 1);
789	case CDIOCPAUSE:
790		return cd_pause(cd, 0);
791	case CDIOCSTART:
792		return scsi_start(cd->sc_link, SSS_START, 0);
793	case CDIOCSTOP:
794		return scsi_start(cd->sc_link, SSS_STOP, 0);
795	case CDIOCEJECT:
796		return scsi_start(cd->sc_link, SSS_LOEJ, 0);
797	case CDIOCALLOW:
798		return scsi_prevent(cd->sc_link, PR_ALLOW, 0);
799	case CDIOCPREVENT:
800		return scsi_prevent(cd->sc_link, PR_PREVENT, 0);
801	case CDIOCSETDEBUG:
802		cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
803		return 0;
804	case CDIOCCLRDEBUG:
805		cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
806		return 0;
807	case CDIOCRESET:
808		return cd_reset(cd);
809	default:
810		if (CDPART(dev) != RAW_PART)
811			return ENOTTY;
812		return scsi_do_ioctl(cd->sc_link, dev, cmd, addr, flag);
813	}
814
815#ifdef DIAGNOSTIC
816	panic("cdioctl: impossible");
817#endif
818}
819
820/*
821 * Load the label information on the named device
822 * Actually fabricate a disklabel
823 *
824 * EVENTUALLY take information about different
825 * data tracks from the TOC and put it in the disklabel
826 */
827void
828cdgetdisklabel(cd)
829	struct cd_data *cd;
830{
831
832	if ((cd->flags & CDF_BSDLABEL) != 0)
833		return;
834
835	bzero(&cd->sc_dk.dk_label, sizeof(struct disklabel));
836	bzero(&cd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
837
838	cd->sc_dk.dk_label.d_secsize = cd->params.blksize;
839	cd->sc_dk.dk_label.d_ntracks = 1;
840	cd->sc_dk.dk_label.d_nsectors = 100;
841	cd->sc_dk.dk_label.d_ncylinders = (cd->params.disksize / 100) + 1;
842	cd->sc_dk.dk_label.d_secpercyl =
843	    cd->sc_dk.dk_label.d_ntracks * cd->sc_dk.dk_label.d_nsectors;
844
845	strncpy(cd->sc_dk.dk_label.d_typename, "SCSI CD-ROM", 16);
846	cd->sc_dk.dk_label.d_type = DTYPE_SCSI;
847	strncpy(cd->sc_dk.dk_label.d_packname, "ficticious", 16);
848	cd->sc_dk.dk_label.d_secperunit = cd->params.disksize;
849	cd->sc_dk.dk_label.d_rpm = 300;
850	cd->sc_dk.dk_label.d_interleave = 1;
851	cd->sc_dk.dk_label.d_flags = D_REMOVABLE;
852
853	cd->sc_dk.dk_label.d_partitions[0].p_offset = 0;
854	cd->sc_dk.dk_label.d_partitions[0].p_size =
855	    cd->sc_dk.dk_label.d_secperunit *
856	    (cd->sc_dk.dk_label.d_secsize / DEV_BSIZE);
857	cd->sc_dk.dk_label.d_partitions[0].p_fstype = FS_ISO9660;
858	cd->sc_dk.dk_label.d_npartitions = 1;
859
860	cd->sc_dk.dk_label.d_magic = DISKMAGIC;
861	cd->sc_dk.dk_label.d_magic2 = DISKMAGIC;
862	cd->sc_dk.dk_label.d_checksum = dkcksum(&cd->sc_dk.dk_label);
863
864	cd->flags |= CDF_BSDLABEL;
865}
866
867/*
868 * Find out from the device what it's capacity is
869 */
870u_int32
871cd_size(cd, flags)
872	struct cd_data *cd;
873	int flags;
874{
875	struct scsi_read_cd_cap_data rdcap;
876	struct scsi_read_cd_capacity scsi_cmd;
877	u_int32 size, blksize;
878	int error;
879
880	/*
881	 * make up a scsi command and ask the scsi driver to do
882	 * it for you.
883	 */
884	bzero(&scsi_cmd, sizeof(scsi_cmd));
885	scsi_cmd.op_code = READ_CD_CAPACITY;
886
887	/*
888	 * If the command works, interpret the result as a 4 byte
889	 * number of blocks and a blocksize
890	 */
891	error = scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
892	    sizeof(scsi_cmd), (u_char *)&rdcap, sizeof(rdcap), CDRETRIES,
893	    20000, NULL, SCSI_DATA_IN | flags);
894	if (error == EBUSY) {
895		if (!(flags & SCSI_SILENT))
896			printf("%s: waiting for drive to spin up\n",
897			    cd->sc_dev.dv_xname);
898		if (flags & SCSI_NOSLEEP)
899			delay(2000000);
900		else
901			tsleep(cd, PRIBIO + 1, "cd_size", 2 * hz);
902		error = scsi_scsi_cmd(cd->sc_link,
903		    (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
904		    (u_char *)&rdcap, sizeof(rdcap), CDRETRIES, 20000, NULL,
905		    SCSI_DATA_IN | flags);
906	}
907
908	if (error) {
909		if (!(flags & SCSI_SILENT))
910			printf("%s: could not get size\n",
911			    cd->sc_dev.dv_xname);
912		return 0;
913	}
914
915	blksize = (rdcap.length_3 << 24) + (rdcap.length_2 << 16) +
916	    (rdcap.length_1 << 8) + rdcap.length_0;
917	if (blksize < 512)
918		blksize = 2048;	/* some drives lie ! */
919	cd->params.blksize = blksize;
920
921	size = (rdcap.addr_3 << 24) + (rdcap.addr_2 << 16) +
922	    (rdcap.addr_1 << 8) + rdcap.addr_0 + 1;
923	if (size < 100)
924		size = 400000;	/* ditto */
925	cd->params.disksize = size;
926
927	return size;
928}
929
930/*
931 * Get the requested page into the buffer given
932 */
933int
934cd_get_mode(cd, data, page)
935	struct cd_data *cd;
936	struct cd_mode_data *data;
937	int page;
938{
939	struct scsi_mode_sense scsi_cmd;
940	int error;
941
942	bzero(&scsi_cmd, sizeof(scsi_cmd));
943	bzero(data, sizeof(*data));
944	scsi_cmd.op_code = MODE_SENSE;
945	scsi_cmd.page = page;
946	scsi_cmd.length = sizeof(*data) & 0xff;
947	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
948	    sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000,
949	    NULL, SCSI_DATA_IN);
950}
951
952/*
953 * Get the requested page into the buffer given
954 */
955int
956cd_set_mode(cd, data)
957	struct cd_data *cd;
958	struct cd_mode_data *data;
959{
960	struct scsi_mode_select scsi_cmd;
961
962	bzero(&scsi_cmd, sizeof(scsi_cmd));
963	scsi_cmd.op_code = MODE_SELECT;
964	scsi_cmd.byte2 |= SMS_PF;
965	scsi_cmd.length = sizeof(*data) & 0xff;
966	data->header.data_length = 0;
967	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
968	    sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000,
969	    NULL, SCSI_DATA_OUT);
970}
971
972/*
973 * Get scsi driver to send a "start playing" command
974 */
975int
976cd_play(cd, blkno, nblks)
977	struct cd_data *cd;
978	int blkno, nblks;
979{
980	struct scsi_play scsi_cmd;
981
982	bzero(&scsi_cmd, sizeof(scsi_cmd));
983	scsi_cmd.op_code = PLAY;
984	scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
985	scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
986	scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
987	scsi_cmd.blk_addr[3] = blkno & 0xff;
988	scsi_cmd.xfer_len[0] = (nblks >> 8) & 0xff;
989	scsi_cmd.xfer_len[1] = nblks & 0xff;
990	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
991	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 200000, NULL, 0);
992}
993
994/*
995 * Get scsi driver to send a "start playing" command
996 */
997int
998cd_play_big(cd, blkno, nblks)
999	struct cd_data *cd;
1000	int blkno, nblks;
1001{
1002	struct scsi_play_big scsi_cmd;
1003
1004	bzero(&scsi_cmd, sizeof(scsi_cmd));
1005	scsi_cmd.op_code = PLAY_BIG;
1006	scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
1007	scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
1008	scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
1009	scsi_cmd.blk_addr[3] = blkno & 0xff;
1010	scsi_cmd.xfer_len[0] = (nblks >> 24) & 0xff;
1011	scsi_cmd.xfer_len[1] = (nblks >> 16) & 0xff;
1012	scsi_cmd.xfer_len[2] = (nblks >> 8) & 0xff;
1013	scsi_cmd.xfer_len[3] = nblks & 0xff;
1014	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1015	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
1016}
1017
1018/*
1019 * Get scsi driver to send a "start playing" command
1020 */
1021int
1022cd_play_tracks(cd, strack, sindex, etrack, eindex)
1023	struct cd_data *cd;
1024	int strack, sindex, etrack, eindex;
1025{
1026	struct scsi_play_track scsi_cmd;
1027
1028	bzero(&scsi_cmd, sizeof(scsi_cmd));
1029	scsi_cmd.op_code = PLAY_TRACK;
1030	scsi_cmd.start_track = strack;
1031	scsi_cmd.start_index = sindex;
1032	scsi_cmd.end_track = etrack;
1033	scsi_cmd.end_index = eindex;
1034	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1035	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
1036}
1037
1038/*
1039 * Get scsi driver to send a "play msf" command
1040 */
1041int
1042cd_play_msf(cd, startm, starts, startf, endm, ends, endf)
1043	struct cd_data *cd;
1044	int startm, starts, startf, endm, ends, endf;
1045{
1046	struct scsi_play_msf scsi_cmd;
1047
1048	bzero(&scsi_cmd, sizeof(scsi_cmd));
1049	scsi_cmd.op_code = PLAY_MSF;
1050	scsi_cmd.start_m = startm;
1051	scsi_cmd.start_s = starts;
1052	scsi_cmd.start_f = startf;
1053	scsi_cmd.end_m = endm;
1054	scsi_cmd.end_s = ends;
1055	scsi_cmd.end_f = endf;
1056	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1057	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
1058}
1059
1060/*
1061 * Get scsi driver to send a "start up" command
1062 */
1063int
1064cd_pause(cd, go)
1065	struct cd_data *cd;
1066	int go;
1067{
1068	struct scsi_pause scsi_cmd;
1069
1070	bzero(&scsi_cmd, sizeof(scsi_cmd));
1071	scsi_cmd.op_code = PAUSE;
1072	scsi_cmd.resume = go;
1073	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1074	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
1075}
1076
1077/*
1078 * Get scsi driver to send a "RESET" command
1079 */
1080int
1081cd_reset(cd)
1082	struct cd_data *cd;
1083{
1084
1085	return scsi_scsi_cmd(cd->sc_link, 0, 0, 0, 0, CDRETRIES, 2000, NULL,
1086	    SCSI_RESET);
1087}
1088
1089/*
1090 * Read subchannel
1091 */
1092int
1093cd_read_subchannel(cd, mode, format, track, data, len)
1094	struct cd_data *cd;
1095	int mode, format, len;
1096	struct cd_sub_channel_info *data;
1097{
1098	struct scsi_read_subchannel scsi_cmd;
1099
1100	bzero(&scsi_cmd, sizeof(scsi_cmd));
1101	scsi_cmd.op_code = READ_SUBCHANNEL;
1102	if (mode == CD_MSF_FORMAT)
1103		scsi_cmd.byte2 |= CD_MSF;
1104	scsi_cmd.byte3 = SRS_SUBQ;
1105	scsi_cmd.subchan_format = format;
1106	scsi_cmd.track = track;
1107	scsi_cmd.data_len[0] = (len) >> 8;
1108	scsi_cmd.data_len[1] = (len) & 0xff;
1109	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1110	    sizeof(struct scsi_read_subchannel), (u_char *)data, len,
1111	    CDRETRIES, 5000, NULL, SCSI_DATA_IN);
1112}
1113
1114/*
1115 * Read table of contents
1116 */
1117int
1118cd_read_toc(cd, mode, start, data, len)
1119	struct cd_data *cd;
1120	int mode, start, len;
1121	struct cd_toc_entry *data;
1122{
1123	struct scsi_read_toc scsi_cmd;
1124	int ntoc;
1125
1126	bzero(&scsi_cmd, sizeof(scsi_cmd));
1127	/*if (len!=sizeof(struct ioc_toc_header))
1128	 * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
1129	 * else */
1130	ntoc = len;
1131	scsi_cmd.op_code = READ_TOC;
1132	if (mode == CD_MSF_FORMAT)
1133		scsi_cmd.byte2 |= CD_MSF;
1134	scsi_cmd.from_track = start;
1135	scsi_cmd.data_len[0] = (ntoc) >> 8;
1136	scsi_cmd.data_len[1] = (ntoc) & 0xff;
1137	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1138	    sizeof(struct scsi_read_toc), (u_char *)data, len, CDRETRIES,
1139	    5000, NULL, SCSI_DATA_IN);
1140}
1141
1142#define b2tol(a)	(((unsigned)(a##_1) << 8) + (unsigned)a##_0)
1143
1144/*
1145 * Get the scsi driver to send a full inquiry to the device and use the
1146 * results to fill out the disk parameter structure.
1147 */
1148int
1149cd_get_parms(cd, flags)
1150	struct cd_data *cd;
1151	int flags;
1152{
1153
1154	/*
1155	 * give a number of sectors so that sec * trks * cyls
1156	 * is <= disk_size
1157	 */
1158	if (cd_size(cd, flags) == 0)
1159		return ENXIO;
1160
1161	return 0;
1162}
1163
1164int
1165cdsize(dev)
1166	dev_t dev;
1167{
1168
1169	return -1;
1170}
1171
1172int
1173cddump()
1174{
1175
1176	/* Not implemented. */
1177	return EINVAL;
1178}
1179