cd.c revision 1.18.2.2 1 /*
2 * Written by Julian Elischer (julian (at) tfs.com)
3 * for TRW Financial Systems for use under the MACH(2.5) operating system.
4 *
5 * TRW Financial Systems, in accordance with their agreement with Carnegie
6 * Mellon University, makes this software available to CMU to distribute
7 * or use in any manner that they see fit as long as this message is kept with
8 * the software. For this reason TFS also grants any other persons or
9 * organisations permission to use or modify this software.
10 *
11 * TFS supplies this software to be publicly redistributed
12 * on the understanding that TFS is not responsible for the correct
13 * functioning of this software in any circumstances.
14 *
15 * Ported to run under 386BSD by Julian Elischer (julian (at) tfs.com) Sept 1992
16 *
17 * $Id: cd.c,v 1.18.2.2 1993/11/24 05:02:56 mycroft Exp $
18 */
19
20 #define SPLCD splbio
21 #define ESUCCESS 0
22 #include <cd.h>
23 #include <sys/types.h>
24 #include <sys/param.h>
25 #include <sys/dkbad.h>
26 #include <sys/systm.h>
27 #include <sys/conf.h>
28 #include <sys/file.h>
29 #include <sys/stat.h>
30 #include <sys/ioctl.h>
31 #include <sys/buf.h>
32 #include <sys/uio.h>
33 #include <sys/malloc.h>
34 #include <sys/cdio.h>
35
36 #include <sys/errno.h>
37 #include <sys/disklabel.h>
38 #include <scsi/scsi_all.h>
39 #include <scsi/scsi_cd.h>
40 #include <scsi/scsi_disk.h> /* rw_big and start_stop come from there */
41 #include <scsi/scsiconf.h>
42
43 int32 cdstrats, cdqueues;
44
45 #include <ddb.h>
46 #if NDDB > 0
47 int Debugger();
48 #else /* NDDB > 0 */
49 #define Debugger()
50 #endif /* NDDB > 0 */
51
52 #define PAGESIZ 4096
53 #define SECSIZE 2048 /* XXX */ /* default only */
54 #define CDOUTSTANDING 2
55 #define CDRETRIES 1
56
57 #define UNITSHIFT 3
58 #define PARTITION(z) (minor(z) & 0x07)
59 #define RAW_PART 3
60 #define UNIT(z) ( (minor(z) >> UNITSHIFT) )
61
62 extern int hz;
63 errval cdstrategy();
64
65 void cdstart();
66 struct scsi_device cd_switch =
67 {
68 NULL, /* use default error handler */
69 cdstart, /* we have a queue, which is started by this */
70 NULL, /* we do not have an async handler */
71 NULL, /* use default 'done' routine */
72 "cd", /* we are to be refered to by this name */
73 0, /* no device specific flags */
74 0, 0 /* spares not used */
75 };
76
77 struct cd_data {
78 u_int32 flags;
79 #define CDINIT 0x04 /* device has been init'd */
80 struct scsi_link *sc_link; /* address of scsi low level switch */
81 u_int32 cmdscount; /* cmds allowed outstanding by board */
82 struct cd_parms {
83 u_int32 blksize;
84 u_long disksize; /* total number sectors */
85 } params;
86 struct disklabel disklabel;
87 u_int32 partflags[MAXPARTITIONS]; /* per partition flags */
88 #define CDOPEN 0x01
89 u_int32 openparts; /* one bit for each open partition */
90 u_int32 xfer_block_wait;
91 struct buf buf_queue;
92 };
93
94 #define CD_STOP 0
95 #define CD_START 1
96 #define CD_EJECT -2
97
98 struct cd_driver {
99 u_int32 size;
100 struct cd_data **cd_data;
101 } cd_driver;
102
103 static u_int32 next_cd_unit = 0;
104
105 /*
106 * The routine called by the low level scsi routine when it discovers
107 * A device suitable for this driver
108 */
109 int
110 cdattach(sc_link)
111 struct scsi_link *sc_link;
112 {
113 u_int32 unit, i;
114 unsigned char *tbl;
115 struct cd_data *cd, **cdrealloc;
116 struct cd_parms *dp;
117
118 SC_DEBUG(sc_link, SDEV_DB2, ("cdattach "));
119
120 /*
121 * Fill out any more info in the
122 * Link structure that we can
123 */
124 unit = next_cd_unit++;
125 sc_link->device = &cd_switch;
126 sc_link->dev_unit = unit;
127 /*
128 * allocate the resources for another drive
129 * if we have already allocate a cd_data pointer we must
130 * copy the old pointers into a new region that is
131 * larger and release the old region, aka realloc
132 */
133 /* XXX
134 * This if will always be true for now, but future code may
135 * preallocate more units to reduce overhead. This would be
136 * done by changing the malloc to be (next_cd_unit * x) and
137 * the cd_driver.size++ to be +x
138 */
139 if (unit >= cd_driver.size) {
140 cdrealloc =
141 malloc(sizeof(cd_driver.cd_data) * next_cd_unit,
142 M_DEVBUF, M_NOWAIT);
143 if (!cdrealloc) {
144 printf("cd%d: malloc failed for cdrealloc\n", unit);
145 return (0);
146 }
147 /* Make sure we have something to copy before we copy it */
148 bzero(cdrealloc, sizeof(cd_driver.cd_data) * next_cd_unit);
149 if (cd_driver.size) {
150 bcopy(cd_driver.cd_data, cdrealloc,
151 sizeof(cd_driver.cd_data) * cd_driver.size);
152 free(cd_driver.cd_data, M_DEVBUF);
153 }
154 cd_driver.cd_data = cdrealloc;
155 cd_driver.cd_data[unit] = NULL;
156 cd_driver.size++;
157 }
158 if (cd_driver.cd_data[unit]) {
159 printf("cd%d: Already has storage!\n", unit);
160 return (0);
161 }
162 /*
163 * allocate the per drive data area
164 */
165 cd = cd_driver.cd_data[unit] =
166 malloc(sizeof(struct cd_data), M_DEVBUF, M_NOWAIT);
167 if (!cd) {
168 printf("cd%d: malloc failed for cd_data\n", unit);
169 return (0);
170 }
171 bzero(cd, sizeof(struct cd_data));
172 dp = &(cd->params);
173 /*
174 * Store information needed to contact our base driver
175 */
176 cd->sc_link = sc_link;
177 /* only allow 1 outstanding command on tapes */
178 sc_link->opennings = cd->cmdscount = CDOUTSTANDING;
179
180 /*
181 * Use the subdriver to request information regarding
182 * the drive. We cannot use interrupts yet, so the
183 * request must specify this.
184 */
185 cd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK);
186 if (dp->disksize) {
187 printf("cd%d: cd present.[%d x %d byte records]\n",
188 unit,
189 cd->params.disksize,
190 cd->params.blksize);
191 } else {
192 printf("cd%d: drive empty\n", unit);
193 }
194 cd->flags |= CDINIT;
195 return (1);
196 }
197
198 /*
199 * open the device. Make sure the partition info is a up-to-date as can be.
200 */
201 errval
202 cdopen(dev)
203 {
204 errval errcode = 0;
205 u_int32 unit, part;
206 struct cd_parms cd_parms;
207 struct cd_data *cd;
208 struct scsi_link *sc_link;
209 u_int32 heldflags;
210
211 unit = UNIT(dev);
212 part = PARTITION(dev);
213
214 /*
215 * Check the unit is legal
216 */
217 if (unit >= cd_driver.size) {
218 return (ENXIO);
219 }
220 cd = cd_driver.cd_data[unit];
221 /*
222 * Make sure the device has been initialised
223 */
224 if ((cd == NULL) || (!(cd->flags & CDINIT)))
225 return (ENXIO);
226
227 sc_link = cd->sc_link;
228 SC_DEBUG(sc_link, SDEV_DB1,
229 ("cdopen: dev=0x%x (unit %d (of %d),partition %d)\n",
230 dev, unit, cd_driver.size, part));
231 /*
232 * If it's been invalidated, and not everybody has closed it then
233 * forbid re-entry. (may have changed media)
234 */
235 if ((!(sc_link->flags & SDEV_MEDIA_LOADED))
236 && (cd->openparts))
237 return (ENXIO);
238
239 /*
240 * Check that it is still responding and ok.
241 * if the media has been changed this will result in a
242 * "unit attention" error which the error code will
243 * disregard because the SDEV_MEDIA_LOADED flag is not yet set
244 */
245 scsi_test_unit_ready(sc_link, SCSI_SILENT);
246
247 /*
248 * Next time actually take notice of error returns
249 */
250 sc_link->flags |= SDEV_OPEN; /* unit attn errors are now errors */
251 if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
252 SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
253 errcode = ENXIO;
254 goto bad;
255 }
256 SC_DEBUG(sc_link, SDEV_DB3, ("Device present\n"));
257 /*
258 * In case it is a funny one, tell it to start
259 * not needed for some drives
260 */
261 scsi_start_unit(sc_link, CD_START);
262 scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT);
263 SC_DEBUG(sc_link, SDEV_DB3, ("started "));
264 /*
265 * Load the physical device parameters
266 */
267 if (cd_get_parms(unit, 0)) {
268 errcode = ENXIO;
269 goto bad;
270 }
271 SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
272 /*
273 * Make up some partition information
274 */
275 cdgetdisklabel(unit);
276 SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated "));
277 /*
278 * Check the partition is legal
279 */
280 if ((part >= cd->disklabel.d_npartitions)
281 && (part != RAW_PART)) {
282 SC_DEBUG(sc_link, SDEV_DB3, ("partition %d > %d\n", part
283 ,cd->disklabel.d_npartitions));
284 errcode = ENXIO;
285 goto bad;
286 }
287 /*
288 * Check that the partition exists
289 */
290 if ((cd->disklabel.d_partitions[part].p_fstype == FS_UNUSED)
291 && (part != RAW_PART)) {
292 SC_DEBUG(sc_link, SDEV_DB3, ("part %d type UNUSED\n", part));
293 errcode = ENXIO;
294 goto bad;
295 }
296 cd->partflags[part] |= CDOPEN;
297 cd->openparts |= (1 << part);
298 SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
299 sc_link->flags |= SDEV_MEDIA_LOADED;
300 return (0);
301 bad:
302
303 /*
304 * if we would have been the only open
305 * then leave things back as they were
306 */
307 if (!(cd->openparts)) {
308 sc_link->flags &= ~SDEV_OPEN;
309 scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
310 }
311 return (errcode);
312 }
313
314 /*
315 * close the device.. only called if we are the LAST
316 * occurence of an open device
317 */
318 errval
319 cdclose(dev)
320 dev_t dev;
321 {
322 u_int8 unit, part;
323 u_int32 old_priority;
324 struct cd_data *cd;
325 struct scsi_link *sc_link;
326
327 unit = UNIT(dev);
328 part = PARTITION(dev);
329 cd = cd_driver.cd_data[unit];
330 sc_link = cd->sc_link;
331 SC_DEBUG(sc_link, SDEV_DB2, ("cd%d: closing part %d\n", unit, part));
332 cd->partflags[part] &= ~CDOPEN;
333 cd->openparts &= ~(1 << part);
334
335 /*
336 * If we were the last open of the entire device, release it.
337 */
338 if (!(cd->openparts)) {
339 scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
340 cd->sc_link->flags &= ~SDEV_OPEN;
341 }
342 return (0);
343 }
344
345 /*
346 * trim the size of the transfer if needed,
347 * called by physio
348 * basically the smaller of our max and the scsi driver's
349 * minphys (note we have no max ourselves)
350 *
351 * Trim buffer length if buffer-size is bigger than page size
352 */
353 void
354 cdminphys(bp)
355 struct buf *bp;
356 {
357 (*(cd_driver.cd_data[UNIT(bp->b_dev)]->sc_link->adapter->scsi_minphys)) (bp);
358 }
359
360 /*
361 * Actually translate the requested transfer into one the physical driver can
362 * understand. The transfer is described by a buf and will include only one
363 * physical transfer.
364 */
365 errval
366 cdstrategy(bp)
367 struct buf *bp;
368 {
369 struct buf *dp;
370 u_int32 opri;
371 u_int32 unit = UNIT((bp->b_dev));
372 struct cd_data *cd = cd_driver.cd_data[unit];
373
374 cdstrats++;
375 SC_DEBUG(cd->sc_link, SDEV_DB2, ("\ncdstrategy "));
376 SC_DEBUG(cd->sc_link, SDEV_DB1, ("cd%d: %d bytes @ blk%d\n",
377 unit, bp->b_bcount, bp->b_blkno));
378 cdminphys(bp);
379 /*
380 * If the device has been made invalid, error out
381 * maybe the media changed
382 */
383 if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED)) {
384 bp->b_error = EIO;
385 goto bad;
386 }
387 /*
388 * can't ever write to a CD
389 */
390 if ((bp->b_flags & B_READ) == 0) {
391 bp->b_error = EROFS;
392 goto bad;
393 }
394 /*
395 * If it's a null transfer, return immediatly
396 */
397 if (bp->b_bcount == 0) {
398 goto done;
399 }
400 /*
401 * Decide which unit and partition we are talking about
402 */
403 if (PARTITION(bp->b_dev) != RAW_PART) {
404 /*
405 * do bounds checking, adjust transfer. if error, process.
406 * if end of partition, just return
407 */
408 if (bounds_check_with_label(bp, &cd->disklabel, 1) <= 0)
409 goto done;
410 /* otherwise, process transfer request */
411 }
412 opri = SPLCD();
413 dp = &cd->buf_queue;
414
415 /*
416 * Place it in the queue of disk activities for this disk
417 */
418 disksort(dp, bp);
419
420 /*
421 * Tell the device to get going on the transfer if it's
422 * not doing anything, otherwise just wait for completion
423 */
424 cdstart(unit);
425
426 splx(opri);
427 return;
428 bad:
429 bp->b_flags |= B_ERROR;
430 done:
431
432 /*
433 * Correctly set the buf to indicate a completed xfer
434 */
435 bp->b_resid = bp->b_bcount;
436 biodone(bp);
437 return (0);
438 }
439
440 /*
441 * cdstart looks to see if there is a buf waiting for the device
442 * and that the device is not already busy. If both are true,
443 * It deques the buf and creates a scsi command to perform the
444 * transfer in the buf. The transfer request will call scsi_done
445 * on completion, which will in turn call this routine again
446 * so that the next queued transfer is performed.
447 * The bufs are queued by the strategy routine (cdstrategy)
448 *
449 * This routine is also called after other non-queued requests
450 * have been made of the scsi driver, to ensure that the queue
451 * continues to be drained.
452 *
453 * must be called at the correct (highish) spl level
454 * cdstart() is called at SPLCD from cdstrategy and scsi_done
455 */
456 void
457 cdstart(unit)
458 u_int32 unit;
459 {
460 register struct buf *bp = 0;
461 register struct buf *dp;
462 struct scsi_rw_big cmd;
463 u_int32 blkno, nblk;
464 struct partition *p;
465 struct cd_data *cd = cd_driver.cd_data[unit];
466 struct scsi_link *sc_link = cd->sc_link;
467
468 SC_DEBUG(sc_link, SDEV_DB2, ("cdstart%d ", unit));
469 /*
470 * See if there is a buf to do and we are not already
471 * doing one
472 */
473 if (!sc_link->opennings) {
474 return; /* no room for us, unit already underway */
475 }
476 if (sc_link->flags & SDEV_WAITING) { /* is room, but a special waits */
477 return; /* give the special that's waiting a chance to run */
478 }
479 dp = &cd->buf_queue;
480 if ((bp = dp->b_actf) != NULL) { /* yes, an assign */
481 dp->b_actf = bp->av_forw;
482 } else {
483 return;
484 }
485 /*
486 * Should reject all queued entries if SDEV_MEDIA_LOADED is not true.
487 */
488 if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
489 goto bad; /* no I/O.. media changed or something */
490 }
491 /*
492 * We have a buf, now we should make a command
493 *
494 * First, translate the block to absolute and put it in terms of the
495 * logical blocksize of the device. Really a bit silly until we have
496 * real partitions, but.
497 */
498 blkno = bp->b_blkno / (cd->params.blksize / 512);
499 if (PARTITION(bp->b_dev) != RAW_PART) {
500 p = cd->disklabel.d_partitions + PARTITION(bp->b_dev);
501 blkno += p->p_offset;
502 }
503 nblk = (bp->b_bcount + (cd->params.blksize - 1)) / (cd->params.blksize);
504 /* what if something asks for 512 bytes not on a 2k boundary? *//*XXX */
505
506 /*
507 * Fill out the scsi command
508 */
509 bzero(&cmd, sizeof(cmd));
510 cmd.op_code = READ_BIG;
511 cmd.addr_3 = (blkno & 0xff000000) >> 24;
512 cmd.addr_2 = (blkno & 0xff0000) >> 16;
513 cmd.addr_1 = (blkno & 0xff00) >> 8;
514 cmd.addr_0 = blkno & 0xff;
515 cmd.length2 = (nblk & 0xff00) >> 8;
516 cmd.length1 = (nblk & 0xff);
517
518 /*
519 * Call the routine that chats with the adapter.
520 * Note: we cannot sleep as we may be an interrupt
521 */
522 if (scsi_scsi_cmd(sc_link,
523 (struct scsi_generic *) &cmd,
524 sizeof(cmd),
525 (u_char *) bp->b_un.b_addr,
526 bp->b_bcount,
527 CDRETRIES,
528 30000,
529 bp,
530 SCSI_NOSLEEP | ((bp->b_flags & B_READ) ?
531 SCSI_DATA_IN : SCSI_DATA_OUT))
532 != SUCCESSFULLY_QUEUED) {
533 bad:
534 printf("cd%d: oops not queued", unit);
535 bp->b_error = EIO;
536 bp->b_flags |= B_ERROR;
537 biodone(bp);
538 return;
539 }
540 cdqueues++;
541 }
542
543 /*
544 * Perform special action on behalf of the user.
545 * Knows about the internals of this device
546 */
547 errval
548 cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
549 {
550 errval error = 0;
551 u_int32 opri;
552 u_int8 unit, part;
553 register struct cd_data *cd;
554
555 /*
556 * Find the device that the user is talking about
557 */
558 unit = UNIT(dev);
559 part = PARTITION(dev);
560 cd = cd_driver.cd_data[unit];
561 SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%x ", cmd));
562
563 /*
564 * If the device is not valid.. abandon ship
565 */
566 if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED))
567 return (EIO);
568 switch (cmd) {
569
570 case DIOCSBAD:
571 error = EINVAL;
572 break;
573
574 case DIOCGDINFO:
575 *(struct disklabel *) addr = cd->disklabel;
576 break;
577
578 case DIOCGPART:
579 ((struct partinfo *) addr)->disklab = &cd->disklabel;
580 ((struct partinfo *) addr)->part =
581 &cd->disklabel.d_partitions[PARTITION(dev)];
582 break;
583
584 /*
585 * a bit silly, but someone might want to test something on a
586 * section of cdrom.
587 */
588 case DIOCWDINFO:
589 case DIOCSDINFO:
590 if ((flag & FWRITE) == 0)
591 error = EBADF;
592 else
593 error = setdisklabel(&cd->disklabel,
594 (struct disklabel *) addr,
595 0,
596 0);
597 if (error == 0)
598 break;
599
600 case DIOCWLABEL:
601 error = EBADF;
602 break;
603
604 case CDIOCPLAYTRACKS:
605 {
606 struct ioc_play_track *args
607 = (struct ioc_play_track *) addr;
608 struct cd_mode_data data;
609 if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
610 break;
611 data.page.audio.flags &= ~CD_PA_SOTC;
612 data.page.audio.flags |= CD_PA_IMMED;
613 if (error = cd_set_mode(unit, &data))
614 break;
615 return (cd_play_tracks(unit
616 ,args->start_track
617 ,args->start_index
618 ,args->end_track
619 ,args->end_index
620 ));
621 }
622 break;
623 case CDIOCPLAYMSF:
624 {
625 struct ioc_play_msf *args
626 = (struct ioc_play_msf *) addr;
627 struct cd_mode_data data;
628 if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
629 break;
630 data.page.audio.flags &= ~CD_PA_SOTC;
631 data.page.audio.flags |= CD_PA_IMMED;
632 if (error = cd_set_mode(unit, &data))
633 break;
634 return (cd_play_msf(unit
635 ,args->start_m
636 ,args->start_s
637 ,args->start_f
638 ,args->end_m
639 ,args->end_s
640 ,args->end_f
641 ));
642 }
643 break;
644 case CDIOCPLAYBLOCKS:
645 {
646 struct ioc_play_blocks *args
647 = (struct ioc_play_blocks *) addr;
648 struct cd_mode_data data;
649 if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
650 break;
651 data.page.audio.flags &= ~CD_PA_SOTC;
652 data.page.audio.flags |= CD_PA_IMMED;
653 if (error = cd_set_mode(unit, &data))
654 break;
655 return (cd_play(unit, args->blk, args->len));
656
657 }
658 break;
659 case CDIOCREADSUBCHANNEL:
660 {
661 struct ioc_read_subchannel *args
662 = (struct ioc_read_subchannel *) addr;
663 struct cd_sub_channel_info data;
664 u_int32 len = args->data_len;
665 if (len > sizeof(data) ||
666 len < sizeof(struct cd_sub_channel_header)) {
667 error = EINVAL;
668 break;
669 }
670 if (error = cd_read_subchannel(unit, args->address_format,
671 args->data_format, args->track, &data, len)) {
672 break;
673 }
674 len = MIN(len, ((data.header.data_len[0] << 8) + data.header.data_len[1] +
675 sizeof(struct cd_sub_channel_header)));
676 if (copyout(&data, args->data, len) != 0) {
677 error = EFAULT;
678 }
679 }
680 break;
681 case CDIOREADTOCHEADER:
682 {
683 struct ioc_toc_header th;
684 if (error = cd_read_toc(unit, 0, 0, &th, sizeof(th)))
685 break;
686 th.len = (th.len & 0xff) << 8 + ((th.len >> 8) & 0xff);
687 bcopy(&th, addr, sizeof(th));
688 }
689 break;
690 case CDIOREADTOCENTRYS:
691 {
692 struct ioc_read_toc_entry *te =
693 (struct ioc_read_toc_entry *) addr;
694 struct cd_toc_entry data[65];
695 struct ioc_toc_header *th;
696 u_int32 len = te->data_len;
697 th = (struct ioc_toc_header *) data;
698
699 if (len > sizeof(data) || len < sizeof(struct cd_toc_entry)) {
700 error = EINVAL;
701 break;
702 }
703 if (error = cd_read_toc(unit, te->address_format,
704 te->starting_track,
705 data,
706 len))
707 break;
708 len = MIN(len, ((((th->len & 0xff) << 8) + ((th->len >> 8))) +
709 sizeof(*th)));
710 if (copyout(th, te->data, len) != 0) {
711 error = EFAULT;
712 }
713 }
714 break;
715 case CDIOCSETPATCH:
716 {
717 struct ioc_patch *arg = (struct ioc_patch *) addr;
718 struct cd_mode_data data;
719 if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
720 break;
721 data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
722 data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
723 data.page.audio.port[2].channels = arg->patch[2];
724 data.page.audio.port[3].channels = arg->patch[3];
725 if (error = cd_set_mode(unit, &data))
726 break; /* eh? */
727 }
728 break;
729 case CDIOCGETVOL:
730 {
731 struct ioc_vol *arg = (struct ioc_vol *) addr;
732 struct cd_mode_data data;
733 if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
734 break;
735 arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
736 arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
737 arg->vol[2] = data.page.audio.port[2].volume;
738 arg->vol[3] = data.page.audio.port[3].volume;
739 }
740 break;
741 case CDIOCSETVOL:
742 {
743 struct ioc_vol *arg = (struct ioc_vol *) addr;
744 struct cd_mode_data data;
745 if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
746 break;
747 data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
748 data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
749 data.page.audio.port[2].volume = arg->vol[2];
750 data.page.audio.port[3].volume = arg->vol[3];
751 if (error = cd_set_mode(unit, &data))
752 break;
753 }
754 break;
755 case CDIOCSETMONO:
756 {
757 struct ioc_vol *arg = (struct ioc_vol *) addr;
758 struct cd_mode_data data;
759 if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
760 break;
761 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL | 4 | 8;
762 data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL;
763 data.page.audio.port[2].channels = 0;
764 data.page.audio.port[3].channels = 0;
765 if (error = cd_set_mode(unit, &data))
766 break;
767 }
768 break;
769 case CDIOCSETSTERIO:
770 {
771 struct ioc_vol *arg = (struct ioc_vol *) addr;
772 struct cd_mode_data data;
773 if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
774 break;
775 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
776 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
777 data.page.audio.port[2].channels = 0;
778 data.page.audio.port[3].channels = 0;
779 if (error = cd_set_mode(unit, &data))
780 break;
781 }
782 break;
783 case CDIOCSETMUTE:
784 {
785 struct ioc_vol *arg = (struct ioc_vol *) addr;
786 struct cd_mode_data data;
787 if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
788 break;
789 data.page.audio.port[LEFT_PORT].channels = 0;
790 data.page.audio.port[RIGHT_PORT].channels = 0;
791 data.page.audio.port[2].channels = 0;
792 data.page.audio.port[3].channels = 0;
793 if (error = cd_set_mode(unit, &data))
794 break;
795 }
796 break;
797 case CDIOCSETLEFT:
798 {
799 struct ioc_vol *arg = (struct ioc_vol *) addr;
800 struct cd_mode_data data;
801 if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
802 break;
803 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
804 data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
805 data.page.audio.port[2].channels = 0;
806 data.page.audio.port[3].channels = 0;
807 if (error = cd_set_mode(unit, &data))
808 break;
809 }
810 break;
811 case CDIOCSETRIGHT:
812 {
813 struct ioc_vol *arg = (struct ioc_vol *) addr;
814 struct cd_mode_data data;
815 if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
816 break;
817 data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
818 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
819 data.page.audio.port[2].channels = 0;
820 data.page.audio.port[3].channels = 0;
821 if (error = cd_set_mode(unit, &data))
822 break;
823 }
824 break;
825 case CDIOCRESUME:
826 error = cd_pause(unit, 1);
827 break;
828 case CDIOCPAUSE:
829 error = cd_pause(unit, 0);
830 break;
831 case CDIOCSTART:
832 error = scsi_start_unit(cd->sc_link, 0);
833 break;
834 case CDIOCSTOP:
835 error = scsi_start_unit(cd->sc_link, 0);
836 break;
837 case CDIOCEJECT:
838 error = scsi_start_unit(cd->sc_link, 0);
839 break;
840 case CDIOCSETDEBUG:
841 cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
842 break;
843 case CDIOCCLRDEBUG:
844 cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
845 break;
846 case CDIOCRESET:
847 return (cd_reset(unit));
848 break;
849 default:
850 if(part == RAW_PART)
851 error = scsi_do_ioctl(cd->sc_link,cmd,addr,flag);
852 else
853 error = ENOTTY;
854 break;
855 }
856 return (error);
857 }
858
859 /*
860 * Load the label information on the named device
861 * Actually fabricate a disklabel
862 *
863 * EVENTUALLY take information about different
864 * data tracks from the TOC and put it in the disklabel
865 */
866 errval
867 cdgetdisklabel(unit)
868 u_int8 unit;
869 {
870 /*unsigned int n, m; */
871 char *errstring;
872 struct cd_data *cd;
873
874 cd = cd_driver.cd_data[unit];
875
876 bzero(&cd->disklabel, sizeof(struct disklabel));
877 /*
878 * make partition 0 the whole disk
879 */
880 strncpy(cd->disklabel.d_typename, "scsi cd_rom", 16);
881 strncpy(cd->disklabel.d_packname, "ficticious", 16);
882 cd->disklabel.d_secsize = cd->params.blksize; /* as long as it's not 0 */
883 cd->disklabel.d_nsectors = 100;
884 cd->disklabel.d_ntracks = 1;
885 cd->disklabel.d_ncylinders = (cd->params.disksize / 100) + 1;
886 cd->disklabel.d_secpercyl = 100;
887 cd->disklabel.d_secperunit = cd->params.disksize;
888 cd->disklabel.d_rpm = 300;
889 cd->disklabel.d_interleave = 1;
890 cd->disklabel.d_flags = D_REMOVABLE;
891
892 /*
893 * remember that comparisons with the partition are done
894 * assuming the blocks are 512 bytes so fudge it.
895 */
896 cd->disklabel.d_npartitions = 1;
897 cd->disklabel.d_partitions[0].p_offset = 0;
898 cd->disklabel.d_partitions[0].p_size
899 = cd->params.disksize * (cd->params.blksize / 512);
900 cd->disklabel.d_partitions[0].p_fstype = 9;
901
902 cd->disklabel.d_magic = DISKMAGIC;
903 cd->disklabel.d_magic2 = DISKMAGIC;
904 cd->disklabel.d_checksum = dkcksum(&(cd->disklabel));
905
906 /*
907 * Signal to other users and routines that we now have a
908 * disklabel that represents the media (maybe)
909 */
910 return (ESUCCESS);
911 }
912
913 /*
914 * Find out from the device what it's capacity is
915 */
916 u_int32
917 cd_size(unit, flags)
918 {
919 struct scsi_read_cd_cap_data rdcap;
920 struct scsi_read_cd_capacity scsi_cmd;
921 u_int32 size;
922 u_int32 blksize;
923 struct cd_data *cd = cd_driver.cd_data[unit];
924
925 /*
926 * make up a scsi command and ask the scsi driver to do
927 * it for you.
928 */
929 bzero(&scsi_cmd, sizeof(scsi_cmd));
930 scsi_cmd.op_code = READ_CD_CAPACITY;
931
932 /*
933 * If the command works, interpret the result as a 4 byte
934 * number of blocks and a blocksize
935 */
936 if (scsi_scsi_cmd(cd->sc_link,
937 (struct scsi_generic *) &scsi_cmd,
938 sizeof(scsi_cmd),
939 (u_char *) & rdcap,
940 sizeof(rdcap),
941 CDRETRIES,
942 20000, /* might be a disk-changer */
943 NULL,
944 SCSI_DATA_IN | flags) != 0) {
945 printf("cd%d: could not get size\n", unit);
946 return (0);
947 } else {
948 size = rdcap.addr_0 + 1;
949 size += rdcap.addr_1 << 8;
950 size += rdcap.addr_2 << 16;
951 size += rdcap.addr_3 << 24;
952 blksize = rdcap.length_0;
953 blksize += rdcap.length_1 << 8;
954 blksize += rdcap.length_2 << 16;
955 blksize += rdcap.length_3 << 24;
956 }
957 if (blksize < 512)
958 blksize = 2048; /* some drives lie ! */
959 if (size < 100)
960 size = 400000; /* ditto */
961 SC_DEBUG(cd->sc_link, SDEV_DB3, ("cd%d: %d %d byte blocks\n"
962 ,unit, size, blksize));
963 cd->params.disksize = size;
964 cd->params.blksize = blksize;
965 return (size);
966 }
967
968 /*
969 * Get the requested page into the buffer given
970 */
971 errval
972 cd_get_mode(unit, data, page)
973 u_int32 unit;
974 struct cd_mode_data *data;
975 u_int32 page;
976 {
977 struct scsi_mode_sense scsi_cmd;
978 errval retval;
979
980 bzero(&scsi_cmd, sizeof(scsi_cmd));
981 bzero(data, sizeof(*data));
982 scsi_cmd.op_code = MODE_SENSE;
983 scsi_cmd.page = page;
984 scsi_cmd.length = sizeof(*data) & 0xff;
985 retval = scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
986 (struct scsi_generic *) &scsi_cmd,
987 sizeof(scsi_cmd),
988 (u_char *) data,
989 sizeof(*data),
990 CDRETRIES,
991 20000, /* should be immed */
992 NULL,
993 SCSI_DATA_IN);
994 return (retval);
995 }
996
997 /*
998 * Get the requested page into the buffer given
999 */
1000 errval
1001 cd_set_mode(unit, data)
1002 u_int32 unit;
1003 struct cd_mode_data *data;
1004 {
1005 struct scsi_mode_select scsi_cmd;
1006
1007 bzero(&scsi_cmd, sizeof(scsi_cmd));
1008 scsi_cmd.op_code = MODE_SELECT;
1009 scsi_cmd.byte2 |= SMS_PF;
1010 scsi_cmd.length = sizeof(*data) & 0xff;
1011 data->header.data_length = 0;
1012 return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1013 (struct scsi_generic *) &scsi_cmd,
1014 sizeof(scsi_cmd),
1015 (u_char *) data,
1016 sizeof(*data),
1017 CDRETRIES,
1018 20000, /* should be immed */
1019 NULL,
1020 SCSI_DATA_OUT));
1021 }
1022
1023 /*
1024 * Get scsi driver to send a "start playing" command
1025 */
1026 errval
1027 cd_play(unit, blk, len)
1028 u_int32 unit, blk, len;
1029 {
1030 struct scsi_play scsi_cmd;
1031 errval retval;
1032
1033 bzero(&scsi_cmd, sizeof(scsi_cmd));
1034 scsi_cmd.op_code = PLAY;
1035 scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
1036 scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
1037 scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
1038 scsi_cmd.blk_addr[3] = blk & 0xff;
1039 scsi_cmd.xfer_len[0] = (len >> 8) & 0xff;
1040 scsi_cmd.xfer_len[1] = len & 0xff;
1041 return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1042 (struct scsi_generic *) &scsi_cmd,
1043 sizeof(scsi_cmd),
1044 0,
1045 0,
1046 CDRETRIES,
1047 200000, /* should be immed */
1048 NULL,
1049 0));
1050 }
1051
1052 /*
1053 * Get scsi driver to send a "start playing" command
1054 */
1055 errval
1056 cd_play_big(unit, blk, len)
1057 u_int32 unit, blk, len;
1058 {
1059 struct scsi_play_big scsi_cmd;
1060 errval retval;
1061
1062 bzero(&scsi_cmd, sizeof(scsi_cmd));
1063 scsi_cmd.op_code = PLAY_BIG;
1064 scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
1065 scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
1066 scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
1067 scsi_cmd.blk_addr[3] = blk & 0xff;
1068 scsi_cmd.xfer_len[0] = (len >> 24) & 0xff;
1069 scsi_cmd.xfer_len[1] = (len >> 16) & 0xff;
1070 scsi_cmd.xfer_len[2] = (len >> 8) & 0xff;
1071 scsi_cmd.xfer_len[3] = len & 0xff;
1072 return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1073 (struct scsi_generic *) &scsi_cmd,
1074 sizeof(scsi_cmd),
1075 0,
1076 0,
1077 CDRETRIES,
1078 20000, /* should be immed */
1079 NULL,
1080 0));
1081 }
1082
1083 /*
1084 * Get scsi driver to send a "start playing" command
1085 */
1086 errval
1087 cd_play_tracks(unit, strack, sindex, etrack, eindex)
1088 u_int32 unit, strack, sindex, etrack, eindex;
1089 {
1090 struct scsi_play_track scsi_cmd;
1091 errval retval;
1092
1093 bzero(&scsi_cmd, sizeof(scsi_cmd));
1094 scsi_cmd.op_code = PLAY_TRACK;
1095 scsi_cmd.start_track = strack;
1096 scsi_cmd.start_index = sindex;
1097 scsi_cmd.end_track = etrack;
1098 scsi_cmd.end_index = eindex;
1099 return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1100 (struct scsi_generic *) &scsi_cmd,
1101 sizeof(scsi_cmd),
1102 0,
1103 0,
1104 CDRETRIES,
1105 20000, /* should be immed */
1106 NULL,
1107 0));
1108 }
1109
1110 /*
1111 * Get scsi driver to send a "play msf" command
1112 */
1113 errval
1114 cd_play_msf(unit, startm, starts, startf, endm, ends, endf)
1115 u_int32 unit, startm, starts, startf, endm, ends, endf;
1116 {
1117 struct scsi_play_msf scsi_cmd;
1118
1119 bzero(&scsi_cmd, sizeof(scsi_cmd));
1120 scsi_cmd.op_code = PLAY_MSF;
1121 scsi_cmd.start_m = startm;
1122 scsi_cmd.start_s = starts;
1123 scsi_cmd.start_f = startf;
1124 scsi_cmd.end_m = endm;
1125 scsi_cmd.end_s = ends;
1126 scsi_cmd.end_f = endf;
1127
1128 return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1129 (struct scsi_generic *) &scsi_cmd,
1130 sizeof(scsi_cmd),
1131 0,
1132 0,
1133 CDRETRIES,
1134 2000,
1135 NULL,
1136 0));
1137 }
1138
1139 /*
1140 * Get scsi driver to send a "start up" command
1141 */
1142 errval
1143 cd_pause(unit, go)
1144 u_int32 unit, go;
1145 {
1146 struct scsi_pause scsi_cmd;
1147
1148 bzero(&scsi_cmd, sizeof(scsi_cmd));
1149 scsi_cmd.op_code = PAUSE;
1150 scsi_cmd.resume = go;
1151
1152 return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1153 (struct scsi_generic *) &scsi_cmd,
1154 sizeof(scsi_cmd),
1155 0,
1156 0,
1157 CDRETRIES,
1158 2000,
1159 NULL,
1160 0));
1161 }
1162
1163 /*
1164 * Get scsi driver to send a "RESET" command
1165 */
1166 errval
1167 cd_reset(unit)
1168 u_int32 unit;
1169 {
1170 return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1171 0,
1172 0,
1173 0,
1174 0,
1175 CDRETRIES,
1176 2000,
1177 NULL,
1178 SCSI_RESET));
1179 }
1180
1181 /*
1182 * Read subchannel
1183 */
1184 errval
1185 cd_read_subchannel(unit, mode, format, track, data, len)
1186 u_int32 unit, mode, format, len;
1187 struct cd_sub_channel_info *data;
1188 {
1189 struct scsi_read_subchannel scsi_cmd;
1190 errval error;
1191
1192 bzero(&scsi_cmd, sizeof(scsi_cmd));
1193
1194 scsi_cmd.op_code = READ_SUBCHANNEL;
1195 if (mode == CD_MSF_FORMAT)
1196 scsi_cmd.byte2 |= CD_MSF;
1197 scsi_cmd.byte3 = SRS_SUBQ;
1198 scsi_cmd.subchan_format = format;
1199 scsi_cmd.track = track;
1200 scsi_cmd.data_len[0] = (len) >> 8;
1201 scsi_cmd.data_len[1] = (len) & 0xff;
1202 return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1203 (struct scsi_generic *) &scsi_cmd,
1204 sizeof(struct scsi_read_subchannel),
1205 (u_char *) data,
1206 len,
1207 CDRETRIES,
1208 5000,
1209 NULL,
1210 SCSI_DATA_IN));
1211 }
1212
1213 /*
1214 * Read table of contents
1215 */
1216 errval
1217 cd_read_toc(unit, mode, start, data, len)
1218 u_int32 unit, mode, start, len;
1219 struct cd_toc_entry *data;
1220 {
1221 struct scsi_read_toc scsi_cmd;
1222 errval error;
1223 u_int32 ntoc;
1224
1225 bzero(&scsi_cmd, sizeof(scsi_cmd));
1226 /*if(len!=sizeof(struct ioc_toc_header))
1227 * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
1228 * else */
1229 ntoc = len;
1230
1231 scsi_cmd.op_code = READ_TOC;
1232 if (mode == CD_MSF_FORMAT)
1233 scsi_cmd.byte2 |= CD_MSF;
1234 scsi_cmd.from_track = start;
1235 scsi_cmd.data_len[0] = (ntoc) >> 8;
1236 scsi_cmd.data_len[1] = (ntoc) & 0xff;
1237 return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1238 (struct scsi_generic *) &scsi_cmd,
1239 sizeof(struct scsi_read_toc),
1240 (u_char *) data,
1241 len,
1242 CDRETRIES,
1243 5000,
1244 NULL,
1245 SCSI_DATA_IN));
1246 }
1247
1248 #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
1249
1250 /*
1251 * Get the scsi driver to send a full inquiry to the device and use the
1252 * results to fill out the disk parameter structure.
1253 */
1254 errval
1255 cd_get_parms(unit, flags)
1256 {
1257 struct cd_data *cd = cd_driver.cd_data[unit];
1258
1259 /*
1260 * First check if we have it all loaded
1261 */
1262 if (cd->sc_link->flags & SDEV_MEDIA_LOADED)
1263 return (0);
1264 /*
1265 * give a number of sectors so that sec * trks * cyls
1266 * is <= disk_size
1267 */
1268 if (cd_size(unit, flags)) {
1269 cd->sc_link->flags |= SDEV_MEDIA_LOADED;
1270 return (0);
1271 } else {
1272 return (ENXIO);
1273 }
1274 }
1275
1276 int
1277 cdsize(dev_t dev)
1278 {
1279 return (-1);
1280 }
1281