xref: /netbsd-src/sys/dev/scsipi/cd.c (revision 201fac6e3d8ac6a5503c4810b0378f73101d50c3)
1 /*	$NetBSD: cd.c,v 1.45 1994/12/14 15:20:11 mycroft Exp $	*/
2 
3 /*
4  * Copyright (c) 1994 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_data {
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_BSDLABEL	0x04
92 	struct scsi_link *sc_link;	/* address of scsi low level switch */
93 	u_int32 ad_info;	/* info about the adapter */
94 	u_int32 cmdscount;	/* cmds allowed outstanding by board */
95 	struct cd_parms {
96 		u_int32 blksize;
97 		u_long disksize;	/* total number sectors */
98 	} params;
99 	u_int32 xfer_block_wait;
100 	struct buf buf_queue;
101 };
102 
103 void cdattach __P((struct device *, struct device *, void *));
104 
105 struct cfdriver cdcd = {
106 	NULL, "cd", scsi_targmatch, cdattach, DV_DISK, sizeof(struct cd_data)
107 };
108 
109 void cdgetdisklabel __P((struct cd_data *));
110 int cd_get_parms __P((struct cd_data *, int));
111 void cdstrategy __P((struct buf *));
112 void cdstart __P((struct cd_data *));
113 
114 struct dkdriver cddkdriver = { cdstrategy };
115 
116 struct scsi_device cd_switch = {
117 	NULL,			/* use default error handler */
118 	cdstart,		/* we have a queue, which is started by this */
119 	NULL,			/* we do not have an async handler */
120 	NULL,			/* use default 'done' routine */
121 	"cd",			/* we are to be refered to by this name */
122 	0			/* no device specific flags */
123 };
124 
125 #define CD_STOP		0
126 #define CD_START	1
127 #define CD_EJECT	-2
128 
129 /*
130  * The routine called by the low level scsi routine when it discovers
131  * A device suitable for this driver
132  */
133 void
134 cdattach(parent, self, aux)
135 	struct device *parent, *self;
136 	void *aux;
137 {
138 	struct cd_data *cd = (void *)self;
139 	struct cd_parms *dp = &cd->params;
140 	struct scsi_link *sc_link = aux;
141 
142 	SC_DEBUG(sc_link, SDEV_DB2, ("cdattach: "));
143 
144 	/*
145 	 * Store information needed to contact our base driver
146 	 */
147 	cd->sc_link = sc_link;
148 	sc_link->device = &cd_switch;
149 	sc_link->device_softc = cd;
150 
151 	cd->sc_dk.dk_driver = &cddkdriver;
152 #if !defined(i386) || defined(NEWCONFIG)
153 	dk_establish(&cd->sc_dk, &cd->sc_dev);
154 #endif
155 
156 	if (cd->sc_link->adapter->adapter_info) {
157 		cd->ad_info = ((*(cd->sc_link->adapter->adapter_info)) (sc_link->adapter_softc));
158 		cd->cmdscount = cd->ad_info & AD_INF_MAX_CMDS;
159 		if (cd->cmdscount > CDOUTSTANDING)
160 			cd->cmdscount = CDOUTSTANDING;
161 	} else {
162 		cd->ad_info = 1;
163 		cd->cmdscount = 1;
164 	}
165 	sc_link->opennings = cd->cmdscount;
166 
167 	/*
168 	 * Use the subdriver to request information regarding
169 	 * the drive. We cannot use interrupts yet, so the
170 	 * request must specify this.
171 	 */
172 	cd_get_parms(cd, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
173 	if (dp->disksize)
174 		printf(": cd present, %d x %d byte records\n",
175 		    cd->params.disksize, cd->params.blksize);
176 	else
177 		printf(": drive empty\n");
178 }
179 
180 /*
181  * open the device. Make sure the partition info is a up-to-date as can be.
182  */
183 int
184 cdopen(dev, flag, fmt)
185 	dev_t dev;
186 	int flag, fmt;
187 {
188 	int error;
189 	int unit, part;
190 	struct cd_data *cd;
191 	struct scsi_link *sc_link;
192 
193 	unit = CDUNIT(dev);
194 	if (unit >= cdcd.cd_ndevs)
195 		return ENXIO;
196 	cd = cdcd.cd_devs[unit];
197 	if (!cd)
198 		return ENXIO;
199 
200 	part = CDPART(dev);
201 	sc_link = cd->sc_link;
202 
203 	SC_DEBUG(sc_link, SDEV_DB1,
204 	    ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
205 	    cdcd.cd_ndevs, part));
206 
207 	while ((cd->flags & CDF_LOCKED) != 0) {
208 		cd->flags |= CDF_WANTED;
209 		if ((error = tsleep(cd, PRIBIO | PCATCH, "cdopn", 0)) != 0)
210 			return error;
211 	}
212 
213 	if (cd->sc_dk.dk_openmask != 0) {
214 		/*
215 		 * If any partition is open, but the disk has been invalidated,
216 		 * disallow further opens.
217 		 */
218 		if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0)
219 			return ENXIO;
220 	} else {
221 		cd->flags |= CDF_LOCKED;
222 
223 		/*
224 		 * Check that it is still responding and ok.
225 		 * if the media has been changed this will result in a
226 		 * "unit attention" error which the error code will
227 		 * disregard because the SDEV_OPEN flag is not yet set.
228 		 */
229 		scsi_test_unit_ready(sc_link, SCSI_SILENT);
230 
231 		/*
232 		 * In case it is a funny one, tell it to start
233 		 * not needed for some drives
234 		 */
235 		scsi_start(sc_link, SSS_START, SCSI_ERR_OK | SCSI_SILENT);
236 
237 		sc_link->flags |= SDEV_OPEN;	/* unit attn errors are now errors */
238 
239 		/*
240 		 * Check that it is still responding and ok.
241 		 */
242 		if (scsi_test_unit_ready(sc_link, 0) != 0) {
243 			SC_DEBUG(sc_link, SDEV_DB3, ("device not responding\n"));
244 			error = ENXIO;
245 			goto bad;
246 		}
247 		SC_DEBUG(sc_link, SDEV_DB3, ("device ok\n"));
248 
249 		/* Lock the pack in. */
250 		scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
251 
252 		if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
253 			cd->flags &= ~CDF_BSDLABEL;
254 			sc_link->flags |= SDEV_MEDIA_LOADED;
255 
256 			/* Load the physical device parameters. */
257 			if (cd_get_parms(cd, 0) != 0) {
258 				error = ENXIO;
259 				goto bad2;
260 			}
261 			SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
262 
263 			/* Fabricate a disk label. */
264 			cdgetdisklabel(cd);
265 			SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated "));
266 		}
267 
268 		cd->flags &= ~CDF_LOCKED;
269 		if ((cd->flags & CDF_WANTED) != 0) {
270 			cd->flags &= ~CDF_WANTED;
271 			wakeup(cd);
272 		}
273 	}
274 
275 	/* Check that the partition exists. */
276 	if (part != RAW_PART &&
277 	    (part >= cd->sc_dk.dk_label.d_npartitions ||
278 	     cd->sc_dk.dk_label.d_partitions[part].p_fstype == FS_UNUSED)) {
279 		error = ENXIO;
280 		goto bad;
281 	}
282 
283 	/* Insure only one open at a time. */
284 	switch (fmt) {
285 	case S_IFCHR:
286 		cd->sc_dk.dk_copenmask |= (1 << part);
287 		break;
288 	case S_IFBLK:
289 		cd->sc_dk.dk_bopenmask |= (1 << part);
290 		break;
291 	}
292 	cd->sc_dk.dk_openmask = cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
293 
294 	SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
295 	return 0;
296 
297 bad2:
298 	sc_link->flags &= ~SDEV_MEDIA_LOADED;
299 
300 bad:
301 	if (cd->sc_dk.dk_openmask == 0) {
302 		scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
303 		sc_link->flags &= ~SDEV_OPEN;
304 
305 		cd->flags &= ~CDF_LOCKED;
306 		if ((cd->flags & CDF_WANTED) != 0) {
307 			cd->flags &= ~CDF_WANTED;
308 			wakeup(cd);
309 		}
310 	}
311 
312 	return error;
313 }
314 
315 /*
316  * close the device.. only called if we are the LAST
317  * occurence of an open device
318  */
319 int
320 cdclose(dev, flag, fmt)
321 	dev_t dev;
322 	int flag, fmt;
323 {
324 	struct cd_data *cd = cdcd.cd_devs[CDUNIT(dev)];
325 	int part = CDPART(dev);
326 	int s;
327 
328 	switch (fmt) {
329 	case S_IFCHR:
330 		cd->sc_dk.dk_copenmask &= ~(1 << part);
331 		break;
332 	case S_IFBLK:
333 		cd->sc_dk.dk_bopenmask &= ~(1 << part);
334 		break;
335 	}
336 	cd->sc_dk.dk_openmask = cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
337 
338 	if (cd->sc_dk.dk_openmask == 0) {
339 		cd->flags |= CDF_LOCKED;
340 
341 #if 0
342 		s = splbio();
343 		while (...) {
344 			cd->flags |= CDF_WAITING;
345 			if ((error = tsleep(cd, PRIBIO | PCATCH, "cdcls", 0)) != 0)
346 				return error;
347 		}
348 		splx(s);
349 #endif
350 
351 		scsi_prevent(cd->sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
352 		cd->sc_link->flags &= ~SDEV_OPEN;
353 
354 		cd->flags &= ~CDF_LOCKED;
355 		if ((cd->flags & CDF_WANTED) != 0) {
356 			cd->flags &= ~CDF_WANTED;
357 			wakeup(cd);
358 		}
359 	}
360 
361 	return 0;
362 }
363 
364 /*
365  * trim the size of the transfer if needed,
366  * called by physio
367  * basically the smaller of our max and the scsi driver's
368  * minphys (note we have no max ourselves)
369  *
370  * Trim buffer length if buffer-size is bigger than page size
371  */
372 void
373 cdminphys(bp)
374 	struct buf *bp;
375 {
376 	register struct cd_data *cd = cdcd.cd_devs[CDUNIT(bp->b_dev)];
377 
378 	(cd->sc_link->adapter->scsi_minphys) (bp);
379 }
380 
381 /*
382  * Actually translate the requested transfer into one the physical driver can
383  * understand.  The transfer is described by a buf and will include only one
384  * physical transfer.
385  */
386 void
387 cdstrategy(bp)
388 	struct buf *bp;
389 {
390 	struct cd_data *cd = cdcd.cd_devs[CDUNIT(bp->b_dev)];
391 	int opri;
392 
393 	SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdstrategy "));
394 	SC_DEBUG(cd->sc_link, SDEV_DB1,
395 	    ("%d bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));
396 	cdminphys(bp);
397 	/*
398 	 * If the device has been made invalid, error out
399 	 * maybe the media changed
400 	 */
401 	if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED)) {
402 		bp->b_error = EIO;
403 		goto bad;
404 	}
405 	/*
406 	 * can't ever write to a CD
407 	 */
408 	if ((bp->b_flags & B_READ) == 0) {
409 		bp->b_error = EROFS;
410 		goto bad;
411 	}
412 	/*
413 	 * If it's a null transfer, return immediately
414 	 */
415 	if (bp->b_bcount == 0)
416 		goto done;
417 	/*
418 	 * Decide which unit and partition we are talking about
419 	 */
420 	if (CDPART(bp->b_dev) != RAW_PART) {
421 		if ((cd->flags & CDF_BSDLABEL) == 0) {
422 			bp->b_error = EIO;
423 			goto bad;
424 		}
425 		/*
426 		 * do bounds checking, adjust transfer. if error, process.
427 		 * if end of partition, just return
428 		 */
429 		if (bounds_check_with_label(bp, &cd->sc_dk.dk_label, 1) <= 0)
430 			goto done;
431 		/* otherwise, process transfer request */
432 	}
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_data *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 	 * See if there is a buf to do and we are not already
490 	 * doing one
491 	 */
492 	while (sc_link->opennings) {
493 		/*
494 		 * there is excess capacity, but a special waits
495 		 * It'll need the adapter as soon as we clear out of the
496 		 * way and let it run (user level wait).
497 		 */
498 		if (sc_link->flags & SDEV_WAITING) {
499 			sc_link->flags &= ~SDEV_WAITING;
500 			wakeup((caddr_t)sc_link);
501 			return;
502 		}
503 
504 		/*
505 		 * See if there is a buf with work for us to do..
506 		 */
507 		dp = &cd->buf_queue;
508 		if ((bp = dp->b_actf) == NULL)	/* yes, an assign */
509 			return;
510 		dp->b_actf = bp->b_actf;
511 
512 		/*
513 		 * If the deivce has become invalid, abort all the
514 		 * reads and writes until all files have been closed and
515 		 * re-openned
516 		 */
517 		if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
518 			bp->b_error = EIO;
519 			bp->b_flags |= B_ERROR;
520 			biodone(bp);
521 			continue;
522 		}
523 
524 		/*
525 		 * We have a buf, now we should make a command
526 		 *
527 		 * First, translate the block to absolute and put it in terms
528 		 * of the logical blocksize of the device.  Really a bit silly
529 		 * until we have real partitions, but.
530 		 */
531 		blkno =
532 		    bp->b_blkno / (cd->sc_dk.dk_label.d_secsize / DEV_BSIZE);
533 		if (CDPART(bp->b_dev) != RAW_PART) {
534 			p = &cd->sc_dk.dk_label.d_partitions[CDPART(bp->b_dev)];
535 			blkno += p->p_offset;
536 		}
537 		nblks = howmany(bp->b_bcount, cd->sc_dk.dk_label.d_secsize);
538 
539 		/*
540 		 *  Fill out the scsi command
541 		 */
542 		bzero(&cmd, sizeof(cmd));
543 		cmd.op_code = (bp->b_flags & B_READ) ? READ_BIG : WRITE_BIG;
544 		cmd.addr_3 = (blkno & 0xff000000) >> 24;
545 		cmd.addr_2 = (blkno & 0xff0000) >> 16;
546 		cmd.addr_1 = (blkno & 0xff00) >> 8;
547 		cmd.addr_0 = blkno & 0xff;
548 		cmd.length2 = (nblks & 0xff00) >> 8;
549 		cmd.length1 = (nblks & 0xff);
550 
551 		/*
552 		 * Call the routine that chats with the adapter.
553 		 * Note: we cannot sleep as we may be an interrupt
554 		 */
555 		if (scsi_scsi_cmd(sc_link, (struct scsi_generic *)&cmd,
556 		    sizeof(cmd), (u_char *) bp->b_data, bp->b_bcount,
557 		    CDRETRIES, 30000, bp, SCSI_NOSLEEP |
558 		    ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT))
559 		    != SUCCESSFULLY_QUEUED)
560 			printf("%s: not queued", cd->sc_dev.dv_xname);
561 	}
562 }
563 
564 /*
565  * Perform special action on behalf of the user.
566  * Knows about the internals of this device
567  */
568 int
569 cdioctl(dev, cmd, addr, flag)
570 	dev_t dev;
571 	u_long cmd;
572 	caddr_t addr;
573 	int flag;
574 {
575 	struct cd_data *cd = cdcd.cd_devs[CDUNIT(dev)];
576 	int error;
577 
578 	SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%x ", cmd));
579 
580 	/*
581 	 * If the device is not valid.. abandon ship
582 	 */
583 	if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED))
584 		return EIO;
585 
586 	switch (cmd) {
587 	case DIOCSBAD:
588 		return EINVAL;
589 
590 	case DIOCGDINFO:
591 		*(struct disklabel *)addr = cd->sc_dk.dk_label;
592 		return 0;
593 
594 	case DIOCGPART:
595 		((struct partinfo *)addr)->disklab = &cd->sc_dk.dk_label;
596 		((struct partinfo *)addr)->part =
597 		    &cd->sc_dk.dk_label.d_partitions[CDPART(dev)];
598 		return 0;
599 
600 	case DIOCWDINFO:
601 	case DIOCSDINFO:
602 		if ((flag & FWRITE) == 0)
603 			return EBADF;
604 		error = setdisklabel(&cd->sc_dk.dk_label,
605 		    (struct disklabel *)addr,
606 		    /*(cd->flags & CDF_BSDLABEL) ? cd->sc_dk.dk_openmask : */0,
607 		    &cd->sc_dk.dk_cpulabel);
608 		if (error == 0)
609 			cd->flags |= CDF_BSDLABEL;
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 		u_int32 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 		u_int32 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_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 	default:
813 		if (CDPART(dev) != RAW_PART)
814 			return ENOTTY;
815 		return scsi_do_ioctl(cd->sc_link, dev, cmd, addr, flag);
816 	}
817 
818 #ifdef DIAGNOSTIC
819 	panic("cdioctl: impossible");
820 #endif
821 }
822 
823 /*
824  * Load the label information on the named device
825  * Actually fabricate a disklabel
826  *
827  * EVENTUALLY take information about different
828  * data tracks from the TOC and put it in the disklabel
829  */
830 void
831 cdgetdisklabel(cd)
832 	struct cd_data *cd;
833 {
834 
835 	if ((cd->flags & CDF_BSDLABEL) != 0)
836 		return;
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, "ficticious", 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 	cd->flags |= CDF_BSDLABEL;
868 }
869 
870 /*
871  * Find out from the device what it's capacity is
872  */
873 u_int32
874 cd_size(cd, flags)
875 	struct cd_data *cd;
876 	int flags;
877 {
878 	struct scsi_read_cd_cap_data rdcap;
879 	struct scsi_read_cd_capacity scsi_cmd;
880 	u_int32 size, blksize;
881 	int error;
882 
883 	/*
884 	 * make up a scsi command and ask the scsi driver to do
885 	 * it for you.
886 	 */
887 	bzero(&scsi_cmd, sizeof(scsi_cmd));
888 	scsi_cmd.op_code = READ_CD_CAPACITY;
889 
890 	/*
891 	 * If the command works, interpret the result as a 4 byte
892 	 * number of blocks and a blocksize
893 	 */
894 	error = scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
895 	    sizeof(scsi_cmd), (u_char *)&rdcap, sizeof(rdcap), CDRETRIES,
896 	    20000, NULL, SCSI_DATA_IN | flags);
897 	if (error == EBUSY) {
898 		if (!(flags & SCSI_SILENT))
899 			printf("%s: waiting for drive to spin up\n",
900 			    cd->sc_dev.dv_xname);
901 		if (flags & SCSI_NOSLEEP)
902 			delay(2000000);
903 		else
904 			tsleep(cd, PRIBIO + 1, "cd_size", 2 * hz);
905 		error = scsi_scsi_cmd(cd->sc_link,
906 		    (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
907 		    (u_char *)&rdcap, sizeof(rdcap), CDRETRIES, 20000, NULL,
908 		    SCSI_DATA_IN | flags);
909 	}
910 
911 	if (error) {
912 		if (!(flags & SCSI_SILENT))
913 			printf("%s: could not get size\n",
914 			    cd->sc_dev.dv_xname);
915 		return 0;
916 	}
917 
918 	blksize = (rdcap.length_3 << 24) + (rdcap.length_2 << 16) +
919 	    (rdcap.length_1 << 8) + rdcap.length_0;
920 	if (blksize < 512)
921 		blksize = 2048;	/* some drives lie ! */
922 	cd->params.blksize = blksize;
923 
924 	size = (rdcap.addr_3 << 24) + (rdcap.addr_2 << 16) +
925 	    (rdcap.addr_1 << 8) + rdcap.addr_0 + 1;
926 	if (size < 100)
927 		size = 400000;	/* ditto */
928 	cd->params.disksize = size;
929 
930 	return size;
931 }
932 
933 /*
934  * Get the requested page into the buffer given
935  */
936 int
937 cd_get_mode(cd, data, page)
938 	struct cd_data *cd;
939 	struct cd_mode_data *data;
940 	int page;
941 {
942 	struct scsi_mode_sense scsi_cmd;
943 	int error;
944 
945 	bzero(&scsi_cmd, sizeof(scsi_cmd));
946 	bzero(data, sizeof(*data));
947 	scsi_cmd.op_code = MODE_SENSE;
948 	scsi_cmd.page = page;
949 	scsi_cmd.length = sizeof(*data) & 0xff;
950 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
951 	    sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000,
952 	    NULL, SCSI_DATA_IN);
953 }
954 
955 /*
956  * Get the requested page into the buffer given
957  */
958 int
959 cd_set_mode(cd, data)
960 	struct cd_data *cd;
961 	struct cd_mode_data *data;
962 {
963 	struct scsi_mode_select scsi_cmd;
964 
965 	bzero(&scsi_cmd, sizeof(scsi_cmd));
966 	scsi_cmd.op_code = MODE_SELECT;
967 	scsi_cmd.byte2 |= SMS_PF;
968 	scsi_cmd.length = sizeof(*data) & 0xff;
969 	data->header.data_length = 0;
970 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
971 	    sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000,
972 	    NULL, SCSI_DATA_OUT);
973 }
974 
975 /*
976  * Get scsi driver to send a "start playing" command
977  */
978 int
979 cd_play(cd, blkno, nblks)
980 	struct cd_data *cd;
981 	int blkno, nblks;
982 {
983 	struct scsi_play scsi_cmd;
984 
985 	bzero(&scsi_cmd, sizeof(scsi_cmd));
986 	scsi_cmd.op_code = PLAY;
987 	scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
988 	scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
989 	scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
990 	scsi_cmd.blk_addr[3] = blkno & 0xff;
991 	scsi_cmd.xfer_len[0] = (nblks >> 8) & 0xff;
992 	scsi_cmd.xfer_len[1] = nblks & 0xff;
993 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
994 	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 200000, NULL, 0);
995 }
996 
997 /*
998  * Get scsi driver to send a "start playing" command
999  */
1000 int
1001 cd_play_big(cd, blkno, nblks)
1002 	struct cd_data *cd;
1003 	int blkno, nblks;
1004 {
1005 	struct scsi_play_big scsi_cmd;
1006 
1007 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1008 	scsi_cmd.op_code = PLAY_BIG;
1009 	scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
1010 	scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
1011 	scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
1012 	scsi_cmd.blk_addr[3] = blkno & 0xff;
1013 	scsi_cmd.xfer_len[0] = (nblks >> 24) & 0xff;
1014 	scsi_cmd.xfer_len[1] = (nblks >> 16) & 0xff;
1015 	scsi_cmd.xfer_len[2] = (nblks >> 8) & 0xff;
1016 	scsi_cmd.xfer_len[3] = nblks & 0xff;
1017 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1018 	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
1019 }
1020 
1021 /*
1022  * Get scsi driver to send a "start playing" command
1023  */
1024 int
1025 cd_play_tracks(cd, strack, sindex, etrack, eindex)
1026 	struct cd_data *cd;
1027 	int strack, sindex, etrack, eindex;
1028 {
1029 	struct scsi_play_track scsi_cmd;
1030 
1031 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1032 	scsi_cmd.op_code = PLAY_TRACK;
1033 	scsi_cmd.start_track = strack;
1034 	scsi_cmd.start_index = sindex;
1035 	scsi_cmd.end_track = etrack;
1036 	scsi_cmd.end_index = eindex;
1037 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1038 	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
1039 }
1040 
1041 /*
1042  * Get scsi driver to send a "play msf" command
1043  */
1044 int
1045 cd_play_msf(cd, startm, starts, startf, endm, ends, endf)
1046 	struct cd_data *cd;
1047 	int startm, starts, startf, endm, ends, endf;
1048 {
1049 	struct scsi_play_msf scsi_cmd;
1050 
1051 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1052 	scsi_cmd.op_code = PLAY_MSF;
1053 	scsi_cmd.start_m = startm;
1054 	scsi_cmd.start_s = starts;
1055 	scsi_cmd.start_f = startf;
1056 	scsi_cmd.end_m = endm;
1057 	scsi_cmd.end_s = ends;
1058 	scsi_cmd.end_f = endf;
1059 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1060 	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
1061 }
1062 
1063 /*
1064  * Get scsi driver to send a "start up" command
1065  */
1066 int
1067 cd_pause(cd, go)
1068 	struct cd_data *cd;
1069 	int go;
1070 {
1071 	struct scsi_pause scsi_cmd;
1072 
1073 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1074 	scsi_cmd.op_code = PAUSE;
1075 	scsi_cmd.resume = go;
1076 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1077 	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
1078 }
1079 
1080 /*
1081  * Get scsi driver to send a "RESET" command
1082  */
1083 int
1084 cd_reset(cd)
1085 	struct cd_data *cd;
1086 {
1087 
1088 	return scsi_scsi_cmd(cd->sc_link, 0, 0, 0, 0, CDRETRIES, 2000, NULL,
1089 	    SCSI_RESET);
1090 }
1091 
1092 /*
1093  * Read subchannel
1094  */
1095 int
1096 cd_read_subchannel(cd, mode, format, track, data, len)
1097 	struct cd_data *cd;
1098 	int mode, format, len;
1099 	struct cd_sub_channel_info *data;
1100 {
1101 	struct scsi_read_subchannel scsi_cmd;
1102 
1103 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1104 	scsi_cmd.op_code = READ_SUBCHANNEL;
1105 	if (mode == CD_MSF_FORMAT)
1106 		scsi_cmd.byte2 |= CD_MSF;
1107 	scsi_cmd.byte3 = SRS_SUBQ;
1108 	scsi_cmd.subchan_format = format;
1109 	scsi_cmd.track = track;
1110 	scsi_cmd.data_len[0] = (len) >> 8;
1111 	scsi_cmd.data_len[1] = (len) & 0xff;
1112 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1113 	    sizeof(struct scsi_read_subchannel), (u_char *)data, len,
1114 	    CDRETRIES, 5000, NULL, SCSI_DATA_IN);
1115 }
1116 
1117 /*
1118  * Read table of contents
1119  */
1120 int
1121 cd_read_toc(cd, mode, start, data, len)
1122 	struct cd_data *cd;
1123 	int mode, start, len;
1124 	struct cd_toc_entry *data;
1125 {
1126 	struct scsi_read_toc scsi_cmd;
1127 	int ntoc;
1128 
1129 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1130 	/*if (len!=sizeof(struct ioc_toc_header))
1131 	 * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
1132 	 * else */
1133 	ntoc = len;
1134 	scsi_cmd.op_code = READ_TOC;
1135 	if (mode == CD_MSF_FORMAT)
1136 		scsi_cmd.byte2 |= CD_MSF;
1137 	scsi_cmd.from_track = start;
1138 	scsi_cmd.data_len[0] = (ntoc) >> 8;
1139 	scsi_cmd.data_len[1] = (ntoc) & 0xff;
1140 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1141 	    sizeof(struct scsi_read_toc), (u_char *)data, len, CDRETRIES,
1142 	    5000, NULL, SCSI_DATA_IN);
1143 }
1144 
1145 #define b2tol(a)	(((unsigned)(a##_1) << 8) + (unsigned)a##_0)
1146 
1147 /*
1148  * Get the scsi driver to send a full inquiry to the device and use the
1149  * results to fill out the disk parameter structure.
1150  */
1151 int
1152 cd_get_parms(cd, flags)
1153 	struct cd_data *cd;
1154 	int flags;
1155 {
1156 
1157 	/*
1158 	 * give a number of sectors so that sec * trks * cyls
1159 	 * is <= disk_size
1160 	 */
1161 	if (cd_size(cd, flags) == 0)
1162 		return ENXIO;
1163 
1164 	return 0;
1165 }
1166 
1167 int
1168 cdsize(dev)
1169 	dev_t dev;
1170 {
1171 
1172 	return -1;
1173 }
1174 
1175 int
1176 cddump()
1177 {
1178 
1179 	/* Not implemented. */
1180 	return EINVAL;
1181 }
1182