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