cd.c revision 1.23
1/*
2 * Copyright (c) 1994 Charles Hannum.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 *    must display the following acknowledgement:
14 *	This product includes software developed by Charles Hannum.
15 * 4. The name of the author may not be used to endorse or promote products
16 *    derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 *      $Id: cd.c,v 1.23 1994/03/29 04:29:22 mycroft Exp $
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/dkbad.h>
52#include <sys/systm.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	MAKECDDEV(maj, unit, part)	(makedev(maj,(unit<<3)|part))
81#define CDPART(z)	(minor(z) & 0x07)
82#define CDUNIT(z)	(minor(z) >> 3)
83#define	RAW_PART	3
84
85struct cd_data {
86	struct device sc_dev;
87	struct dkdevice sc_dk;
88
89	u_int32 flags;
90#define	CDINIT		0x04	/* device has been init'd */
91	struct scsi_link *sc_link;	/* address of scsi low level switch */
92	u_int32 cmdscount;	/* cmds allowed outstanding by board */
93	struct cd_parms {
94		u_int32 blksize;
95		u_long disksize;	/* total number sectors */
96	} params;
97	u_int32 partflags[MAXPARTITIONS];	/* per partition flags */
98#define CDOPEN	0x01
99	u_int32 openparts;	/* one bit for each open partition */
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
110int cdgetdisklabel __P((struct cd_data *));
111int cd_get_parms __P((struct cd_data *, int));
112void cdstrategy __P((struct buf *));
113void cdstart __P((int));
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->dev_unit = cd->sc_dev.dv_unit;
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	sc_link->opennings = cd->cmdscount = CDOUTSTANDING;
158
159	/*
160	 * Use the subdriver to request information regarding
161	 * the drive. We cannot use interrupts yet, so the
162	 * request must specify this.
163	 */
164	cd_get_parms(cd, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
165	if (dp->disksize)
166		printf(": cd present, %d x %d byte records\n",
167		    cd->params.disksize, cd->params.blksize);
168	else
169		printf(": drive empty\n");
170	cd->flags |= CDINIT;
171}
172
173/*
174 * open the device. Make sure the partition info is a up-to-date as can be.
175 */
176int
177cdopen(dev)
178	dev_t dev;
179{
180	int error = 0;
181	int unit, part;
182	struct cd_data *cd;
183	struct scsi_link *sc_link;
184
185	unit = CDUNIT(dev);
186	part = CDPART(dev);
187
188	if (unit >= cdcd.cd_ndevs)
189		return ENXIO;
190	cd = cdcd.cd_devs[unit];
191	/*
192	 * Make sure the device has been initialised
193	 */
194	if (!cd || !(cd->flags & CDINIT))
195		return ENXIO;
196
197	sc_link = cd->sc_link;
198
199	SC_DEBUG(sc_link, SDEV_DB1,
200	    ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
201	    cdcd.cd_ndevs, part));
202
203	/*
204	 * If it's been invalidated, and not everybody has closed it then
205	 * forbid re-entry.  (may have changed media)
206	 */
207	if (!(sc_link->flags & SDEV_MEDIA_LOADED) && cd->openparts)
208		return ENXIO;
209
210	/*
211	 * Check that it is still responding and ok.
212	 * if the media has been changed this will result in a
213	 * "unit attention" error which the error code will
214	 * disregard because the SDEV_MEDIA_LOADED flag is not yet set
215	 */
216	scsi_test_unit_ready(sc_link, SCSI_SILENT);
217
218	/*
219	 * In case it is a funny one, tell it to start
220	 * not needed for some drives
221	 */
222	scsi_start_unit(sc_link, SCSI_ERR_OK | SCSI_SILENT);
223
224	/*
225	 * Next time actually take notice of error returns
226	 */
227	sc_link->flags |= SDEV_OPEN;	/* unit attn errors are now errors */
228	if (scsi_test_unit_ready(sc_link, 0) != 0) {
229		SC_DEBUG(sc_link, SDEV_DB3, ("device not responding\n"));
230		error = ENXIO;
231		goto bad;
232	}
233	SC_DEBUG(sc_link, SDEV_DB3, ("device ok\n"));
234
235	/* Lock the pack in. */
236	scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
237
238	/*
239	 * Load the physical device parameters
240	 */
241	if (cd_get_parms(cd, 0)) {
242		error = ENXIO;
243		goto bad;
244	}
245	SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
246
247	/*
248	 * Make up some partition information
249	 */
250	cdgetdisklabel(cd);
251	SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated "));
252
253	/*
254	 * Check the partition is legal
255	 */
256	if (part >= cd->sc_dk.dk_label.d_npartitions && part != RAW_PART) {
257		error = ENXIO;
258		goto bad;
259	}
260	SC_DEBUG(sc_link, SDEV_DB3, ("partition ok"));
261
262	/*
263	 *  Check that the partition exists
264	 */
265	if (cd->sc_dk.dk_label.d_partitions[part].p_fstype == FS_UNUSED &&
266	    part != RAW_PART) {
267		error = ENXIO;
268		goto bad;
269	}
270	cd->partflags[part] |= CDOPEN;
271	cd->openparts |= (1 << part);
272	SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
273	sc_link->flags |= SDEV_MEDIA_LOADED;
274	return 0;
275
276bad:
277	if (!cd->openparts) {
278		scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
279		sc_link->flags &= ~SDEV_OPEN;
280	}
281	return error;
282}
283
284/*
285 * close the device.. only called if we are the LAST
286 * occurence of an open device
287 */
288int
289cdclose(dev)
290	dev_t dev;
291{
292	int unit, part;
293	struct cd_data *cd;
294
295	unit = CDUNIT(dev);
296	part = CDPART(dev);
297	cd = cdcd.cd_devs[unit];
298	cd->partflags[part] &= ~CDOPEN;
299	cd->openparts &= ~(1 << part);
300	if (!cd->openparts) {
301		scsi_prevent(cd->sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
302		cd->sc_link->flags &= ~SDEV_OPEN;
303	}
304	return 0;
305}
306
307/*
308 * trim the size of the transfer if needed,
309 * called by physio
310 * basically the smaller of our max and the scsi driver's
311 * minphys (note we have no max ourselves)
312 *
313 * Trim buffer length if buffer-size is bigger than page size
314 */
315void
316cdminphys(bp)
317	struct buf *bp;
318{
319	register struct cd_data *cd = cdcd.cd_devs[CDUNIT(bp->b_dev)];
320
321	(cd->sc_link->adapter->scsi_minphys) (bp);
322}
323
324/*
325 * Actually translate the requested transfer into one the physical driver can
326 * understand.  The transfer is described by a buf and will include only one
327 * physical transfer.
328 */
329void
330cdstrategy(bp)
331	struct buf *bp;
332{
333	struct buf *dp;
334	int opri;
335	struct cd_data *cd;
336	int unit;
337
338	unit = CDUNIT(bp->b_dev);
339	cd = cdcd.cd_devs[unit];
340	SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdstrategy "));
341	SC_DEBUG(cd->sc_link, SDEV_DB1,
342	    ("%d bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));
343	cdminphys(bp);
344	/*
345	 * If the device has been made invalid, error out
346	 * maybe the media changed
347	 */
348	if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED)) {
349		bp->b_error = EIO;
350		goto bad;
351	}
352	/*
353	 * can't ever write to a CD
354	 */
355	if ((bp->b_flags & B_READ) == 0) {
356		bp->b_error = EROFS;
357		goto bad;
358	}
359	/*
360	 * If it's a null transfer, return immediately
361	 */
362	if (bp->b_bcount == 0)
363		goto done;
364	/*
365	 * Decide which unit and partition we are talking about
366	 */
367	if (CDPART(bp->b_dev) != RAW_PART) {
368		/*
369		 * do bounds checking, adjust transfer. if error, process.
370		 * if end of partition, just return
371		 */
372		if (bounds_check_with_label(bp, &cd->sc_dk.dk_label, 1) <= 0)
373			goto done;
374		/* otherwise, process transfer request */
375	}
376	opri = splbio();
377	dp = &cd->buf_queue;
378
379	/*
380	 * Place it in the queue of disk activities for this disk
381	 */
382	disksort(dp, bp);
383
384	/*
385	 * Tell the device to get going on the transfer if it's
386	 * not doing anything, otherwise just wait for completion
387	 */
388	cdstart(unit);
389
390	splx(opri);
391	return;
392
393bad:
394	bp->b_flags |= B_ERROR;
395done:
396
397	/*
398	 * Correctly set the buf to indicate a completed xfer
399	 */
400	bp->b_resid = bp->b_bcount;
401	biodone(bp);
402}
403
404/*
405 * cdstart looks to see if there is a buf waiting for the device
406 * and that the device is not already busy. If both are true,
407 * It deques the buf and creates a scsi command to perform the
408 * transfer in the buf. The transfer request will call scsi_done
409 * on completion, which will in turn call this routine again
410 * so that the next queued transfer is performed.
411 * The bufs are queued by the strategy routine (cdstrategy)
412 *
413 * This routine is also called after other non-queued requests
414 * have been made of the scsi driver, to ensure that the queue
415 * continues to be drained.
416 *
417 * must be called at the correct (highish) spl level
418 * cdstart() is called at splbio from cdstrategy and scsi_done
419 */
420void
421cdstart(unit)
422	int unit;
423{
424	register struct cd_data *cd = cdcd.cd_devs[unit];
425	register struct scsi_link *sc_link = cd->sc_link;
426	struct buf *bp = 0;
427	struct buf *dp;
428	struct scsi_rw_big cmd;
429	int blkno, nblks;
430	struct partition *p;
431
432	SC_DEBUG(sc_link, SDEV_DB2, ("cdstart "));
433	/*
434	 * See if there is a buf to do and we are not already
435	 * doing one
436	 */
437	while (sc_link->opennings) {
438		/*
439		 * there is excess capacity, but a special waits
440		 * It'll need the adapter as soon as we clear out of the
441		 * way and let it run (user level wait).
442		 */
443		if (sc_link->flags & SDEV_WAITING) {
444			sc_link->flags &= ~SDEV_WAITING;
445			wakeup((caddr_t)sc_link);
446			return;
447		}
448
449		/*
450		 * See if there is a buf with work for us to do..
451		 */
452		dp = &cd->buf_queue;
453		if ((bp = dp->b_actf) == NULL)	/* yes, an assign */
454			return;
455		dp->b_actf = bp->b_actf;
456
457		/*
458		 * If the deivce has become invalid, abort all the
459		 * reads and writes until all files have been closed and
460		 * re-openned
461		 */
462		if (!(sc_link->flags & SDEV_MEDIA_LOADED))
463			goto bad;
464
465		/*
466		 * We have a buf, now we should make a command
467		 *
468		 * First, translate the block to absolute and put it in terms
469		 * of the logical blocksize of the device.  Really a bit silly
470		 * until we have real partitions, but.
471		 */
472		blkno = bp->b_blkno / (cd->params.blksize / DEV_BSIZE);
473		if (CDPART(bp->b_dev) != RAW_PART) {
474			p = &cd->sc_dk.dk_label.d_partitions[CDPART(bp->b_dev)];
475			blkno += p->p_offset;
476		}
477		nblks = (bp->b_bcount + (cd->params.blksize - 1)) /
478		    cd->params.blksize;
479
480		/*
481		 *  Fill out the scsi command
482		 */
483		bzero(&cmd, sizeof(cmd));
484		cmd.op_code = (bp->b_flags & B_READ) ? READ_BIG : WRITE_BIG;
485		cmd.addr_3 = (blkno & 0xff000000) >> 24;
486		cmd.addr_2 = (blkno & 0xff0000) >> 16;
487		cmd.addr_1 = (blkno & 0xff00) >> 8;
488		cmd.addr_0 = blkno & 0xff;
489		cmd.length2 = (nblks & 0xff00) >> 8;
490		cmd.length1 = (nblks & 0xff);
491
492		/*
493		 * Call the routine that chats with the adapter.
494		 * Note: we cannot sleep as we may be an interrupt
495		 */
496		if (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd,
497		    sizeof(cmd), (u_char *) bp->b_un.b_addr, bp->b_bcount,
498		    CDRETRIES, 30000, bp, SCSI_NOSLEEP |
499		    ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT))
500		    != SUCCESSFULLY_QUEUED) {
501bad:
502			printf("%s: not queued", cd->sc_dev.dv_xname);
503			bp->b_error = EIO;
504			bp->b_flags |= B_ERROR;
505			biodone(bp);
506		}
507	}
508}
509
510/*
511 * Perform special action on behalf of the user.
512 * Knows about the internals of this device
513 */
514int
515cdioctl(dev, cmd, addr, flag)
516	dev_t dev;
517	int cmd;
518	caddr_t addr;
519	int flag;
520{
521	int error;
522	int unit, part;
523	register struct cd_data *cd;
524
525	/*
526	 * Find the device that the user is talking about
527	 */
528	unit = CDUNIT(dev);
529	part = CDPART(dev);
530	cd = cdcd.cd_devs[unit];
531	SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%x ", cmd));
532
533	/*
534	 * If the device is not valid.. abandon ship
535	 */
536	if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED))
537		return EIO;
538
539	switch (cmd) {
540	case DIOCSBAD:
541		return EINVAL;
542
543	case DIOCGDINFO:
544		*(struct disklabel *) addr = cd->sc_dk.dk_label;
545		return 0;
546
547	case DIOCGPART:
548		((struct partinfo *) addr)->disklab = &cd->sc_dk.dk_label;
549		((struct partinfo *) addr)->part =
550		    &cd->sc_dk.dk_label.d_partitions[CDPART(dev)];
551		return 0;
552
553		/*
554		 * a bit silly, but someone might want to test something on a
555		 * section of cdrom.
556		 */
557	case DIOCWDINFO:
558	case DIOCSDINFO:
559		if ((flag & FWRITE) == 0)
560			return EBADF;
561		error = setdisklabel(&cd->sc_dk.dk_label,
562		    (struct disklabel *) addr, 0, 0);
563		return error;
564
565	case DIOCWLABEL:
566		return EBADF;
567
568	case CDIOCPLAYTRACKS: {
569		struct ioc_play_track *args = (struct ioc_play_track *) addr;
570		struct cd_mode_data data;
571		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
572			return error;
573		data.page.audio.flags &= ~CD_PA_SOTC;
574		data.page.audio.flags |= CD_PA_IMMED;
575		if (error = cd_set_mode(cd, &data))
576			return error;
577		return cd_play_tracks(cd, args->start_track, args->start_index,
578		    args->end_track, args->end_index);
579	}
580	case CDIOCPLAYMSF: {
581		struct ioc_play_msf *args
582		= (struct ioc_play_msf *) addr;
583		struct cd_mode_data data;
584		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
585			return error;
586		data.page.audio.flags &= ~CD_PA_SOTC;
587		data.page.audio.flags |= CD_PA_IMMED;
588		if (error = cd_set_mode(cd, &data))
589			return error;
590		return cd_play_msf(cd, args->start_m, args->start_s,
591		    args->start_f, args->end_m, args->end_s, args->end_f);
592	}
593	case CDIOCPLAYBLOCKS: {
594		struct ioc_play_blocks *args
595		= (struct ioc_play_blocks *) addr;
596		struct cd_mode_data data;
597		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
598			return error;
599		data.page.audio.flags &= ~CD_PA_SOTC;
600		data.page.audio.flags |= CD_PA_IMMED;
601		if (error = cd_set_mode(cd, &data))
602			return error;
603		return cd_play(cd, args->blk, args->len);
604	}
605	case CDIOCREADSUBCHANNEL: {
606		struct ioc_read_subchannel *args
607		= (struct ioc_read_subchannel *) addr;
608		struct cd_sub_channel_info data;
609		u_int32 len = args->data_len;
610		if (len > sizeof(data) ||
611		    len < sizeof(struct cd_sub_channel_header))
612			return EINVAL;
613		if (error = cd_read_subchannel(cd, args->address_format,
614		    args->data_format, args->track, &data, len))
615			return error;
616		len = min(len, ((data.header.data_len[0] << 8) +
617		    data.header.data_len[1] +
618		    sizeof(struct cd_sub_channel_header)));
619		return copyout(&data, args->data, len);
620	}
621	case CDIOREADTOCHEADER: {
622		struct ioc_toc_header th;
623		if (error = cd_read_toc(cd, 0, 0, &th, sizeof(th)))
624			return error;
625		th.len = ntohs(th.len);
626		bcopy(&th, addr, sizeof(th));
627		return 0;
628	}
629	case CDIOREADTOCENTRYS: {
630		struct cd_toc {
631			struct ioc_toc_header header;
632			struct cd_toc_entry entries[65];
633		} data;
634		struct ioc_read_toc_entry *te =
635		(struct ioc_read_toc_entry *) addr;
636		struct ioc_toc_header *th;
637		u_int32 len = te->data_len;
638		th = &data.header;
639
640		if (len > sizeof(data.entries) ||
641		    len < sizeof(struct cd_toc_entry))
642			return EINVAL;
643		if (error = cd_read_toc(cd, te->address_format,
644		    te->starting_track, (struct cd_toc_entry *) &data,
645		    len + sizeof(struct ioc_toc_header)))
646			return error;
647		len = min(len, ntohs(th->len) - (sizeof(th->starting_track) +
648		    sizeof(th->ending_track)));
649		return copyout(data.entries, te->data, len);
650	}
651	case CDIOCSETPATCH: {
652		struct ioc_patch *arg = (struct ioc_patch *) addr;
653		struct cd_mode_data data;
654		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
655			return error;
656		data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
657		data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
658		data.page.audio.port[2].channels = arg->patch[2];
659		data.page.audio.port[3].channels = arg->patch[3];
660		return cd_set_mode(cd, &data);
661	}
662	case CDIOCGETVOL: {
663		struct ioc_vol *arg = (struct ioc_vol *) addr;
664		struct cd_mode_data data;
665		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
666			return error;
667		arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
668		arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
669		arg->vol[2] = data.page.audio.port[2].volume;
670		arg->vol[3] = data.page.audio.port[3].volume;
671		return 0;
672	}
673	case CDIOCSETVOL: {
674		struct ioc_vol *arg = (struct ioc_vol *) addr;
675		struct cd_mode_data data;
676		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
677			return error;
678		data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
679		data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
680		data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1;
681		data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
682		data.page.audio.port[2].volume = arg->vol[2];
683		data.page.audio.port[3].volume = arg->vol[3];
684		return cd_set_mode(cd, &data);
685	}
686	case CDIOCSETMONO: {
687		struct ioc_vol *arg = (struct ioc_vol *) addr;
688		struct cd_mode_data data;
689		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
690			return error;
691		data.page.audio.port[LEFT_PORT].channels =
692		    LEFT_CHANNEL | RIGHT_CHANNEL | 4 | 8;
693		data.page.audio.port[RIGHT_PORT].channels =
694		    LEFT_CHANNEL | RIGHT_CHANNEL;
695		data.page.audio.port[2].channels = 0;
696		data.page.audio.port[3].channels = 0;
697		return cd_set_mode(cd, &data);
698	}
699	case CDIOCSETSTERIO: {
700		struct ioc_vol *arg = (struct ioc_vol *) addr;
701		struct cd_mode_data data;
702		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
703			return error;
704		data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
705		data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
706		data.page.audio.port[2].channels = 0;
707		data.page.audio.port[3].channels = 0;
708		return cd_set_mode(cd, &data);
709	}
710	case CDIOCSETMUTE: {
711		struct ioc_vol *arg = (struct ioc_vol *) addr;
712		struct cd_mode_data data;
713		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
714			return error;
715		data.page.audio.port[LEFT_PORT].channels = 0;
716		data.page.audio.port[RIGHT_PORT].channels = 0;
717		data.page.audio.port[2].channels = 0;
718		data.page.audio.port[3].channels = 0;
719		return cd_set_mode(cd, &data);
720	}
721	case CDIOCSETLEFT: {
722		struct ioc_vol *arg = (struct ioc_vol *) addr;
723		struct cd_mode_data data;
724		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
725			return error;
726		data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
727		data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
728		data.page.audio.port[2].channels = 0;
729		data.page.audio.port[3].channels = 0;
730		return cd_set_mode(cd, &data);
731	}
732	case CDIOCSETRIGHT: {
733		struct ioc_vol *arg = (struct ioc_vol *) addr;
734		struct cd_mode_data data;
735		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
736			return error;
737		data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
738		data.page.audio.port[RIGHT_PORT].channels = 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 CDIOCRESUME:
744		return cd_pause(cd, 1);
745	case CDIOCPAUSE:
746		return cd_pause(cd, 0);
747	case CDIOCSTART:
748		return scsi_start_unit(cd->sc_link, 0);
749	case CDIOCSTOP:
750		return scsi_stop_unit(cd->sc_link, 0, 0);
751	case CDIOCEJECT:
752		return scsi_stop_unit(cd->sc_link, 1, 0);
753	case CDIOCALLOW:
754		return scsi_prevent(cd->sc_link, PR_ALLOW, 0);
755	case CDIOCPREVENT:
756		return scsi_prevent(cd->sc_link, PR_PREVENT, 0);
757	case CDIOCSETDEBUG:
758		cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
759		return 0;
760	case CDIOCCLRDEBUG:
761		cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
762		return 0;
763	case CDIOCRESET:
764		return cd_reset(cd);
765	default:
766		if (part != RAW_PART)
767			return ENOTTY;
768		return scsi_do_ioctl(cd->sc_link, cmd, addr, flag);
769	}
770#ifdef DIAGNOSTIC
771	panic("cdioctl: impossible");
772#endif
773}
774
775/*
776 * Load the label information on the named device
777 * Actually fabricate a disklabel
778 *
779 * EVENTUALLY take information about different
780 * data tracks from the TOC and put it in the disklabel
781 */
782int
783cdgetdisklabel(cd)
784	struct cd_data *cd;
785{
786	char *errstring;
787
788	bzero(&cd->sc_dk.dk_label, sizeof(struct disklabel));
789	bzero(&cd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
790	/*
791	 * make partition 0 the whole disk
792	 * remember that comparisons with the partition are done
793	 * assuming the blocks are 512 bytes so fudge it.
794	 */
795	cd->sc_dk.dk_label.d_partitions[0].p_offset = 0;
796	cd->sc_dk.dk_label.d_partitions[0].p_size =
797	    cd->params.disksize * (cd->params.blksize / DEV_BSIZE);
798	cd->sc_dk.dk_label.d_partitions[0].p_fstype = FS_ISO9660;
799	cd->sc_dk.dk_label.d_npartitions = 1;
800
801	cd->sc_dk.dk_label.d_secsize = cd->params.blksize;
802	cd->sc_dk.dk_label.d_ntracks = 1;
803	cd->sc_dk.dk_label.d_nsectors = 100;
804	cd->sc_dk.dk_label.d_ncylinders = (cd->params.disksize / 100) + 1;
805	cd->sc_dk.dk_label.d_secpercyl = 100;
806
807	strncpy(cd->sc_dk.dk_label.d_typename, "scsi cd_rom", 16);
808	strncpy(cd->sc_dk.dk_label.d_packname, "ficticious", 16);
809	cd->sc_dk.dk_label.d_secperunit = cd->params.disksize;
810	cd->sc_dk.dk_label.d_rpm = 300;
811	cd->sc_dk.dk_label.d_interleave = 1;
812	cd->sc_dk.dk_label.d_flags = D_REMOVABLE;
813	cd->sc_dk.dk_label.d_magic = DISKMAGIC;
814	cd->sc_dk.dk_label.d_magic2 = DISKMAGIC;
815	cd->sc_dk.dk_label.d_checksum = dkcksum(&cd->sc_dk.dk_label);
816
817	/*
818	 * Signal to other users and routines that we now have a
819	 * disklabel that represents the media (maybe)
820	 */
821	return 0;
822}
823
824/*
825 * Find out from the device what it's capacity is
826 */
827u_int32
828cd_size(cd, flags)
829	struct cd_data *cd;
830	int flags;
831{
832	struct scsi_read_cd_cap_data rdcap;
833	struct scsi_read_cd_capacity scsi_cmd;
834	u_int32 size, blksize;
835
836	/*
837	 * make up a scsi command and ask the scsi driver to do
838	 * it for you.
839	 */
840	bzero(&scsi_cmd, sizeof(scsi_cmd));
841	scsi_cmd.op_code = READ_CD_CAPACITY;
842
843	/*
844	 * If the command works, interpret the result as a 4 byte
845	 * number of blocks and a blocksize
846	 */
847	if (scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd,
848	    sizeof(scsi_cmd), (u_char *) &rdcap, sizeof(rdcap), CDRETRIES,
849	    20000, NULL, SCSI_DATA_IN | flags) != 0) {
850		if (!(flags & SCSI_SILENT))
851			printf("%s: could not get size\n",
852			    cd->sc_dev.dv_xname);
853		return 0;
854	} else {
855		size = (rdcap.addr_3 << 24) + (rdcap.addr_2 << 16) +
856		    (rdcap.addr_1 << 8) + rdcap.addr_0 + 1;
857		blksize = (rdcap.length_3 << 24) + (rdcap.length_2 << 16) +
858		    (rdcap.length_1 << 8) + rdcap.length_0;
859	}
860	if (blksize < 512)
861		blksize = 2048;	/* some drives lie ! */
862	if (size < 100)
863		size = 400000;	/* ditto */
864	cd->params.disksize = size;
865	cd->params.blksize = blksize;
866	return size;
867}
868
869/*
870 * Get the requested page into the buffer given
871 */
872int
873cd_get_mode(cd, data, page)
874	struct cd_data *cd;
875	struct cd_mode_data *data;
876	int page;
877{
878	struct scsi_mode_sense scsi_cmd;
879	int error;
880
881	bzero(&scsi_cmd, sizeof(scsi_cmd));
882	bzero(data, sizeof(*data));
883	scsi_cmd.op_code = MODE_SENSE;
884	scsi_cmd.page = page;
885	scsi_cmd.length = sizeof(*data) & 0xff;
886	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd,
887	    sizeof(scsi_cmd), (u_char *) data, sizeof(*data), CDRETRIES, 20000,
888	    NULL, SCSI_DATA_IN);
889}
890
891/*
892 * Get the requested page into the buffer given
893 */
894int
895cd_set_mode(cd, data)
896	struct cd_data *cd;
897	struct cd_mode_data *data;
898{
899	struct scsi_mode_select scsi_cmd;
900
901	bzero(&scsi_cmd, sizeof(scsi_cmd));
902	scsi_cmd.op_code = MODE_SELECT;
903	scsi_cmd.byte2 |= SMS_PF;
904	scsi_cmd.length = sizeof(*data) & 0xff;
905	data->header.data_length = 0;
906	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd,
907	    sizeof(scsi_cmd), (u_char *) data, sizeof(*data), CDRETRIES, 20000,
908	    NULL, SCSI_DATA_OUT);
909}
910
911/*
912 * Get scsi driver to send a "start playing" command
913 */
914int
915cd_play(cd, blkno, nblks)
916	struct cd_data *cd;
917	int blkno, nblks;
918{
919	struct scsi_play scsi_cmd;
920
921	bzero(&scsi_cmd, sizeof(scsi_cmd));
922	scsi_cmd.op_code = PLAY;
923	scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
924	scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
925	scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
926	scsi_cmd.blk_addr[3] = blkno & 0xff;
927	scsi_cmd.xfer_len[0] = (nblks >> 8) & 0xff;
928	scsi_cmd.xfer_len[1] = nblks & 0xff;
929	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd,
930	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 200000, NULL, 0);
931}
932
933/*
934 * Get scsi driver to send a "start playing" command
935 */
936int
937cd_play_big(cd, blkno, nblks)
938	struct cd_data *cd;
939	int blkno, nblks;
940{
941	struct scsi_play_big scsi_cmd;
942
943	bzero(&scsi_cmd, sizeof(scsi_cmd));
944	scsi_cmd.op_code = PLAY_BIG;
945	scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
946	scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
947	scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
948	scsi_cmd.blk_addr[3] = blkno & 0xff;
949	scsi_cmd.xfer_len[0] = (nblks >> 24) & 0xff;
950	scsi_cmd.xfer_len[1] = (nblks >> 16) & 0xff;
951	scsi_cmd.xfer_len[2] = (nblks >> 8) & 0xff;
952	scsi_cmd.xfer_len[3] = nblks & 0xff;
953	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd,
954	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
955}
956
957/*
958 * Get scsi driver to send a "start playing" command
959 */
960int
961cd_play_tracks(cd, strack, sindex, etrack, eindex)
962	struct cd_data *cd;
963	int strack, sindex, etrack, eindex;
964{
965	struct scsi_play_track scsi_cmd;
966
967	bzero(&scsi_cmd, sizeof(scsi_cmd));
968	scsi_cmd.op_code = PLAY_TRACK;
969	scsi_cmd.start_track = strack;
970	scsi_cmd.start_index = sindex;
971	scsi_cmd.end_track = etrack;
972	scsi_cmd.end_index = eindex;
973	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd,
974	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
975}
976
977/*
978 * Get scsi driver to send a "play msf" command
979 */
980int
981cd_play_msf(cd, startm, starts, startf, endm, ends, endf)
982	struct cd_data *cd;
983	int startm, starts, startf, endm, ends, endf;
984{
985	struct scsi_play_msf scsi_cmd;
986
987	bzero(&scsi_cmd, sizeof(scsi_cmd));
988	scsi_cmd.op_code = PLAY_MSF;
989	scsi_cmd.start_m = startm;
990	scsi_cmd.start_s = starts;
991	scsi_cmd.start_f = startf;
992	scsi_cmd.end_m = endm;
993	scsi_cmd.end_s = ends;
994	scsi_cmd.end_f = endf;
995	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd,
996	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
997}
998
999/*
1000 * Get scsi driver to send a "start up" command
1001 */
1002int
1003cd_pause(cd, go)
1004	struct cd_data *cd;
1005	int go;
1006{
1007	struct scsi_pause scsi_cmd;
1008
1009	bzero(&scsi_cmd, sizeof(scsi_cmd));
1010	scsi_cmd.op_code = PAUSE;
1011	scsi_cmd.resume = go;
1012	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd,
1013	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
1014}
1015
1016/*
1017 * Get scsi driver to send a "RESET" command
1018 */
1019int
1020cd_reset(cd)
1021	struct cd_data *cd;
1022{
1023
1024	return scsi_scsi_cmd(cd->sc_link, 0, 0, 0, 0, CDRETRIES, 2000, NULL,
1025	    SCSI_RESET);
1026}
1027
1028/*
1029 * Read subchannel
1030 */
1031int
1032cd_read_subchannel(cd, mode, format, track, data, len)
1033	struct cd_data *cd;
1034	int mode, format, len;
1035	struct cd_sub_channel_info *data;
1036{
1037	struct scsi_read_subchannel scsi_cmd;
1038
1039	bzero(&scsi_cmd, sizeof(scsi_cmd));
1040	scsi_cmd.op_code = READ_SUBCHANNEL;
1041	if (mode == CD_MSF_FORMAT)
1042		scsi_cmd.byte2 |= CD_MSF;
1043	scsi_cmd.byte3 = SRS_SUBQ;
1044	scsi_cmd.subchan_format = format;
1045	scsi_cmd.track = track;
1046	scsi_cmd.data_len[0] = (len) >> 8;
1047	scsi_cmd.data_len[1] = (len) & 0xff;
1048	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd,
1049	    sizeof(struct scsi_read_subchannel), (u_char *) data, len,
1050	    CDRETRIES, 5000, NULL, SCSI_DATA_IN);
1051}
1052
1053/*
1054 * Read table of contents
1055 */
1056int
1057cd_read_toc(cd, mode, start, data, len)
1058	struct cd_data *cd;
1059	int mode, start, len;
1060	struct cd_toc_entry *data;
1061{
1062	struct scsi_read_toc scsi_cmd;
1063	int ntoc;
1064
1065	bzero(&scsi_cmd, sizeof(scsi_cmd));
1066	/*if (len!=sizeof(struct ioc_toc_header))
1067	 * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
1068	 * else */
1069	ntoc = len;
1070	scsi_cmd.op_code = READ_TOC;
1071	if (mode == CD_MSF_FORMAT)
1072		scsi_cmd.byte2 |= CD_MSF;
1073	scsi_cmd.from_track = start;
1074	scsi_cmd.data_len[0] = (ntoc) >> 8;
1075	scsi_cmd.data_len[1] = (ntoc) & 0xff;
1076	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd,
1077	    sizeof(struct scsi_read_toc), (u_char *) data, len, CDRETRIES,
1078	    5000, NULL, SCSI_DATA_IN);
1079}
1080
1081#define b2tol(a)	(((unsigned)(a##_1) << 8) + (unsigned)a##_0)
1082
1083/*
1084 * Get the scsi driver to send a full inquiry to the device and use the
1085 * results to fill out the disk parameter structure.
1086 */
1087int
1088cd_get_parms(cd, flags)
1089	struct cd_data *cd;
1090	int flags;
1091{
1092
1093	/*
1094	 * First check if we have it all loaded
1095	 */
1096	if (cd->sc_link->flags & SDEV_MEDIA_LOADED)
1097		return 0;
1098
1099	/*
1100	 * give a number of sectors so that sec * trks * cyls
1101	 * is <= disk_size
1102	 */
1103	if (!cd_size(cd, flags))
1104		return ENXIO;
1105
1106	cd->sc_link->flags |= SDEV_MEDIA_LOADED;
1107	return 0;
1108}
1109
1110int
1111cdsize(dev_t dev)
1112{
1113
1114	return -1;
1115}
1116