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