xref: /netbsd-src/sys/dev/scsipi/cd.c (revision ae9172d6cd9432a6a1a56760d86b32c57a66c39c)
1 /*	$NetBSD: cd.c,v 1.46 1994/12/16 04:38:30 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 DIOCGDINFO:
588 		*(struct disklabel *)addr = cd->sc_dk.dk_label;
589 		return 0;
590 
591 	case DIOCGPART:
592 		((struct partinfo *)addr)->disklab = &cd->sc_dk.dk_label;
593 		((struct partinfo *)addr)->part =
594 		    &cd->sc_dk.dk_label.d_partitions[CDPART(dev)];
595 		return 0;
596 
597 	case DIOCWDINFO:
598 	case DIOCSDINFO:
599 		if ((flag & FWRITE) == 0)
600 			return EBADF;
601 		error = setdisklabel(&cd->sc_dk.dk_label,
602 		    (struct disklabel *)addr,
603 		    /*(cd->flags & CDF_BSDLABEL) ? cd->sc_dk.dk_openmask : */0,
604 		    &cd->sc_dk.dk_cpulabel);
605 		if (error == 0)
606 			cd->flags |= CDF_BSDLABEL;
607 		return error;
608 
609 	case DIOCWLABEL:
610 		return EBADF;
611 
612 	case CDIOCPLAYTRACKS: {
613 		struct ioc_play_track *args = (struct ioc_play_track *)addr;
614 		struct cd_mode_data data;
615 		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
616 			return error;
617 		data.page.audio.flags &= ~CD_PA_SOTC;
618 		data.page.audio.flags |= CD_PA_IMMED;
619 		if (error = cd_set_mode(cd, &data))
620 			return error;
621 		return cd_play_tracks(cd, args->start_track, args->start_index,
622 		    args->end_track, args->end_index);
623 	}
624 	case CDIOCPLAYMSF: {
625 		struct ioc_play_msf *args
626 		= (struct ioc_play_msf *)addr;
627 		struct cd_mode_data data;
628 		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
629 			return error;
630 		data.page.audio.flags &= ~CD_PA_SOTC;
631 		data.page.audio.flags |= CD_PA_IMMED;
632 		if (error = cd_set_mode(cd, &data))
633 			return error;
634 		return cd_play_msf(cd, args->start_m, args->start_s,
635 		    args->start_f, args->end_m, args->end_s, args->end_f);
636 	}
637 	case CDIOCPLAYBLOCKS: {
638 		struct ioc_play_blocks *args
639 		= (struct ioc_play_blocks *)addr;
640 		struct cd_mode_data data;
641 		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
642 			return error;
643 		data.page.audio.flags &= ~CD_PA_SOTC;
644 		data.page.audio.flags |= CD_PA_IMMED;
645 		if (error = cd_set_mode(cd, &data))
646 			return error;
647 		return cd_play(cd, args->blk, args->len);
648 	}
649 	case CDIOCREADSUBCHANNEL: {
650 		struct ioc_read_subchannel *args
651 		= (struct ioc_read_subchannel *)addr;
652 		struct cd_sub_channel_info data;
653 		u_int32 len = args->data_len;
654 		if (len > sizeof(data) ||
655 		    len < sizeof(struct cd_sub_channel_header))
656 			return EINVAL;
657 		if (error = cd_read_subchannel(cd, args->address_format,
658 		    args->data_format, args->track, &data, len))
659 			return error;
660 		len = min(len, ((data.header.data_len[0] << 8) +
661 		    data.header.data_len[1] +
662 		    sizeof(struct cd_sub_channel_header)));
663 		return copyout(&data, args->data, len);
664 	}
665 	case CDIOREADTOCHEADER: {
666 		struct ioc_toc_header th;
667 		if (error = cd_read_toc(cd, 0, 0, &th, sizeof(th)))
668 			return error;
669 		th.len = ntohs(th.len);
670 		bcopy(&th, addr, sizeof(th));
671 		return 0;
672 	}
673 	case CDIOREADTOCENTRYS: {
674 		struct cd_toc {
675 			struct ioc_toc_header header;
676 			struct cd_toc_entry entries[65];
677 		} data;
678 		struct ioc_read_toc_entry *te =
679 		(struct ioc_read_toc_entry *)addr;
680 		struct ioc_toc_header *th;
681 		u_int32 len = te->data_len;
682 		th = &data.header;
683 
684 		if (len > sizeof(data.entries) ||
685 		    len < sizeof(struct cd_toc_entry))
686 			return EINVAL;
687 		if (error = cd_read_toc(cd, te->address_format,
688 		    te->starting_track, (struct cd_toc_entry *)&data,
689 		    len + sizeof(struct ioc_toc_header)))
690 			return error;
691 		len = min(len, ntohs(th->len) - (sizeof(th->starting_track) +
692 		    sizeof(th->ending_track)));
693 		return copyout(data.entries, te->data, len);
694 	}
695 	case CDIOCSETPATCH: {
696 		struct ioc_patch *arg = (struct ioc_patch *)addr;
697 		struct cd_mode_data data;
698 		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
699 			return error;
700 		data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
701 		data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
702 		data.page.audio.port[2].channels = arg->patch[2];
703 		data.page.audio.port[3].channels = arg->patch[3];
704 		return cd_set_mode(cd, &data);
705 	}
706 	case CDIOCGETVOL: {
707 		struct ioc_vol *arg = (struct ioc_vol *)addr;
708 		struct cd_mode_data data;
709 		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
710 			return error;
711 		arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
712 		arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
713 		arg->vol[2] = data.page.audio.port[2].volume;
714 		arg->vol[3] = data.page.audio.port[3].volume;
715 		return 0;
716 	}
717 	case CDIOCSETVOL: {
718 		struct ioc_vol *arg = (struct ioc_vol *)addr;
719 		struct cd_mode_data data;
720 		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
721 			return error;
722 		data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
723 		data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
724 		data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1;
725 		data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
726 		data.page.audio.port[2].volume = arg->vol[2];
727 		data.page.audio.port[3].volume = arg->vol[3];
728 		return cd_set_mode(cd, &data);
729 	}
730 	case CDIOCSETMONO: {
731 		struct ioc_vol *arg = (struct ioc_vol *)addr;
732 		struct cd_mode_data data;
733 		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
734 			return error;
735 		data.page.audio.port[LEFT_PORT].channels =
736 		    LEFT_CHANNEL | RIGHT_CHANNEL | 4 | 8;
737 		data.page.audio.port[RIGHT_PORT].channels =
738 		    LEFT_CHANNEL | RIGHT_CHANNEL;
739 		data.page.audio.port[2].channels = 0;
740 		data.page.audio.port[3].channels = 0;
741 		return cd_set_mode(cd, &data);
742 	}
743 	case CDIOCSETSTEREO: {
744 		struct ioc_vol *arg = (struct ioc_vol *)addr;
745 		struct cd_mode_data data;
746 		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
747 			return error;
748 		data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
749 		data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
750 		data.page.audio.port[2].channels = 0;
751 		data.page.audio.port[3].channels = 0;
752 		return cd_set_mode(cd, &data);
753 	}
754 	case CDIOCSETMUTE: {
755 		struct ioc_vol *arg = (struct ioc_vol *)addr;
756 		struct cd_mode_data data;
757 		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
758 			return error;
759 		data.page.audio.port[LEFT_PORT].channels = 0;
760 		data.page.audio.port[RIGHT_PORT].channels = 0;
761 		data.page.audio.port[2].channels = 0;
762 		data.page.audio.port[3].channels = 0;
763 		return cd_set_mode(cd, &data);
764 	}
765 	case CDIOCSETLEFT: {
766 		struct ioc_vol *arg = (struct ioc_vol *)addr;
767 		struct cd_mode_data data;
768 		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
769 			return error;
770 		data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
771 		data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
772 		data.page.audio.port[2].channels = 0;
773 		data.page.audio.port[3].channels = 0;
774 		return cd_set_mode(cd, &data);
775 	}
776 	case CDIOCSETRIGHT: {
777 		struct ioc_vol *arg = (struct ioc_vol *)addr;
778 		struct cd_mode_data data;
779 		if (error = cd_get_mode(cd, &data, AUDIO_PAGE))
780 			return error;
781 		data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
782 		data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
783 		data.page.audio.port[2].channels = 0;
784 		data.page.audio.port[3].channels = 0;
785 		return cd_set_mode(cd, &data);
786 	}
787 	case CDIOCRESUME:
788 		return cd_pause(cd, 1);
789 	case CDIOCPAUSE:
790 		return cd_pause(cd, 0);
791 	case CDIOCSTART:
792 		return scsi_start(cd->sc_link, SSS_START, 0);
793 	case CDIOCSTOP:
794 		return scsi_start(cd->sc_link, SSS_STOP, 0);
795 	case CDIOCEJECT:
796 		return scsi_start(cd->sc_link, SSS_LOEJ, 0);
797 	case CDIOCALLOW:
798 		return scsi_prevent(cd->sc_link, PR_ALLOW, 0);
799 	case CDIOCPREVENT:
800 		return scsi_prevent(cd->sc_link, PR_PREVENT, 0);
801 	case CDIOCSETDEBUG:
802 		cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
803 		return 0;
804 	case CDIOCCLRDEBUG:
805 		cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
806 		return 0;
807 	case CDIOCRESET:
808 		return cd_reset(cd);
809 	default:
810 		if (CDPART(dev) != RAW_PART)
811 			return ENOTTY;
812 		return scsi_do_ioctl(cd->sc_link, dev, cmd, addr, flag);
813 	}
814 
815 #ifdef DIAGNOSTIC
816 	panic("cdioctl: impossible");
817 #endif
818 }
819 
820 /*
821  * Load the label information on the named device
822  * Actually fabricate a disklabel
823  *
824  * EVENTUALLY take information about different
825  * data tracks from the TOC and put it in the disklabel
826  */
827 void
828 cdgetdisklabel(cd)
829 	struct cd_data *cd;
830 {
831 
832 	if ((cd->flags & CDF_BSDLABEL) != 0)
833 		return;
834 
835 	bzero(&cd->sc_dk.dk_label, sizeof(struct disklabel));
836 	bzero(&cd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
837 
838 	cd->sc_dk.dk_label.d_secsize = cd->params.blksize;
839 	cd->sc_dk.dk_label.d_ntracks = 1;
840 	cd->sc_dk.dk_label.d_nsectors = 100;
841 	cd->sc_dk.dk_label.d_ncylinders = (cd->params.disksize / 100) + 1;
842 	cd->sc_dk.dk_label.d_secpercyl =
843 	    cd->sc_dk.dk_label.d_ntracks * cd->sc_dk.dk_label.d_nsectors;
844 
845 	strncpy(cd->sc_dk.dk_label.d_typename, "SCSI CD-ROM", 16);
846 	cd->sc_dk.dk_label.d_type = DTYPE_SCSI;
847 	strncpy(cd->sc_dk.dk_label.d_packname, "ficticious", 16);
848 	cd->sc_dk.dk_label.d_secperunit = cd->params.disksize;
849 	cd->sc_dk.dk_label.d_rpm = 300;
850 	cd->sc_dk.dk_label.d_interleave = 1;
851 	cd->sc_dk.dk_label.d_flags = D_REMOVABLE;
852 
853 	cd->sc_dk.dk_label.d_partitions[0].p_offset = 0;
854 	cd->sc_dk.dk_label.d_partitions[0].p_size =
855 	    cd->sc_dk.dk_label.d_secperunit *
856 	    (cd->sc_dk.dk_label.d_secsize / DEV_BSIZE);
857 	cd->sc_dk.dk_label.d_partitions[0].p_fstype = FS_ISO9660;
858 	cd->sc_dk.dk_label.d_npartitions = 1;
859 
860 	cd->sc_dk.dk_label.d_magic = DISKMAGIC;
861 	cd->sc_dk.dk_label.d_magic2 = DISKMAGIC;
862 	cd->sc_dk.dk_label.d_checksum = dkcksum(&cd->sc_dk.dk_label);
863 
864 	cd->flags |= CDF_BSDLABEL;
865 }
866 
867 /*
868  * Find out from the device what it's capacity is
869  */
870 u_int32
871 cd_size(cd, flags)
872 	struct cd_data *cd;
873 	int flags;
874 {
875 	struct scsi_read_cd_cap_data rdcap;
876 	struct scsi_read_cd_capacity scsi_cmd;
877 	u_int32 size, blksize;
878 	int error;
879 
880 	/*
881 	 * make up a scsi command and ask the scsi driver to do
882 	 * it for you.
883 	 */
884 	bzero(&scsi_cmd, sizeof(scsi_cmd));
885 	scsi_cmd.op_code = READ_CD_CAPACITY;
886 
887 	/*
888 	 * If the command works, interpret the result as a 4 byte
889 	 * number of blocks and a blocksize
890 	 */
891 	error = scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
892 	    sizeof(scsi_cmd), (u_char *)&rdcap, sizeof(rdcap), CDRETRIES,
893 	    20000, NULL, SCSI_DATA_IN | flags);
894 	if (error == EBUSY) {
895 		if (!(flags & SCSI_SILENT))
896 			printf("%s: waiting for drive to spin up\n",
897 			    cd->sc_dev.dv_xname);
898 		if (flags & SCSI_NOSLEEP)
899 			delay(2000000);
900 		else
901 			tsleep(cd, PRIBIO + 1, "cd_size", 2 * hz);
902 		error = scsi_scsi_cmd(cd->sc_link,
903 		    (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),
904 		    (u_char *)&rdcap, sizeof(rdcap), CDRETRIES, 20000, NULL,
905 		    SCSI_DATA_IN | flags);
906 	}
907 
908 	if (error) {
909 		if (!(flags & SCSI_SILENT))
910 			printf("%s: could not get size\n",
911 			    cd->sc_dev.dv_xname);
912 		return 0;
913 	}
914 
915 	blksize = (rdcap.length_3 << 24) + (rdcap.length_2 << 16) +
916 	    (rdcap.length_1 << 8) + rdcap.length_0;
917 	if (blksize < 512)
918 		blksize = 2048;	/* some drives lie ! */
919 	cd->params.blksize = blksize;
920 
921 	size = (rdcap.addr_3 << 24) + (rdcap.addr_2 << 16) +
922 	    (rdcap.addr_1 << 8) + rdcap.addr_0 + 1;
923 	if (size < 100)
924 		size = 400000;	/* ditto */
925 	cd->params.disksize = size;
926 
927 	return size;
928 }
929 
930 /*
931  * Get the requested page into the buffer given
932  */
933 int
934 cd_get_mode(cd, data, page)
935 	struct cd_data *cd;
936 	struct cd_mode_data *data;
937 	int page;
938 {
939 	struct scsi_mode_sense scsi_cmd;
940 	int error;
941 
942 	bzero(&scsi_cmd, sizeof(scsi_cmd));
943 	bzero(data, sizeof(*data));
944 	scsi_cmd.op_code = MODE_SENSE;
945 	scsi_cmd.page = page;
946 	scsi_cmd.length = sizeof(*data) & 0xff;
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_IN);
950 }
951 
952 /*
953  * Get the requested page into the buffer given
954  */
955 int
956 cd_set_mode(cd, data)
957 	struct cd_data *cd;
958 	struct cd_mode_data *data;
959 {
960 	struct scsi_mode_select scsi_cmd;
961 
962 	bzero(&scsi_cmd, sizeof(scsi_cmd));
963 	scsi_cmd.op_code = MODE_SELECT;
964 	scsi_cmd.byte2 |= SMS_PF;
965 	scsi_cmd.length = sizeof(*data) & 0xff;
966 	data->header.data_length = 0;
967 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
968 	    sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000,
969 	    NULL, SCSI_DATA_OUT);
970 }
971 
972 /*
973  * Get scsi driver to send a "start playing" command
974  */
975 int
976 cd_play(cd, blkno, nblks)
977 	struct cd_data *cd;
978 	int blkno, nblks;
979 {
980 	struct scsi_play scsi_cmd;
981 
982 	bzero(&scsi_cmd, sizeof(scsi_cmd));
983 	scsi_cmd.op_code = PLAY;
984 	scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
985 	scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
986 	scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
987 	scsi_cmd.blk_addr[3] = blkno & 0xff;
988 	scsi_cmd.xfer_len[0] = (nblks >> 8) & 0xff;
989 	scsi_cmd.xfer_len[1] = nblks & 0xff;
990 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
991 	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 200000, NULL, 0);
992 }
993 
994 /*
995  * Get scsi driver to send a "start playing" command
996  */
997 int
998 cd_play_big(cd, blkno, nblks)
999 	struct cd_data *cd;
1000 	int blkno, nblks;
1001 {
1002 	struct scsi_play_big scsi_cmd;
1003 
1004 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1005 	scsi_cmd.op_code = PLAY_BIG;
1006 	scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff;
1007 	scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff;
1008 	scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff;
1009 	scsi_cmd.blk_addr[3] = blkno & 0xff;
1010 	scsi_cmd.xfer_len[0] = (nblks >> 24) & 0xff;
1011 	scsi_cmd.xfer_len[1] = (nblks >> 16) & 0xff;
1012 	scsi_cmd.xfer_len[2] = (nblks >> 8) & 0xff;
1013 	scsi_cmd.xfer_len[3] = nblks & 0xff;
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 "start playing" command
1020  */
1021 int
1022 cd_play_tracks(cd, strack, sindex, etrack, eindex)
1023 	struct cd_data *cd;
1024 	int strack, sindex, etrack, eindex;
1025 {
1026 	struct scsi_play_track scsi_cmd;
1027 
1028 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1029 	scsi_cmd.op_code = PLAY_TRACK;
1030 	scsi_cmd.start_track = strack;
1031 	scsi_cmd.start_index = sindex;
1032 	scsi_cmd.end_track = etrack;
1033 	scsi_cmd.end_index = eindex;
1034 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1035 	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0);
1036 }
1037 
1038 /*
1039  * Get scsi driver to send a "play msf" command
1040  */
1041 int
1042 cd_play_msf(cd, startm, starts, startf, endm, ends, endf)
1043 	struct cd_data *cd;
1044 	int startm, starts, startf, endm, ends, endf;
1045 {
1046 	struct scsi_play_msf scsi_cmd;
1047 
1048 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1049 	scsi_cmd.op_code = PLAY_MSF;
1050 	scsi_cmd.start_m = startm;
1051 	scsi_cmd.start_s = starts;
1052 	scsi_cmd.start_f = startf;
1053 	scsi_cmd.end_m = endm;
1054 	scsi_cmd.end_s = ends;
1055 	scsi_cmd.end_f = endf;
1056 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1057 	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
1058 }
1059 
1060 /*
1061  * Get scsi driver to send a "start up" command
1062  */
1063 int
1064 cd_pause(cd, go)
1065 	struct cd_data *cd;
1066 	int go;
1067 {
1068 	struct scsi_pause scsi_cmd;
1069 
1070 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1071 	scsi_cmd.op_code = PAUSE;
1072 	scsi_cmd.resume = go;
1073 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1074 	    sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0);
1075 }
1076 
1077 /*
1078  * Get scsi driver to send a "RESET" command
1079  */
1080 int
1081 cd_reset(cd)
1082 	struct cd_data *cd;
1083 {
1084 
1085 	return scsi_scsi_cmd(cd->sc_link, 0, 0, 0, 0, CDRETRIES, 2000, NULL,
1086 	    SCSI_RESET);
1087 }
1088 
1089 /*
1090  * Read subchannel
1091  */
1092 int
1093 cd_read_subchannel(cd, mode, format, track, data, len)
1094 	struct cd_data *cd;
1095 	int mode, format, len;
1096 	struct cd_sub_channel_info *data;
1097 {
1098 	struct scsi_read_subchannel scsi_cmd;
1099 
1100 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1101 	scsi_cmd.op_code = READ_SUBCHANNEL;
1102 	if (mode == CD_MSF_FORMAT)
1103 		scsi_cmd.byte2 |= CD_MSF;
1104 	scsi_cmd.byte3 = SRS_SUBQ;
1105 	scsi_cmd.subchan_format = format;
1106 	scsi_cmd.track = track;
1107 	scsi_cmd.data_len[0] = (len) >> 8;
1108 	scsi_cmd.data_len[1] = (len) & 0xff;
1109 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1110 	    sizeof(struct scsi_read_subchannel), (u_char *)data, len,
1111 	    CDRETRIES, 5000, NULL, SCSI_DATA_IN);
1112 }
1113 
1114 /*
1115  * Read table of contents
1116  */
1117 int
1118 cd_read_toc(cd, mode, start, data, len)
1119 	struct cd_data *cd;
1120 	int mode, start, len;
1121 	struct cd_toc_entry *data;
1122 {
1123 	struct scsi_read_toc scsi_cmd;
1124 	int ntoc;
1125 
1126 	bzero(&scsi_cmd, sizeof(scsi_cmd));
1127 	/*if (len!=sizeof(struct ioc_toc_header))
1128 	 * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
1129 	 * else */
1130 	ntoc = len;
1131 	scsi_cmd.op_code = READ_TOC;
1132 	if (mode == CD_MSF_FORMAT)
1133 		scsi_cmd.byte2 |= CD_MSF;
1134 	scsi_cmd.from_track = start;
1135 	scsi_cmd.data_len[0] = (ntoc) >> 8;
1136 	scsi_cmd.data_len[1] = (ntoc) & 0xff;
1137 	return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd,
1138 	    sizeof(struct scsi_read_toc), (u_char *)data, len, CDRETRIES,
1139 	    5000, NULL, SCSI_DATA_IN);
1140 }
1141 
1142 #define b2tol(a)	(((unsigned)(a##_1) << 8) + (unsigned)a##_0)
1143 
1144 /*
1145  * Get the scsi driver to send a full inquiry to the device and use the
1146  * results to fill out the disk parameter structure.
1147  */
1148 int
1149 cd_get_parms(cd, flags)
1150 	struct cd_data *cd;
1151 	int flags;
1152 {
1153 
1154 	/*
1155 	 * give a number of sectors so that sec * trks * cyls
1156 	 * is <= disk_size
1157 	 */
1158 	if (cd_size(cd, flags) == 0)
1159 		return ENXIO;
1160 
1161 	return 0;
1162 }
1163 
1164 int
1165 cdsize(dev)
1166 	dev_t dev;
1167 {
1168 
1169 	return -1;
1170 }
1171 
1172 int
1173 cddump()
1174 {
1175 
1176 	/* Not implemented. */
1177 	return EINVAL;
1178 }
1179