2 * Written by Julian Elischer (julian@tfs.com)
3 * for TRW Financial Systems for use under the MACH(2.5) operating system.
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.
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.
15 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
17 * $Id: cd.c,v 1.9 1993/09/20 06:27:02 rgrimes Exp $
23 #include <sys/types.h>
24 #include <sys/param.h>
25 #include <sys/dkbad.h>
26 #include <sys/systm.h>
30 #include <sys/ioctl.h>
33 #include <sys/malloc.h>
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>
43 long int cdstrats,cdqueues;
55 #define SECSIZE 2048 /* XXX */ /* default only */
56 #define CDOUTSTANDING 2
61 #define PARTITION(z) (minor(z) & 0x07)
63 #define UNIT(z) ( (minor(z) >> UNITSHIFT) )
75 #define CDVALID 0x02 /* PARAMS LOADED */
76 #define CDINIT 0x04 /* device has been init'd */
77 #define CDWAIT 0x08 /* device has someone waiting */
78 #define CDHAVELABEL 0x10 /* have read the label */
79 struct scsi_switch *sc_sw; /* address of scsi low level switch */
80 int ctlr; /* so they know which one we want */
81 int targ; /* our scsi target ID */
82 int lu; /* out scsi lu */
83 int cmdscount; /* cmds allowed outstanding by board*/
87 u_long disksize; /* total number sectors */
89 struct disklabel disklabel;
90 int partflags[MAXPARTITIONS]; /* per partition flags */
92 int openparts; /* one bit for each open partition */
94 struct scsi_xfer *free_xfer;
95 struct scsi_xfer scsi_xfer[CDOUTSTANDING]; /* XXX */
106 struct cd_data **cd_data;
109 static int next_cd_unit = 0;
110 /***********************************************************************\
111 * The routine called by the low level scsi routine when it discovers *
112 * A device suitable for this driver *
113 \***********************************************************************/
114 int cdattach(ctlr,targ,lu,scsi_switch)
115 struct scsi_switch *scsi_switch;
119 struct cd_data *cd, **cdrealloc;
123 if(scsi_debug & PRINTROUTINES) printf("cdattach: ");
125 /*******************************************************\
126 * Check if we have resources allocated yet, if not *
127 * allocate and initialize them *
128 \*******************************************************/
129 if (next_cd_unit == 0)
132 malloc(sizeof(struct cd_driver),M_DEVBUF,M_NOWAIT);
135 printf("cd%d: malloc failed for cd_driver\n",unit);
138 bzero(cd_driver,sizeof(cd_driver));
141 /*******************************************************\
142 * allocate the resources for another drive *
143 * if we have already allocate a cd_data pointer we must *
144 * copy the old pointers into a new region that is *
145 * larger and release the old region, aka realloc *
146 \*******************************************************/
147 unit = next_cd_unit++;
149 * This if will always be true for now, but future code may
150 * preallocate more units to reduce overhead. This would be
151 * done by changing the malloc to be (next_cd_unit * x) and
152 * the cd_driver->size++ to be +x
154 if(unit >= cd_driver->size)
157 malloc(sizeof(cd_driver->cd_data) * next_cd_unit,
161 printf("cd%d: malloc failed for cdrealloc\n",unit);
164 /* Make sure we have something to copy before we copy it */
165 bzero(cdrealloc,sizeof(cd_driver->cd_data) * next_cd_unit);
168 bcopy(cd_driver->cd_data,cdrealloc,
169 sizeof(cd_driver->cd_data) * cd_driver->size);
170 free(cd_driver->cd_data,M_DEVBUF);
172 cd_driver->cd_data = cdrealloc;
173 cd_driver->cd_data[unit] = NULL;
176 if(cd_driver->cd_data[unit])
178 printf("cd%d: Already has storage!\n",unit);
181 /*******************************************************\
182 * allocate the per drive data area *
183 \*******************************************************/
184 cd = cd_driver->cd_data[unit] =
185 malloc(sizeof(struct cd_data),M_DEVBUF,M_NOWAIT);
188 printf("cd%d: malloc failed for cd_data\n",unit);
191 bzero(cd,sizeof(struct cd_data));
193 /*******************************************************\
194 * Store information needed to contact our base driver *
195 \*******************************************************/
196 cd->sc_sw = scsi_switch;
200 cd->cmdscount = CDOUTSTANDING; /* XXX (ask the board) */
205 cd->scsi_xfer[i].next = cd->free_xfer;
206 cd->free_xfer = &cd->scsi_xfer[i];
208 /*******************************************************\
209 * Use the subdriver to request information regarding *
210 * the drive. We cannot use interrupts yet, so the *
211 * request must specify this. *
212 \*******************************************************/
213 cd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK);
216 printf("cd%d: cd present.[%d x %d byte records]\n",
223 printf("cd%d: drive empty\n", unit);
229 /*******************************************************\
230 * open the device. Make sure the partition info *
231 * is a up-to-date as can be. *
232 \*******************************************************/
237 struct cd_parms cd_parms;
241 part = PARTITION(dev);
244 if(scsi_debug & (PRINTROUTINES | TRACEOPENS))
245 printf("cdopen: dev=0x%x (unit %d (of %d),partition %d)\n"
246 ,dev,unit,cd_driver->size,part);
248 /*******************************************************\
249 * Check the unit is legal *
250 \*******************************************************/
251 if ( unit >= cd_driver->size )
255 cd = cd_driver->cd_data[unit];
256 /*******************************************************\
257 * Make sure the device has been initialised *
258 \*******************************************************/
259 if ((cd == NULL) || (!(cd->flags & CDINIT)))
262 /*******************************************************\
263 * If it's been invalidated, and not everybody has *
264 * closed it then forbid re-entry. *
265 * (may have changed media) *
266 \*******************************************************/
267 if ((! (cd->flags & CDVALID))
271 /*******************************************************\
272 * Check that it is still responding and ok. *
273 * if the media has been changed this will result in a *
274 * "unit attention" error which the error code will *
275 * disregard because the CDVALID flag is not yet set *
276 \*******************************************************/
277 cd_test_ready(unit, SCSI_SILENT);
279 /*******************************************************\
280 * Next time actually take notice of error returns *
281 \*******************************************************/
282 if (cd_test_ready(unit, SCSI_SILENT) != 0) {
284 if(scsi_debug & TRACEOPENS)
285 printf("not ready\n");
290 if(scsi_debug & TRACEOPENS)
291 printf("Device present\n");
293 /*******************************************************\
294 * In case it is a funny one, tell it to start *
295 * not needed for some drives *
296 \*******************************************************/
297 cd_start_unit(unit,part,CD_START);
298 cd_prevent_unit(unit,PR_PREVENT,SCSI_SILENT);
300 if(scsi_debug & TRACEOPENS)
303 /*******************************************************\
304 * Load the physical device parameters *
305 \*******************************************************/
306 cd_get_parms(unit, 0);
308 if(scsi_debug & TRACEOPENS)
309 printf("Params loaded ");
311 /*******************************************************\
312 * Load the partition info if not already loaded *
313 \*******************************************************/
314 cdgetdisklabel(unit);
316 if(scsi_debug & TRACEOPENS)
317 printf("Disklabel fabricated ");
319 /*******************************************************\
320 * Check the partition is legal *
321 \*******************************************************/
322 if (( part >= cd->disklabel.d_npartitions )
323 && (part != RAW_PART))
326 if(scsi_debug & TRACEOPENS)
327 printf("partition %d > %d\n",part
328 ,cd->disklabel.d_npartitions);
330 cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
333 /*******************************************************\
334 * Check that the partition exists *
335 \*******************************************************/
336 if (( cd->disklabel.d_partitions[part].p_fstype != FS_UNUSED )
337 || (part == RAW_PART))
339 cd->partflags[part] |= CDOPEN;
340 cd->openparts |= (1 << part);
342 if(scsi_debug & TRACEOPENS)
343 printf("open complete\n");
345 cd->flags |= CDVALID;
350 if(scsi_debug & TRACEOPENS)
351 printf("part %d type UNUSED\n",part);
353 cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
359 /*******************************************************\
360 * Get ownership of a scsi_xfer structure *
361 * If need be, sleep on it, until it comes free *
362 \*******************************************************/
363 struct scsi_xfer *cd_get_xs(unit,flags)
367 struct scsi_xfer *xs;
371 cd = cd_driver->cd_data[unit];
372 if(flags & (SCSI_NOSLEEP | SCSI_NOMASK))
374 if (xs = cd->free_xfer)
376 cd->free_xfer = xs->next;
383 while (!(xs = cd->free_xfer))
385 cd->xfer_block_wait++; /* someone waiting! */
386 sleep((caddr_t)&cd->free_xfer, PRIBIO+1);
387 cd->xfer_block_wait--;
389 cd->free_xfer = xs->next;
396 /*******************************************************\
397 * Free a scsi_xfer, wake processes waiting for it *
398 \*******************************************************/
399 cd_free_xs(unit,xs,flags)
400 struct scsi_xfer *xs;
407 cd = cd_driver->cd_data[unit];
408 if(flags & SCSI_NOMASK)
410 if (cd->xfer_block_wait)
412 printf("cd%d: doing a wakeup from NOMASK mode\n", unit);
413 wakeup((caddr_t)&cd->free_xfer);
415 xs->next = cd->free_xfer;
421 if (cd->xfer_block_wait)
422 wakeup((caddr_t)&cd->free_xfer);
423 xs->next = cd->free_xfer;
429 /*******************************************************\
430 * trim the size of the transfer if needed, *
432 * basically the smaller of our max and the scsi driver's*
433 * minphys (note we have no max ourselves) *
434 \*******************************************************/
435 /* Trim buffer length if buffer-size is bigger than page size */
439 (*(cd_driver->cd_data[UNIT(bp->b_dev)]->sc_sw->scsi_minphys))(bp);
442 /*******************************************************\
443 * Actually translate the requested transfer into *
444 * one the physical driver can understand *
445 * The transfer is described by a buf and will include *
446 * only one physical transfer. *
447 \*******************************************************/
458 unit = UNIT((bp->b_dev));
459 cd = cd_driver->cd_data[unit];
461 if(scsi_debug & PRINTROUTINES) printf("\ncdstrategy ");
462 if(scsi_debug & SHOWREQUESTS) printf("cd%d: %d bytes @ blk%d\n",
463 unit,bp->b_bcount,bp->b_blkno);
466 /*******************************************************\
467 * If the device has been made invalid, error out *
468 * maybe the media changed *
469 \*******************************************************/
470 if(!(cd->flags & CDVALID))
475 /*******************************************************\
476 * can't ever write to a CD *
477 \*******************************************************/
478 if ((bp->b_flags & B_READ) == 0) {
482 /*******************************************************\
483 * If it's a null transfer, return immediatly *
484 \*******************************************************/
485 if (bp->b_bcount == 0) {
489 /*******************************************************\
490 * Decide which unit and partition we are talking about *
491 \*******************************************************/
492 if(PARTITION(bp->b_dev) != RAW_PART)
494 if (!(cd->flags & CDHAVELABEL))
500 * do bounds checking, adjust transfer. if error, process.
501 * if end of partition, just return
503 if (bounds_check_with_label(bp,&cd->disklabel,1) <= 0)
505 /* otherwise, process transfer request */
511 /*******************************************************\
512 * Place it in the queue of disk activities for this disk*
513 \*******************************************************/
516 /*******************************************************\
517 * Tell the device to get going on the transfer if it's *
518 * not doing anything, otherwise just wait for completion*
519 \*******************************************************/
525 bp->b_flags |= B_ERROR;
528 /*******************************************************\
529 * Correctly set the buf to indicate a completed xfer *
530 \*******************************************************/
531 bp->b_resid = bp->b_bcount;
536 /***************************************************************\
537 * cdstart looks to see if there is a buf waiting for the device *
538 * and that the device is not already busy. If both are true, *
539 * It deques the buf and creates a scsi command to perform the *
540 * transfer in the buf. The transfer request will call cd_done *
541 * on completion, which will in turn call this routine again *
542 * so that the next queued transfer is performed. *
543 * The bufs are queued by the strategy routine (cdstrategy) *
545 * This routine is also called after other non-queued requests *
546 * have been made of the scsi driver, to ensure that the queue *
547 * continues to be drained. *
549 * must be called at the correct (highish) spl level *
550 \***************************************************************/
551 /* cdstart() is called at SPLCD from cdstrategy and cd_done*/
555 register struct buf *bp = 0;
556 register struct buf *dp;
557 struct scsi_xfer *xs;
558 struct scsi_rw_big cmd;
561 struct partition *p ;
564 if(scsi_debug & PRINTROUTINES) printf("cdstart%d ",unit);
566 cd = cd_driver->cd_data[unit];
567 /*******************************************************\
568 * See if there is a buf to do and we are not already *
570 \*******************************************************/
573 return; /* none for us, unit already underway */
576 if(cd->xfer_block_wait) /* there is one, but a special waits */
578 return; /* give the special that's waiting a chance to run */
583 if ((bp = dp->b_actf) != NULL) /* yes, an assign */
585 dp->b_actf = bp->av_forw;
592 xs=cd_get_xs(unit,0); /* ok we can grab it */
593 xs->flags = INUSE; /* Now ours */
594 /***************************************************************\
595 * Should reject all queued entries if CDVALID is not true *
596 \***************************************************************/
597 if(!(cd->flags & CDVALID))
599 goto bad; /* no I/O.. media changed or something */
602 /*******************************************************\
603 * We have a buf, now we should move the data into *
604 * a scsi_xfer definition and try start it *
606 * First, translate the block to absolute *
607 * and put it in terms of the logical blocksize of the *
609 * really a bit silly until we have real partitions, but.*
610 \*******************************************************/
611 blkno = bp->b_blkno / (cd->params.blksize/512);
612 if(PARTITION(bp->b_dev) != RAW_PART)
614 p = cd->disklabel.d_partitions + PARTITION(bp->b_dev);
615 blkno += p->p_offset;
617 nblk = (bp->b_bcount + (cd->params.blksize - 1)) / (cd->params.blksize);
618 /* what if something asks for 512 bytes not on a 2k boundary? *//*XXX*/
620 /*******************************************************\
621 * Fill out the scsi command *
622 \*******************************************************/
623 bzero(&cmd, sizeof(cmd));
624 cmd.op_code = READ_BIG;
625 cmd.addr_3 = (blkno & 0xff000000) >> 24;
626 cmd.addr_2 = (blkno & 0xff0000) >> 16;
627 cmd.addr_1 = (blkno & 0xff00) >> 8;
628 cmd.addr_0 = blkno & 0xff;
629 cmd.length2 = (nblk & 0xff00) >> 8;
630 cmd.length1 = (nblk & 0xff);
631 /*******************************************************\
632 * Fill out the scsi_xfer structure *
633 * Note: we cannot sleep as we may be an interrupt *
634 \*******************************************************/
635 xs->flags |= SCSI_NOSLEEP;
636 xs->adapter = cd->ctlr;
639 xs->retries = CD_RETRIES;
640 xs->timeout = 10000;/* 10000 millisecs for a disk !*/
641 xs->cmd = (struct scsi_generic *)&cmd;
642 xs->cmdlen = sizeof(cmd);
643 xs->resid = bp->b_bcount;
644 xs->when_done = cd_done;
646 xs->done_arg2 = (int)xs;
647 xs->error = XS_NOERROR;
649 xs->data = (u_char *)bp->b_un.b_addr;
650 xs->datalen = bp->b_bcount;
652 /*******************************************************\
653 * Pass all this info to the scsi driver. *
654 \*******************************************************/
655 if ( (*(cd->sc_sw->scsi_cmd))(xs) != SUCCESSFULLY_QUEUED)
657 printf("cd%d: oops not queued",unit);
662 bad: xs->error = XS_DRIVER_STUFFUP;
666 /*******************************************************\
667 * This routine is called by the scsi interrupt when *
668 * the transfer is complete. (or failed) *
669 \*******************************************************/
672 struct scsi_xfer *xs;
676 struct cd_data *cd = cd_driver->cd_data[unit];
679 if(scsi_debug & PRINTROUTINES) printf("cd_done%d ",unit);
682 if (! (xs->flags & INUSE)) /* paranoia always pays off */
683 panic("scsi_xfer not in use!");
698 retval = (cd_interpret_sense(unit,xs));
701 bp->b_flags |= B_ERROR;
702 bp->b_error = retval;
707 printf("cd%d timeout\n",unit);
710 /***********************************\
711 * Just resubmit it straight back to *
712 * the SCSI driver to try it again *
713 \***********************************/
716 xs->error = XS_NOERROR;
717 xs->flags &= ~ITSDONE;
718 if ((*(cd->sc_sw->scsi_cmd))(xs)
719 == SUCCESSFULLY_QUEUED)
720 { /* shhh! don't wake the job, ok? */
721 /* don't tell cdstart either, */
724 /* xs->error is set by the scsi driver */
727 case XS_DRIVER_STUFFUP:
728 bp->b_flags |= B_ERROR;
732 printf("cd%d: unknown error category from scsi driver\n"
736 cd_free_xs(unit,xs,0);
737 cdstart(unit); /* If there's anything waiting.. do it */
741 /*******************************************************\
742 * Perform special action on behalf of the user *
743 * Knows about the internals of this device *
744 \*******************************************************/
745 cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
749 unsigned char unit, part;
750 register struct cd_data *cd;
753 /*******************************************************\
754 * Find the device that the user is talking about *
755 \*******************************************************/
757 part = PARTITION(dev);
758 cd = cd_driver->cd_data[unit];
760 if(scsi_debug & PRINTROUTINES) printf("cdioctl%d ",unit);
763 /*******************************************************\
764 * If the device is not valid.. abandon ship *
765 \*******************************************************/
766 if (!(cd_driver->cd_data[unit]->flags & CDVALID))
776 *(struct disklabel *)addr = cd->disklabel;
780 ((struct partinfo *)addr)->disklab = &cd->disklabel;
781 ((struct partinfo *)addr)->part =
782 &cd->disklabel.d_partitions[PARTITION(dev)];
787 if ((flag & FWRITE) == 0)
790 error = setdisklabel(&cd->disklabel,
791 (struct disklabel *)addr,
792 /*(cd->flags & DKFL_BSDLABEL) ? cd->openparts : */0,
795 cd->flags |= CDHAVELABEL;
803 case CDIOCPLAYTRACKS:
805 struct ioc_play_track *args
806 = (struct ioc_play_track *)addr;
807 struct cd_mode_data data;
808 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
810 data.page.audio.flags &= ~CD_PA_SOTC;
811 data.page.audio.flags |= CD_PA_IMMED;
812 if(error = cd_set_mode(unit,&data))
814 return(cd_play_tracks(unit
824 struct ioc_play_msf *args
825 = (struct ioc_play_msf *)addr;
826 struct cd_mode_data data;
827 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
829 data.page.audio.flags &= ~CD_PA_SOTC;
830 data.page.audio.flags |= CD_PA_IMMED;
831 if(error = cd_set_mode(unit,&data))
833 return(cd_play_msf(unit
843 case CDIOCPLAYBLOCKS:
845 struct ioc_play_blocks *args
846 = (struct ioc_play_blocks *)addr;
847 struct cd_mode_data data;
848 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
850 data.page.audio.flags &= ~CD_PA_SOTC;
851 data.page.audio.flags |= CD_PA_IMMED;
852 if(error = cd_set_mode(unit,&data))
854 return(cd_play(unit,args->blk,args->len));
859 case CDIOCREADSUBCHANNEL:
861 struct ioc_read_subchannel *args
862 = (struct ioc_read_subchannel *)addr;
863 struct cd_sub_channel_info data;
864 int len=args->data_len;
865 if(len>sizeof(data)||
866 len<sizeof(struct cd_sub_channel_header)) {
870 if(error = cd_read_subchannel(unit,args->address_format,
871 args->data_format,args->track,&data,len)) {
874 len=MIN(len,((data.header.data_len[0]<<8)+data.header.data_len[1]+
875 sizeof(struct cd_sub_channel_header)));
876 if(copyout(&data,args->data,len)!=0) {
881 case CDIOREADTOCHEADER:
883 struct ioc_toc_header th;
884 if( error = cd_read_toc(unit,0,0,&th,sizeof(th)))
886 th.len=(th.len&0xff)<<8+((th.len>>8)&0xff);
887 bcopy(&th,addr,sizeof(th));
890 case CDIOREADTOCENTRYS:
892 struct ioc_read_toc_entry *te=
893 (struct ioc_read_toc_entry *)addr;
894 struct cd_toc_entry data[65];
895 struct ioc_toc_header *th;
896 int len=te->data_len;
897 th=(struct ioc_toc_header *)data;
899 if(len>sizeof(data) || len<sizeof(struct cd_toc_entry)) {
903 if(error = cd_read_toc(unit,te->address_format,
908 len=MIN(len,((((th->len&0xff)<<8)+((th->len>>8)))+
910 if(copyout(th,te->data,len)!=0) {
918 struct ioc_patch *arg = (struct ioc_patch *)addr;
919 struct cd_mode_data data;
920 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
922 data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
923 data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
924 data.page.audio.port[2].channels = arg->patch[2];
925 data.page.audio.port[3].channels = arg->patch[3];
926 if(error = cd_set_mode(unit,&data))
932 struct ioc_vol *arg = (struct ioc_vol *)addr;
933 struct cd_mode_data data;
934 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
936 arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
937 arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
938 arg->vol[2] = data.page.audio.port[2].volume;
939 arg->vol[3] = data.page.audio.port[3].volume;
944 struct ioc_vol *arg = (struct ioc_vol *)addr;
945 struct cd_mode_data data;
946 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
948 data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
949 data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
950 data.page.audio.port[2].volume = arg->vol[2];
951 data.page.audio.port[3].volume = arg->vol[3];
952 if(error = cd_set_mode(unit,&data))
958 struct ioc_vol *arg = (struct ioc_vol *)addr;
959 struct cd_mode_data data;
960 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
962 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL|RIGHT_CHANNEL|4|8;
963 data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL|RIGHT_CHANNEL;
964 data.page.audio.port[2].channels = 0;
965 data.page.audio.port[3].channels = 0;
966 if(error = cd_set_mode(unit,&data))
972 struct ioc_vol *arg = (struct ioc_vol *)addr;
973 struct cd_mode_data data;
974 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
976 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
977 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
978 data.page.audio.port[2].channels = 0;
979 data.page.audio.port[3].channels = 0;
980 if(error = cd_set_mode(unit,&data))
986 struct ioc_vol *arg = (struct ioc_vol *)addr;
987 struct cd_mode_data data;
988 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
990 data.page.audio.port[LEFT_PORT].channels = 0;
991 data.page.audio.port[RIGHT_PORT].channels = 0;
992 data.page.audio.port[2].channels = 0;
993 data.page.audio.port[3].channels = 0;
994 if(error = cd_set_mode(unit,&data))
1000 struct ioc_vol *arg = (struct ioc_vol *)addr;
1001 struct cd_mode_data data;
1002 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
1004 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
1005 data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
1006 data.page.audio.port[2].channels = 0;
1007 data.page.audio.port[3].channels = 0;
1008 if(error = cd_set_mode(unit,&data))
1014 struct ioc_vol *arg = (struct ioc_vol *)addr;
1015 struct cd_mode_data data;
1016 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
1018 data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
1019 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
1020 data.page.audio.port[2].channels = 0;
1021 data.page.audio.port[3].channels = 0;
1022 if(error = cd_set_mode(unit,&data))
1027 error = cd_pause(unit,1);
1030 error = cd_pause(unit,0);
1033 error = cd_start_unit(unit,part,CD_START);
1036 error = cd_start_unit(unit,part,CD_STOP);
1039 error = cd_start_unit(unit,part,CD_EJECT);
1042 scsi_debug = 0xfff; cd_debug = 0xfff;
1045 scsi_debug = 0; cd_debug = 0;
1048 return(cd_reset(unit));
1058 /*******************************************************\
1059 * Load the label information on the named device *
1061 * EVENTUALLY take information about different *
1062 * data tracks from the TOC and put it in the disklabel *
1063 \*******************************************************/
1064 int cdgetdisklabel(unit)
1067 /*unsigned int n, m;*/
1069 struct dos_partition *dos_partition_p;
1072 cd = cd_driver->cd_data[unit];
1073 /*******************************************************\
1074 * If the info is already loaded, use it *
1075 \*******************************************************/
1076 if(cd->flags & CDHAVELABEL) return;
1078 bzero(&cd->disklabel,sizeof(struct disklabel));
1079 /*******************************************************\
1080 * make partition 3 the whole disk in case of failure *
1082 \*******************************************************/
1083 strncpy(cd->disklabel.d_typename,"scsi cd_rom",16);
1084 strncpy(cd->disklabel.d_packname,"ficticious",16);
1085 cd->disklabel.d_secsize = cd->params.blksize; /* as long as it's not 0 */
1086 cd->disklabel.d_nsectors = 100;
1087 cd->disklabel.d_ntracks = 1;
1088 cd->disklabel.d_ncylinders = (cd->params.disksize / 100) + 1;
1089 cd->disklabel.d_secpercyl = 100;
1090 cd->disklabel.d_secperunit = cd->params.disksize;
1091 cd->disklabel.d_rpm = 300;
1092 cd->disklabel.d_interleave = 1;
1093 cd->disklabel.d_flags = D_REMOVABLE;
1095 cd->disklabel.d_npartitions = 1;
1096 cd->disklabel.d_partitions[0].p_offset = 0;
1097 cd->disklabel.d_partitions[0].p_size
1098 = cd->params.disksize * (cd->params.blksize / 512);
1099 cd->disklabel.d_partitions[0].p_fstype = 9;
1101 cd->disklabel.d_magic = DISKMAGIC;
1102 cd->disklabel.d_magic2 = DISKMAGIC;
1103 cd->disklabel.d_checksum = dkcksum(&(cd->disklabel));
1105 /*******************************************************\
1106 * Signal to other users and routines that we now have a *
1107 * disklabel that represents the media (maybe) *
1108 \*******************************************************/
1109 cd->flags |= CDHAVELABEL;
1113 /*******************************************************\
1114 * Get scsi driver to send a "are you ready" command *
1115 \*******************************************************/
1116 cd_test_ready(unit,flags)
1119 struct scsi_test_unit_ready scsi_cmd;
1121 bzero(&scsi_cmd, sizeof(scsi_cmd));
1122 scsi_cmd.op_code = TEST_UNIT_READY;
1124 return (cd_scsi_cmd(unit,
1135 /*******************************************************\
1136 * Find out form the device what it's capacity is *
1137 \*******************************************************/
1138 cd_size(unit, flags)
1140 struct scsi_read_cd_cap_data rdcap;
1141 struct scsi_read_cd_capacity scsi_cmd;
1145 /*******************************************************\
1146 * make up a scsi command and ask the scsi driver to do *
1148 \*******************************************************/
1149 bzero(&scsi_cmd, sizeof(scsi_cmd));
1150 scsi_cmd.op_code = READ_CD_CAPACITY;
1152 /*******************************************************\
1153 * If the command works, interpret the result as a 4 byte*
1154 * number of blocks *
1155 \*******************************************************/
1156 if (cd_scsi_cmd(unit,
1165 printf("cd%d: could not get size\n", unit);
1168 size = rdcap.addr_0 + 1 ;
1169 size += rdcap.addr_1 << 8;
1170 size += rdcap.addr_2 << 16;
1171 size += rdcap.addr_3 << 24;
1172 blksize = rdcap.length_0 ;
1173 blksize += rdcap.length_1 << 8;
1174 blksize += rdcap.length_2 << 16;
1175 blksize += rdcap.length_3 << 24;
1178 if(cd_debug)printf("cd%d: %d %d byte blocks\n",unit,size,blksize);
1180 cd_driver->cd_data[unit]->params.disksize = size;
1181 cd_driver->cd_data[unit]->params.blksize = blksize;
1186 /*******************************************************\
1187 * Get the requested page into the buffer given *
1188 \*******************************************************/
1189 cd_get_mode(unit,data,page)
1191 struct cd_mode_data *data;
1194 struct scsi_mode_sense scsi_cmd;
1197 bzero(&scsi_cmd, sizeof(scsi_cmd));
1198 bzero(data,sizeof(*data));
1199 scsi_cmd.op_code = MODE_SENSE;
1200 scsi_cmd.page = page;
1201 scsi_cmd.length = sizeof(*data) & 0xff;
1202 retval = cd_scsi_cmd(unit,
1207 20000, /* should be immed */
1212 /*******************************************************\
1213 * Get the requested page into the buffer given *
1214 \*******************************************************/
1215 cd_set_mode(unit,data)
1217 struct cd_mode_data *data;
1219 struct scsi_mode_select scsi_cmd;
1221 bzero(&scsi_cmd, sizeof(scsi_cmd));
1222 scsi_cmd.op_code = MODE_SELECT;
1223 scsi_cmd.byte2 |= SMS_PF;
1224 scsi_cmd.length = sizeof(*data) & 0xff;
1225 data->header.data_length = 0;
1226 /*show_mem(data,sizeof(*data));/**/
1227 return (cd_scsi_cmd(unit,
1232 20000, /* should be immed */
1237 /*******************************************************\
1238 * Get scsi driver to send a "start playing" command *
1239 \*******************************************************/
1240 cd_play(unit,blk,len)
1243 struct scsi_play scsi_cmd;
1246 bzero(&scsi_cmd, sizeof(scsi_cmd));
1247 scsi_cmd.op_code = PLAY;
1248 scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
1249 scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
1250 scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
1251 scsi_cmd.blk_addr[3] = blk & 0xff;
1252 scsi_cmd.xfer_len[0] = (len >> 8) & 0xff;
1253 scsi_cmd.xfer_len[1] = len & 0xff;
1254 retval = cd_scsi_cmd(unit,
1259 200000, /* should be immed */
1264 /*******************************************************\
1265 * Get scsi driver to send a "start playing" command *
1266 \*******************************************************/
1267 cd_play_big(unit,blk,len)
1270 struct scsi_play_big scsi_cmd;
1273 bzero(&scsi_cmd, sizeof(scsi_cmd));
1274 scsi_cmd.op_code = PLAY_BIG;
1275 scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
1276 scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
1277 scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
1278 scsi_cmd.blk_addr[3] = blk & 0xff;
1279 scsi_cmd.xfer_len[0] = (len >> 24) & 0xff;
1280 scsi_cmd.xfer_len[1] = (len >> 16) & 0xff;
1281 scsi_cmd.xfer_len[2] = (len >> 8) & 0xff;
1282 scsi_cmd.xfer_len[3] = len & 0xff;
1283 retval = cd_scsi_cmd(unit,
1288 20000, /* should be immed */
1293 /*******************************************************\
1294 * Get scsi driver to send a "start playing" command *
1295 \*******************************************************/
1296 cd_play_tracks(unit,strack,sindex,etrack,eindex)
1297 int unit,strack,sindex,etrack,eindex;
1299 struct scsi_play_track scsi_cmd;
1302 bzero(&scsi_cmd, sizeof(scsi_cmd));
1303 scsi_cmd.op_code = PLAY_TRACK;
1304 scsi_cmd.start_track = strack;
1305 scsi_cmd.start_index = sindex;
1306 scsi_cmd.end_track = etrack;
1307 scsi_cmd.end_index = eindex;
1308 retval = cd_scsi_cmd(unit,
1313 20000, /* should be immed */
1318 /*******************************************************\
1319 * Get scsi driver to send a "play msf" command *
1320 \*******************************************************/
1321 cd_play_msf(unit,startm,starts,startf,endm,ends,endf)
1322 int unit,startm,starts,startf,endm,ends,endf;
1324 struct scsi_play_msf scsi_cmd;
1326 bzero(&scsi_cmd, sizeof(scsi_cmd));
1327 scsi_cmd.op_code = PLAY_MSF;
1328 scsi_cmd.start_m=startm;
1329 scsi_cmd.start_s=starts;
1330 scsi_cmd.start_f=startf;
1331 scsi_cmd.end_m=endm;
1332 scsi_cmd.end_s=ends;
1333 scsi_cmd.end_f=endf;
1335 return (cd_scsi_cmd(unit,
1344 /*******************************************************\
1345 * Get scsi driver to send a "start up" command *
1346 \*******************************************************/
1350 struct scsi_pause scsi_cmd;
1352 bzero(&scsi_cmd, sizeof(scsi_cmd));
1353 scsi_cmd.op_code = PAUSE;
1354 scsi_cmd.resume = go;
1356 return (cd_scsi_cmd(unit,
1365 /*******************************************************\
1366 * Get scsi driver to send a "RESET" command *
1367 \*******************************************************/
1371 return(cd_scsi_cmd(unit,
1380 /*******************************************************\
1381 * Get scsi driver to send a "start up" command *
1382 \*******************************************************/
1383 cd_start_unit(unit,part,type)
1385 struct scsi_start_stop scsi_cmd;
1386 struct cd_data *cd = cd_driver->cd_data[unit];
1389 /*&& (cd->openparts == 0)*/)/* trouble is WE have it open *//*XXX*/
1391 cd_prevent_unit(unit,PR_ALLOW,0);
1394 bzero(&scsi_cmd, sizeof(scsi_cmd));
1395 scsi_cmd.op_code = START_STOP;
1396 scsi_cmd.how |= (type==CD_START)?SSS_START:0;
1397 scsi_cmd.how |= (type==CD_EJECT)?SSS_LOEJ:0;
1399 if (cd_scsi_cmd(unit,
1411 /*******************************************************\
1412 * Prevent or allow the user to remove the disk *
1413 \*******************************************************/
1414 cd_prevent_unit(unit,type,flags)
1415 int unit,type,flags;
1417 struct scsi_prevent scsi_cmd;
1418 struct cd_data *cd = cd_driver->cd_data[unit];
1421 || ( type==PR_ALLOW && cd->openparts == 0 ))/*XXX*/
1423 bzero(&scsi_cmd, sizeof(scsi_cmd));
1424 scsi_cmd.op_code = PREVENT_ALLOW;
1425 scsi_cmd.how = type;
1426 if (cd_scsi_cmd(unit,
1428 sizeof(struct scsi_prevent),
1435 if(!(flags & SCSI_SILENT))
1436 printf("cd%d: cannot prevent/allow\n", unit);
1443 /******************************************************\
1445 \******************************************************/
1447 cd_read_subchannel(unit,mode,format,track,data,len)
1448 int unit,mode,format,len;
1449 struct cd_sub_channel_info *data;
1451 struct scsi_read_subchannel scsi_cmd;
1454 bzero(&scsi_cmd,sizeof(scsi_cmd));
1456 scsi_cmd.op_code=READ_SUBCHANNEL;
1457 if(mode==CD_MSF_FORMAT)
1458 scsi_cmd.byte2 |= CD_MSF;
1459 scsi_cmd.byte3=SRS_SUBQ;
1460 scsi_cmd.subchan_format=format;
1461 scsi_cmd.track=track;
1462 scsi_cmd.data_len[0]=(len)>>8;
1463 scsi_cmd.data_len[1]=(len)&0xff;
1464 return cd_scsi_cmd(unit,
1466 sizeof(struct scsi_read_subchannel),
1474 /*******************************************************\
1475 * Read Table of contents *
1476 \*******************************************************/
1477 cd_read_toc(unit,mode,start,data,len)
1478 int unit,mode,start,len;
1479 struct cd_toc_entry *data;
1481 struct scsi_read_toc scsi_cmd;
1485 bzero(&scsi_cmd,sizeof(scsi_cmd));
1486 /*if(len!=sizeof(struct ioc_toc_header))
1487 ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
1491 scsi_cmd.op_code=READ_TOC;
1492 if(mode==CD_MSF_FORMAT)
1493 scsi_cmd.byte2 |= CD_MSF;
1494 scsi_cmd.from_track=start;
1495 scsi_cmd.data_len[0]=(ntoc)>>8;
1496 scsi_cmd.data_len[1]=(ntoc)&0xff;
1497 return cd_scsi_cmd(unit,
1499 sizeof(struct scsi_read_toc),
1508 #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
1510 /*******************************************************\
1511 * Get the scsi driver to send a full inquiry to the *
1512 * device and use the results to fill out the disk *
1513 * parameter structure. *
1514 \*******************************************************/
1516 int cd_get_parms(unit, flags)
1518 struct cd_data *cd = cd_driver->cd_data[unit];
1520 /*******************************************************\
1521 * First check if we have it all loaded *
1522 \*******************************************************/
1523 if(cd->flags & CDVALID) return(0);
1524 /*******************************************************\
1525 * give a number of sectors so that sec * trks * cyls *
1527 \*******************************************************/
1528 if(cd_size(unit, flags))
1530 cd->flags |= CDVALID;
1539 /*******************************************************\
1540 * close the device.. only called if we are the LAST *
1541 * occurence of an open device *
1542 \*******************************************************/
1546 unsigned char unit, part;
1547 unsigned int old_priority;
1550 part = PARTITION(dev);
1552 if(scsi_debug & TRACEOPENS)
1553 printf("cd%d: closing part %d\n",unit,part);
1555 cd_driver->cd_data[unit]->partflags[part] &= ~CDOPEN;
1556 cd_driver->cd_data[unit]->openparts &= ~(1 << part);
1557 cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
1561 /*******************************************************\
1562 * ask the scsi driver to perform a command for us. *
1563 * Call it through the switch table, and tell it which *
1564 * sub-unit we want, and what target and lu we wish to *
1565 * talk to. Also tell it where to find the command *
1566 * how long int is. *
1567 * Also tell it where to read/write the data, and how *
1568 * long the data is supposed to be *
1569 \*******************************************************/
1570 int cd_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,bp,flags)
1573 struct scsi_generic *scsi_cmd;
1580 struct scsi_xfer *xs;
1583 struct cd_data *cd = cd_driver->cd_data[unit];
1586 if(scsi_debug & PRINTROUTINES) printf("\ncd_scsi_cmd%d ",unit);
1589 if(!(cd->sc_sw)) /* If we have a scsi driver */
1591 /* !? how'd we GET here? */
1592 panic("attempt to run bad cd device");
1595 xs = cd_get_xs(unit,flags); /* should wait unless booting */
1598 printf("cd%d: scsi_cmd controller busy"
1599 " (this should never happen)\n",unit);
1603 /*******************************************************\
1604 * Fill out the scsi_xfer structure *
1605 \*******************************************************/
1607 xs->adapter = cd->ctlr;
1608 xs->targ = cd->targ;
1610 xs->retries = CD_RETRIES;
1611 xs->timeout = timeout;
1613 xs->cmdlen = cmdlen;
1614 xs->data = data_addr;
1615 xs->datalen = datalen;
1616 xs->resid = datalen;
1617 xs->when_done = (flags & SCSI_NOMASK)
1620 xs->done_arg = unit;
1621 xs->done_arg2 = (int)xs;
1623 retry: xs->error = XS_NOERROR;
1624 /*******************************************************\
1625 * Do the transfer. If we are polling we will return: *
1626 * COMPLETE, Was poll, and cd_done has been called *
1627 * HAD_ERROR, Was poll and an error was encountered *
1628 * TRY_AGAIN_LATER, Adapter short resources, try again *
1630 * if under full steam (interrupts) it will return: *
1631 * SUCCESSFULLY_QUEUED, will do a wakeup when complete *
1632 * HAD_ERROR, had an erro before it could queue *
1633 * TRY_AGAIN_LATER, (as for polling) *
1634 * After the wakeup, we must still check if it succeeded *
1636 * If we have a bp however, all the error proccessing *
1637 * and the buffer code both expect us to return straight *
1638 * to them, so as soon as the command is queued, return *
1639 \*******************************************************/
1640 retval = (*(cd->sc_sw->scsi_cmd))(xs);
1641 if(bp) return retval; /* will sleep (or not) elsewhere */
1643 /*******************************************************\
1644 * Only here for non I/O cmds. It's cheaper to process *
1645 * the error status here than at interrupt time so *
1646 * sd_done will have done nothing except wake us up. *
1647 \*******************************************************/
1650 case SUCCESSFULLY_QUEUED:
1652 while(!(xs->flags & ITSDONE))
1655 /* Fall through to check the result */
1660 case XS_NOERROR: /* usually this one */
1665 retval = (cd_interpret_sense(unit,xs));
1668 /* should sleep here 1 sec */
1673 xs->flags &= ~ITSDONE;
1677 case XS_DRIVER_STUFFUP:
1682 printf("cd%d: unknown error category from scsi driver\n"
1690 case TRY_AGAIN_LATER:
1693 if(tsleep( 0,PRIBIO + 2,"retry",hz * 2))
1695 xs->flags &= ~ITSDONE;
1704 /*******************************************************\
1705 * we have finished doing the command, free the struct *
1706 * and check if anyone else needs it *
1707 \*******************************************************/
1708 cd_free_xs(unit,xs,flags);
1709 cdstart(unit); /* check if anything is waiting for the xs */
1712 /***************************************************************\
1713 * Look at the returned sense and act on the error and detirmine *
1714 * The unix error number to pass back... (0 = report no error) *
1715 \***************************************************************/
1717 int cd_interpret_sense(unit,xs)
1719 struct scsi_xfer *xs;
1721 struct scsi_sense_data *sense;
1725 struct cd_data *cd = cd_driver->cd_data[unit];
1727 static char *error_mes[] = { "soft error (corrected)",
1728 "not ready", "medium error",
1729 "non-media hardware failure", "illegal request",
1730 "unit attention", "readonly device",
1731 "no data found", "vendor unique",
1732 "copy aborted", "command aborted",
1733 "search returned equal", "volume overflow",
1734 "verify miscompare", "unknown error key"
1737 /***************************************************************\
1738 * If the flags say errs are ok, then always return ok. *
1739 \***************************************************************/
1740 if (xs->flags & SCSI_ERR_OK) return(ESUCCESS);
1741 silent = (xs->flags & SCSI_SILENT);
1743 sense = &(xs->sense);
1748 printf("code%x valid%x\n"
1749 ,sense->error_code & SSD_ERRCODE
1750 ,sense->error_code & SSD_ERRCODE_VALID ? 1 : 0);
1751 printf("seg%x key%x ili%x eom%x fmark%x\n"
1752 ,sense->ext.extended.segment
1753 ,sense->ext.extended.flags & SSD_KEY
1754 ,sense->ext.extended.flags & SSD_ILI ? 1 : 0
1755 ,sense->ext.extended.flags & SSD_EOM ? 1 : 0
1756 ,sense->ext.extended.flags & SSD_FILEMARK ? 1 : 0);
1757 printf("info: %x %x %x %x followed by %d extra bytes\n"
1758 ,sense->ext.extended.info[0]
1759 ,sense->ext.extended.info[1]
1760 ,sense->ext.extended.info[2]
1761 ,sense->ext.extended.info[3]
1762 ,sense->ext.extended.extra_len);
1764 while(count < sense->ext.extended.extra_len)
1766 printf ("%x ",sense->ext.extended.extra_bytes[count++]);
1771 switch(sense->error_code & SSD_ERRCODE)
1773 /***************************************************************\
1774 * If it's code 70, use the extended stuff and interpret the key *
1775 \***************************************************************/
1776 case 0x71:/* delayed error */
1777 printf("cd%d: DELAYED ERROR, key = 0x%x\n",unit,key);
1779 if(sense->error_code & SSD_ERRCODE_VALID)
1781 info = ntohl(*((long *)sense->ext.extended.info));
1788 key=sense->ext.extended.flags & SSD_KEY;
1792 printf("cd%d: %s", unit, error_mes[key - 1]);
1793 if(sense->error_code & SSD_ERRCODE_VALID)
1797 case 0x2: /* NOT READY */
1798 case 0x5: /* ILLEGAL REQUEST */
1799 case 0x6: /* UNIT ATTENTION */
1800 case 0x7: /* DATA PROTECT */
1802 case 0x8: /* BLANK CHECK */
1803 printf(", requested size: %d (decimal)",
1807 printf(", info = %d (decimal)", info);
1815 case 0x0: /* NO SENSE */
1816 case 0x1: /* RECOVERED ERROR */
1818 case 0xc: /* EQUAL */
1820 case 0x2: /* NOT READY */
1821 cd->flags &= ~(CDVALID | CDHAVELABEL);
1823 case 0x5: /* ILLEGAL REQUEST */
1825 case 0x6: /* UNIT ATTENTION */
1826 cd->flags &= ~(CDVALID | CDHAVELABEL);
1832 case 0x7: /* DATA PROTECT */
1834 case 0xd: /* VOLUME OVERFLOW */
1836 case 0x8: /* BLANK CHECK */
1841 /*******************************\
1842 * Not code 70, just report it *
1843 \*******************************/
1847 printf("cd%d: error code %d", unit,
1848 sense->error_code & SSD_ERRCODE);
1849 if(sense->error_code & SSD_ERRCODE_VALID)
1851 printf(" at block no. %d (decimal)",
1852 (sense->ext.unextended.blockhi <<16)
1853 + (sense->ext.unextended.blockmed <<8)
1854 + (sense->ext.unextended.blocklow ));
1872 show_mem(address,num)
1873 unsigned char *address;
1877 printf("------------------------------");
1878 for (y = 0; y<num; y += 1)
1881 printf("\n%03d: ",y);
1882 printf("%02x ",*address++);
1884 printf("\n------------------------------\n");