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