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