cd.c revision 1.5 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 */
16
17 /*
18 * Ported to run under 386BSD by Julian Elischer (julian (at) tfs.com) Sept 1992
19 *
20 * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
21 * -------------------- ----- ----------------------
22 * CURRENT PATCH LEVEL: 1 00098
23 * -------------------- ----- ----------------------
24 *
25 * 16 Feb 93 Julian Elischer ADDED for SCSI system
26 */
27
28 #define SPLCD splbio
29 #define ESUCCESS 0
30
31 #include "cd.h"
32 #include "sys/types.h"
33 #include "sys/param.h"
34 #include "sys/dkbad.h"
35 #include "sys/systm.h"
36 #include "sys/conf.h"
37 #include "sys/file.h"
38 #include "sys/stat.h"
39 #include "sys/ioctl.h"
40 #include "sys/buf.h"
41 #include "sys/uio.h"
42 #include "sys/malloc.h"
43 #include "sys/cdio.h"
44
45 #include "sys/errno.h"
46 #include "sys/disklabel.h"
47 #include "scsi/scsi_all.h"
48 #include "scsi/scsi_cd.h"
49 #include "scsi/cddefs.h"
50 #include "scsi/scsi_disk.h" /* rw_big and start_stop come from there */
51 #include "scsi/scsiconf.h"
52
53 long int cdstrats,cdqueues;
54
55
56 #ifdef DDB
57 int Debugger();
58 #else
59 #define Debugger()
60 #endif
61
62
63 #define PAGESIZ 4096
64 #define SECSIZE 2048 /* XXX */ /* default only */
65 #define CDOUTSTANDING 2
66 #define CDQSIZE 4
67 #define CD_RETRIES 4
68
69 #define UNITSHIFT 3
70 #define PARTITION(z) (minor(z) & 0x07)
71 #define RAW_PART 3
72 #define UNIT(z) ( (minor(z) >> UNITSHIFT) )
73
74
75 extern int hz;
76 int cd_done();
77 int cdstrategy();
78 int cd_debug = 0;
79
80 struct buf cd_buf_queue[NCD];
81 struct scsi_xfer cd_scsi_xfer[NCD][CDOUTSTANDING]; /* XXX */
82 struct scsi_xfer *cd_free_xfer[NCD];
83 int cd_xfer_block_wait[NCD];
84
85 struct cd_data *cd_data[NCD];
86
87 #define CD_STOP 0
88 #define CD_START 1
89 #define CD_EJECT -2
90
91 /***********************************************************************\
92 * The routine called by the low level scsi routine when it discovers *
93 * A device suitable for this driver *
94 \***********************************************************************/
95 int cdattach(int masunit, struct scsi_switch *sw, int physid, int unit)
96 {
97 unsigned char *tbl;
98 struct cd_data *cd;
99 struct cd_parms *dp;
100 int targ, lun, i;
101
102 targ = physid >> 3;
103 lun = physid & 7;
104
105 if(unit >= NCD)
106 return -1;
107 if(cd_data[unit])
108 return -1;
109
110 cd = cd_data[unit] = (struct cd_data *)malloc(sizeof *cd,
111 M_TEMP, M_NOWAIT);
112 if(!cd)
113 return -1;
114 bzero(cd, sizeof *cd);
115
116 dp = &(cd->params);
117 if(scsi_debug & PRINTROUTINES) printf("cdattach: ");
118
119 /*******************************************************\
120 * Store information needed to contact our base driver *
121 \*******************************************************/
122 cd->sc_sw = sw;
123 cd->ctlr = masunit;
124 cd->targ = targ;
125 cd->lu = lun;
126 cd->cmdscount = CDOUTSTANDING; /* XXX (ask the board) */
127
128
129 i = cd->cmdscount;
130 while(i-- )
131 {
132 cd_scsi_xfer[unit][i].next = cd_free_xfer[unit];
133 cd_free_xfer[unit] = &cd_scsi_xfer[unit][i];
134 }
135 /*******************************************************\
136 * Use the subdriver to request information regarding *
137 * the drive. We cannot use interrupts yet, so the *
138 * request must specify this. *
139 \*******************************************************/
140 cd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK);
141 printf("cd%d at %s%d targ %d lun %d: %s\n",
142 unit, sw->name, masunit, targ, lun,
143 dp->disksize ? "loaded" : "empty");
144 cd->flags |= CDINIT;
145 return 0;
146 }
147
148
149 /*******************************************************\
150 * open the device. Make sure the partition info *
151 * is a up-to-date as can be. *
152 \*******************************************************/
153 cdopen(dev_t dev)
154 {
155 int errcode = 0;
156 int unit, part;
157 struct cd_parms cd_parms;
158 struct cd_data *cd;
159
160 unit = UNIT(dev);
161 part = PARTITION(dev);
162
163 if(scsi_debug & (PRINTROUTINES | TRACEOPENS))
164 printf("cd%d: open dev=0x%x partition %d)\n",
165 unit, dev, part);
166
167 /*******************************************************\
168 * Check the unit is legal *
169 \*******************************************************/
170 if( unit >= NCD )
171 return(ENXIO);
172 cd = cd_data[unit];
173 if(!cd)
174 return ENXIO;
175 if (! (cd->flags & CDINIT))
176 return(ENXIO);
177
178 /*******************************************************\
179 * If it's been invalidated, and not everybody has *
180 * closed it then forbid re-entry. *
181 * (may have changed media) *
182 \*******************************************************/
183 if ((! (cd->flags & CDVALID))
184 && ( cd->openparts))
185 return(ENXIO);
186 /*******************************************************\
187 * Check that it is still responding and ok. *
188 * if the media has been changed this will result in a *
189 * "unit attention" error which the error code will *
190 * disregard because the CDVALID flag is not yet set *
191 \*******************************************************/
192 if (cd_req_sense(unit, SCSI_SILENT) != 0) {
193 if(scsi_debug & TRACEOPENS)
194 printf("not reponding\n");
195 return(ENXIO);
196 }
197 if(scsi_debug & TRACEOPENS)
198 printf("Device present\n");
199 /*******************************************************\
200 * In case it is a funny one, tell it to start *
201 * not needed for hard drives *
202 \*******************************************************/
203 cd_start_unit(unit,part,CD_START);
204 cd_prevent_unit(unit,PR_PREVENT,SCSI_SILENT);
205 if(scsi_debug & TRACEOPENS)
206 printf("started ");
207 /*******************************************************\
208 * Load the physical device parameters *
209 \*******************************************************/
210 cd_get_parms(unit, 0);
211 if(scsi_debug & TRACEOPENS)
212 printf("Params loaded ");
213 /*******************************************************\
214 * Load the partition info if not already loaded *
215 \*******************************************************/
216 cdgetdisklabel(unit);
217 if(scsi_debug & TRACEOPENS)
218 printf("Disklabel fabricated ");
219 /*******************************************************\
220 * Check the partition is legal *
221 \*******************************************************/
222 if (( part >= cd->disklabel.d_npartitions )
223 && (part != RAW_PART))
224 {
225 if(scsi_debug & TRACEOPENS)
226 printf("partition %d > %d\n",part
227 ,cd->disklabel.d_npartitions);
228 cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
229 return(ENXIO);
230 }
231 /*******************************************************\
232 * Check that the partition exists *
233 \*******************************************************/
234 if (( cd->disklabel.d_partitions[part].p_fstype != FS_UNUSED )
235 || (part == RAW_PART))
236 {
237 cd->partflags[part] |= CDOPEN;
238 cd->openparts |= (1 << part);
239 if(scsi_debug & TRACEOPENS)
240 printf("open complete\n");
241 cd->flags |= CDVALID;
242 }
243 else
244 {
245 if(scsi_debug & TRACEOPENS)
246 printf("part %d type UNUSED\n",part);
247 cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
248 return(ENXIO);
249 }
250 return(0);
251 }
252
253 /*******************************************************\
254 * Get ownership of a scsi_xfer structure *
255 * If need be, sleep on it, until it comes free *
256 \*******************************************************/
257 struct scsi_xfer *cd_get_xs(unit,flags)
258 int flags;
259 int unit;
260 {
261 struct scsi_xfer *xs;
262 int s;
263
264 if(flags & (SCSI_NOSLEEP | SCSI_NOMASK))
265 {
266 if (xs = cd_free_xfer[unit])
267 {
268 cd_free_xfer[unit] = xs->next;
269 xs->flags = 0;
270 }
271 }
272 else
273 {
274 s = SPLCD();
275 while (!(xs = cd_free_xfer[unit]))
276 {
277 cd_xfer_block_wait[unit]++; /* someone waiting! */
278 sleep((caddr_t)&cd_free_xfer[unit], PRIBIO+1);
279 cd_xfer_block_wait[unit]--;
280 }
281 cd_free_xfer[unit] = xs->next;
282 splx(s);
283 xs->flags = 0;
284 }
285 return(xs);
286 }
287
288 /*******************************************************\
289 * Free a scsi_xfer, wake processes waiting for it *
290 \*******************************************************/
291 void
292 cd_free_xs(int unit, struct scsi_xfer *xs, int flags)
293 {
294 int s;
295
296 if(flags & SCSI_NOMASK)
297 {
298 if (cd_xfer_block_wait[unit])
299 {
300 printf("cd%d: doing a wakeup from NOMASK mode\n", unit);
301 wakeup((caddr_t)&cd_free_xfer[unit]);
302 }
303 xs->next = cd_free_xfer[unit];
304 cd_free_xfer[unit] = xs;
305 }
306 else
307 {
308 s = SPLCD();
309 if (cd_xfer_block_wait[unit])
310 wakeup((caddr_t)&cd_free_xfer[unit]);
311 xs->next = cd_free_xfer[unit];
312 cd_free_xfer[unit] = xs;
313 splx(s);
314 }
315 }
316
317 /*******************************************************\
318 * trim the size of the transfer if needed, *
319 * called by physio *
320 * basically the smaller of our max and the scsi driver's*
321 * minphys (note we have no max ourselves) *
322 \*******************************************************/
323 /* Trim buffer length if buffer-size is bigger than page size */
324 void cdminphys(bp)
325 struct buf *bp;
326 {
327 (*(cd_data[UNIT(bp->b_dev)]->sc_sw->scsi_minphys))(bp);
328 }
329
330 /*******************************************************\
331 * Actually translate the requested transfer into *
332 * one the physical driver can understand *
333 * The transfer is described by a buf and will include *
334 * only one physical transfer. *
335 \*******************************************************/
336
337 int cdstrategy(bp)
338 struct buf *bp;
339 {
340 struct buf *dp;
341 unsigned int opri;
342 struct cd_data *cd ;
343 int unit;
344
345 cdstrats++;
346 unit = UNIT((bp->b_dev));
347 cd = cd_data[unit];
348 if(scsi_debug & PRINTROUTINES) printf("\ncdstrategy ");
349 if(scsi_debug & SHOWREQUESTS) printf("cd%d: %d bytes @ blk%d\n",
350 unit,bp->b_bcount,bp->b_blkno);
351
352 if(!cd) {
353 bp->b_error = EIO;
354 goto bad;
355 }
356 if(!(cd->flags & CDVALID)) {
357 bp->b_error = EIO;
358 goto bad;
359 }
360
361 cdminphys(bp);
362 /*******************************************************\
363 * If the device has been made invalid, error out *
364 * maybe the media changed *
365 \*******************************************************/
366
367 /*******************************************************\
368 * can't ever write to a CD *
369 \*******************************************************/
370 if ((bp->b_flags & B_READ) == 0) {
371 bp->b_error = EROFS;
372 goto bad;
373 }
374 /*******************************************************\
375 * If it's a null transfer, return immediatly *
376 \*******************************************************/
377 if (bp->b_bcount == 0) {
378 goto done;
379 }
380
381 /*******************************************************\
382 * Decide which unit and partition we are talking about *
383 \*******************************************************/
384 if(PARTITION(bp->b_dev) != RAW_PART)
385 {
386 if (!(cd->flags & CDHAVELABEL))
387 {
388 bp->b_error = EIO;
389 goto bad;
390 }
391 /*
392 * do bounds checking, adjust transfer. if error, process.
393 * if end of partition, just return
394 */
395 if (bounds_check_with_label(bp,&cd->disklabel,1) <= 0)
396 goto done;
397 /* otherwise, process transfer request */
398 }
399
400 opri = SPLCD();
401 dp = &cd_buf_queue[unit];
402
403 /*******************************************************\
404 * Place it in the queue of disk activities for this disk*
405 \*******************************************************/
406 disksort(dp, bp);
407
408 /*******************************************************\
409 * Tell the device to get going on the transfer if it's *
410 * not doing anything, otherwise just wait for completion*
411 \*******************************************************/
412 cdstart(unit);
413
414 splx(opri);
415 return;
416 bad:
417 bp->b_flags |= B_ERROR;
418 done:
419
420 /*******************************************************\
421 * Correctly set the buf to indicate a completed xfer *
422 \*******************************************************/
423 bp->b_resid = bp->b_bcount;
424 biodone(bp);
425 return;
426 }
427
428 /***************************************************************\
429 * cdstart looks to see if there is a buf waiting for the device *
430 * and that the device is not already busy. If both are true, *
431 * It deques the buf and creates a scsi command to perform the *
432 * transfer in the buf. The transfer request will call cd_done *
433 * on completion, which will in turn call this routine again *
434 * so that the next queued transfer is performed. *
435 * The bufs are queued by the strategy routine (cdstrategy) *
436 * *
437 * This routine is also called after other non-queued requests *
438 * have been made of the scsi driver, to ensure that the queue *
439 * continues to be drained. *
440 * *
441 * must be called at the correct (highish) spl level *
442 \***************************************************************/
443 /* cdstart() is called at SPLCD from cdstrategy and cd_done*/
444 void
445 cdstart(int unit)
446 {
447 register struct buf *bp = 0;
448 register struct buf *dp;
449 struct scsi_xfer *xs;
450 struct scsi_rw_big cmd;
451 int blkno, nblk;
452 struct cd_data *cd = cd_data[unit];
453 struct partition *p ;
454
455 if(scsi_debug & PRINTROUTINES) printf("cdstart%d ",unit);
456 /*******************************************************\
457 * See if there is a buf to do and we are not already *
458 * doing one *
459 \*******************************************************/
460 if(!cd_free_xfer[unit])
461 {
462 return; /* none for us, unit already underway */
463 }
464
465 if(cd_xfer_block_wait[unit]) /* there is one, but a special waits */
466 {
467 return; /* give the special that's waiting a chance to run */
468 }
469
470
471 dp = &cd_buf_queue[unit];
472 if ((bp = dp->b_actf) != NULL) /* yes, an assign */
473 {
474 dp->b_actf = bp->av_forw;
475 }
476 else
477 {
478 return;
479 }
480
481 xs=cd_get_xs(unit,0); /* ok we can grab it */
482 xs->flags = INUSE; /* Now ours */
483 /***************************************************************\
484 * Should reject all queued entries if CDVALID is not true *
485 \***************************************************************/
486 if(!(cd->flags & CDVALID))
487 {
488 goto bad; /* no I/O.. media changed or something */
489 }
490
491 /*******************************************************\
492 * We have a buf, now we should move the data into *
493 * a scsi_xfer definition and try start it *
494 \*******************************************************/
495 /*******************************************************\
496 * First, translate the block to absolute *
497 * and put it in terms of the logical blocksize of the *
498 * device.. *
499 \*******************************************************/
500 p = cd->disklabel.d_partitions + PARTITION(bp->b_dev);
501 blkno = ((bp->b_blkno / (cd->params.blksize/512)) + p->p_offset);
502 nblk = (bp->b_bcount + (cd->params.blksize - 1)) / (cd->params.blksize);
503
504 /*******************************************************\
505 * Fill out the scsi command *
506 \*******************************************************/
507 bzero(&cmd, sizeof(cmd));
508 cmd.op_code = READ_BIG;
509 cmd.addr_3 = (blkno & 0xff000000) >> 24;
510 cmd.addr_2 = (blkno & 0xff0000) >> 16;
511 cmd.addr_1 = (blkno & 0xff00) >> 8;
512 cmd.addr_0 = blkno & 0xff;
513 cmd.length2 = (nblk & 0xff00) >> 8;
514 cmd.length1 = (nblk & 0xff);
515 /*******************************************************\
516 * Fill out the scsi_xfer structure *
517 * Note: we cannot sleep as we may be an interrupt *
518 \*******************************************************/
519 xs->flags |= SCSI_NOSLEEP;
520 xs->adapter = cd->ctlr;
521 xs->targ = cd->targ;
522 xs->lu = cd->lu;
523 xs->retries = CD_RETRIES;
524 xs->timeout = 10000;/* 10000 millisecs for a disk !*/
525 xs->cmd = (struct scsi_generic *)&cmd;
526 xs->cmdlen = sizeof(cmd);
527 xs->resid = bp->b_bcount;
528 xs->when_done = cd_done;
529 xs->done_arg = unit;
530 xs->done_arg2 = (int)xs;
531 xs->error = XS_NOERROR;
532 xs->bp = bp;
533 xs->data = (u_char *)bp->b_un.b_addr;
534 xs->datalen = bp->b_bcount;
535
536 /*******************************************************\
537 * Pass all this info to the scsi driver. *
538 \*******************************************************/
539 if ( (*(cd->sc_sw->scsi_cmd))(xs) != SUCCESSFULLY_QUEUED)
540 {
541 printf("cd%d: oops not queued",unit);
542 goto bad;
543 }
544 cdqueues++;
545 return;
546 bad: xs->error = XS_DRIVER_STUFFUP;
547 cd_done(unit,xs);
548 }
549
550 /*******************************************************\
551 * This routine is called by the scsi interrupt when *
552 * the transfer is complete. (or failed) *
553 \*******************************************************/
554 int cd_done(unit,xs)
555 int unit;
556 struct scsi_xfer *xs;
557 {
558 struct buf *bp;
559 int retval;
560
561 if(scsi_debug & PRINTROUTINES) printf("cd_done%d ",unit);
562 if (! (xs->flags & INUSE)) /* paranoia always pays off */
563 panic("scsi_xfer not in use!");
564 if(bp = xs->bp)
565 {
566 switch(xs->error)
567 {
568 case XS_NOERROR:
569 bp->b_error = 0;
570 bp->b_resid = 0;
571 break;
572
573 case XS_SENSE:
574 retval = (cd_interpret_sense(unit,xs));
575 if(retval)
576 {
577 bp->b_flags |= B_ERROR;
578 bp->b_error = retval;
579 }
580 break;
581
582 case XS_TIMEOUT:
583 printf("cd%d: timeout\n",unit);
584
585 case XS_BUSY:
586 /***********************************\
587 * Just resubmit it straight back to *
588 * the SCSI driver to try it again *
589 \***********************************/
590 if(xs->retries--)
591 {
592 xs->error = XS_NOERROR;
593 xs->flags &= ~ITSDONE;
594 if ( (*(cd_data[unit]->sc_sw->scsi_cmd))(xs)
595 == SUCCESSFULLY_QUEUED)
596 { /* shhh! don't wake the job, ok? */
597 /* don't tell cdstart either, */
598 return;
599 }
600 /* xs->error is set by the scsi driver */
601 } /* Fall through */
602
603 case XS_DRIVER_STUFFUP:
604 bp->b_flags |= B_ERROR;
605 bp->b_error = EIO;
606 break;
607 default:
608 printf("cd%d: unknown error category from scsi driver\n"
609 ,unit);
610 }
611 biodone(bp);
612 cd_free_xs(unit,xs,0);
613 cdstart(unit); /* If there's anything waiting.. do it */
614 }
615 else /* special has finished */
616 {
617 wakeup(xs);
618 }
619 }
620 /*******************************************************\
621 * Perform special action on behalf of the user *
622 * Knows about the internals of this device *
623 \*******************************************************/
624 cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
625 {
626 int error = 0;
627 unsigned int opri;
628 unsigned char unit, part;
629 register struct cd_data *cd;
630
631
632 /*******************************************************\
633 * Find the device that the user is talking about *
634 \*******************************************************/
635 unit = UNIT(dev);
636 part = PARTITION(dev);
637 cd = cd_data[unit];
638 if(scsi_debug & PRINTROUTINES) printf("cdioctl%d ",unit);
639
640 /*******************************************************\
641 * If the device is not valid.. abandon ship *
642 \*******************************************************/
643 if(!cd)
644 return ENXIO;
645 if (!(cd_data[unit]->flags & CDVALID))
646 return ENXIO;
647
648 switch(cmd)
649 {
650
651 case DIOCSBAD:
652 error = EINVAL;
653 break;
654
655 case DIOCGDINFO:
656 *(struct disklabel *)addr = cd->disklabel;
657 break;
658
659 case DIOCGPART:
660 ((struct partinfo *)addr)->disklab = &cd->disklabel;
661 ((struct partinfo *)addr)->part =
662 &cd->disklabel.d_partitions[PARTITION(dev)];
663 break;
664
665 case DIOCWDINFO:
666 case DIOCSDINFO:
667 if ((flag & FWRITE) == 0)
668 error = EBADF;
669 else
670 error = setdisklabel(&cd->disklabel,
671 (struct disklabel *)addr,
672 /*(cd->flags & DKFL_BSDLABEL) ? cd->openparts : */0,
673 0);
674 if (error == 0) {
675 cd->flags |= CDHAVELABEL;
676 }
677 break;
678
679 case DIOCWLABEL:
680 error = EBADF;
681 break;
682
683 case CDIOCPLAYTRACKS:
684 {
685 struct ioc_play_track *args
686 = (struct ioc_play_track *)addr;
687 struct cd_mode_data data;
688 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
689 break;
690 data.page.audio.sotc = 0;
691 data.page.audio.immed = 1;
692 if(error = cd_set_mode(unit,&data))
693 break;
694 return(cd_play_tracks(unit
695 ,args->start_track
696 ,args->start_index
697 ,args->end_track
698 ,args->end_index
699 ));
700 }
701 break;
702 case CDIOCPLAYBLOCKS:
703 {
704 struct ioc_play_blocks *args
705 = (struct ioc_play_blocks *)addr;
706 struct cd_mode_data data;
707 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
708 break;
709 data.page.audio.sotc = 0;
710 data.page.audio.immed = 1;
711 if(error = cd_set_mode(unit,&data))
712 break;
713 return(cd_play(unit,args->blk,args->len));
714
715
716 }
717 break;
718 case CDIOCREADSUBCHANNEL:
719 {
720 struct ioc_read_subchannel *args
721 = (struct ioc_read_subchannel *)addr;
722 struct cd_sub_channel_info data;
723 int len=args->data_len;
724 if(len>sizeof(data)||
725 len<sizeof(struct cd_sub_channel_header)) {
726 error=EINVAL;
727 break;
728 }
729 if(error = cd_read_subchannel(unit,args->address_format,
730 args->data_format,args->track,&data,len)) {
731 break;
732 }
733 len=MIN(len,((data.header.data_len[0]<<8)+data.header.data_len[1]+
734 sizeof(struct cd_sub_channel_header)));
735 if(copyout(&data,args->data,len)!=0) {
736 error=EFAULT;
737 }
738 }
739 break;
740 case CDIOREADTOCHEADER:
741 {
742 struct ioc_toc_header th;
743 if( error = cd_read_toc(unit, 0, 0,
744 (struct cd_toc_entry *)&th,sizeof(th)))
745 break;
746 th.len=(th.len&0xff)<<8+((th.len>>8)&0xff);
747 bcopy(&th,addr,sizeof(th));
748 }
749 break;
750 case CDIOREADTOCENTRYS:
751 {
752 struct ioc_read_toc_entry *te=
753 (struct ioc_read_toc_entry *)addr;
754 struct cd_toc_entry data[65];
755 struct ioc_toc_header *th;
756 int len=te->data_len;
757 th=(struct ioc_toc_header *)data;
758
759 if(len>sizeof(data) || len<sizeof(struct cd_toc_entry)) {
760 error=EINVAL;
761 break;
762 }
763 if(error = cd_read_toc(unit,te->address_format,
764 te->starting_track,
765 (struct cd_toc_entry *)data,
766 len))
767 break;
768 len=MIN(len,((((th->len&0xff)<<8)+((th->len>>8)))+
769 sizeof(*th)));
770 if(copyout(th,te->data,len)!=0) {
771 error=EFAULT;
772 }
773
774 }
775 break;
776 case CDIOCSETPATCH:
777 {
778 struct ioc_patch *arg = (struct ioc_patch *)addr;
779 struct cd_mode_data data;
780 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
781 break;
782 data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
783 data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
784 data.page.audio.port[2].channels = arg->patch[2];
785 data.page.audio.port[3].channels = arg->patch[3];
786 if(error = cd_set_mode(unit,&data))
787 break;
788 }
789 break;
790 case CDIOCGETVOL:
791 {
792 struct ioc_vol *arg = (struct ioc_vol *)addr;
793 struct cd_mode_data data;
794 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
795 break;
796 arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
797 arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
798 arg->vol[2] = data.page.audio.port[2].volume;
799 arg->vol[3] = data.page.audio.port[3].volume;
800 }
801 break;
802 case CDIOCSETVOL:
803 {
804 struct ioc_vol *arg = (struct ioc_vol *)addr;
805 struct cd_mode_data data;
806 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
807 break;
808 data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
809 data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
810 data.page.audio.port[2].volume = arg->vol[2];
811 data.page.audio.port[3].volume = arg->vol[3];
812 if(error = cd_set_mode(unit,&data))
813 break;
814 }
815 break;
816 case CDIOCSETMONO:
817 {
818 struct ioc_vol *arg = (struct ioc_vol *)addr;
819 struct cd_mode_data data;
820 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
821 break;
822 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL|RIGHT_CHANNEL|4|8;
823 data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL|RIGHT_CHANNEL;
824 data.page.audio.port[2].channels = 0;
825 data.page.audio.port[3].channels = 0;
826 if(error = cd_set_mode(unit,&data))
827 break;
828 }
829 break;
830 case CDIOCSETSTERIO:
831 {
832 struct ioc_vol *arg = (struct ioc_vol *)addr;
833 struct cd_mode_data data;
834 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
835 break;
836 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
837 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
838 data.page.audio.port[2].channels = 0;
839 data.page.audio.port[3].channels = 0;
840 if(error = cd_set_mode(unit,&data))
841 break;
842 }
843 break;
844 case CDIOCSETMUTE:
845 {
846 struct ioc_vol *arg = (struct ioc_vol *)addr;
847 struct cd_mode_data data;
848 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
849 break;
850 data.page.audio.port[LEFT_PORT].channels = 0;
851 data.page.audio.port[RIGHT_PORT].channels = 0;
852 data.page.audio.port[2].channels = 0;
853 data.page.audio.port[3].channels = 0;
854 if(error = cd_set_mode(unit,&data))
855 break;
856 }
857 break;
858 case CDIOCSETLEFT:
859 {
860 struct ioc_vol *arg = (struct ioc_vol *)addr;
861 struct cd_mode_data data;
862 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
863 break;
864 data.page.audio.port[LEFT_PORT].channels = 15;
865 data.page.audio.port[RIGHT_PORT].channels = 15;
866 data.page.audio.port[2].channels = 15;
867 data.page.audio.port[3].channels = 15;
868 if(error = cd_set_mode(unit,&data))
869 break;
870 }
871 break;
872 case CDIOCSETRIGHT:
873 {
874 struct ioc_vol *arg = (struct ioc_vol *)addr;
875 struct cd_mode_data data;
876 if(error = cd_get_mode(unit,&data,AUDIO_PAGE))
877 break;
878 data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
879 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
880 data.page.audio.port[2].channels = 0;
881 data.page.audio.port[3].channels = 0;
882 if(error = cd_set_mode(unit,&data))
883 break;
884 }
885 break;
886 case CDIOCRESUME:
887 error = cd_pause(unit,1);
888 break;
889 case CDIOCPAUSE:
890 error = cd_pause(unit,0);
891 break;
892 case CDIOCSTART:
893 error = cd_start_unit(unit,part,CD_START);
894 break;
895 case CDIOCSTOP:
896 error = cd_start_unit(unit,part,CD_STOP);
897 break;
898 case CDIOCEJECT:
899 error = cd_start_unit(unit,part,CD_EJECT);
900 break;
901 case CDIOCSETDEBUG:
902 scsi_debug = 0xfff; cd_debug = 0xfff;
903 break;
904 case CDIOCCLRDEBUG:
905 scsi_debug = 0; cd_debug = 0;
906 break;
907 case CDIOCRESET:
908 return(cd_reset(unit));
909 break;
910 default:
911 error = ENOTTY;
912 break;
913 }
914 return (error);
915 }
916
917
918 /*******************************************************\
919 * Load the label information on the named device *
920 * *
921 * EVENTUALLY take information about different *
922 * data tracks from the TOC and put it in the disklabel *
923 \*******************************************************/
924 int cdgetdisklabel(unit)
925 unsigned char unit;
926 {
927 /*unsigned int n, m;*/
928 char *errstring;
929 struct dos_partition *dos_partition_p;
930 struct cd_data *cd = cd_data[unit];
931
932 /*******************************************************\
933 * If the inflo is already loaded, use it *
934 \*******************************************************/
935 if(cd->flags & CDHAVELABEL) return;
936
937 bzero(&cd->disklabel,sizeof(struct disklabel));
938 /*******************************************************\
939 * make partition 3 the whole disk in case of failure *
940 * then get pdinfo *
941 \*******************************************************/
942 strncpy(cd->disklabel.d_typename,"scsi cd_rom",16);
943 strncpy(cd->disklabel.d_packname,"ficticious",16);
944 cd->disklabel.d_secsize = cd->params.blksize; /* as long as it's not 0 */
945 cd->disklabel.d_nsectors = 100;
946 cd->disklabel.d_ntracks = 1;
947 cd->disklabel.d_ncylinders = (cd->params.disksize / 100) + 1;
948 cd->disklabel.d_secpercyl = 100;
949 cd->disklabel.d_secperunit = cd->params.disksize;
950 cd->disklabel.d_rpm = 300;
951 cd->disklabel.d_interleave = 1;
952 cd->disklabel.d_flags = D_REMOVABLE;
953
954 cd->disklabel.d_npartitions = 1;
955 cd->disklabel.d_partitions[0].p_offset = 0;
956 cd->disklabel.d_partitions[0].p_size = cd->params.disksize;
957 cd->disklabel.d_partitions[0].p_fstype = 9;
958
959 cd->disklabel.d_magic = DISKMAGIC;
960 cd->disklabel.d_magic2 = DISKMAGIC;
961 cd->disklabel.d_checksum = dkcksum(&(cd->disklabel));
962
963 /*******************************************************\
964 * Signal to other users and routines that we now have a *
965 * disklabel that represents the media (maybe) *
966 \*******************************************************/
967 cd->flags |= CDHAVELABEL;
968 return(ESUCCESS);
969 }
970
971 /*******************************************************\
972 * Find out form the device what it's capacity is *
973 \*******************************************************/
974 cd_size(unit, flags)
975 {
976 struct scsi_read_cd_cap_data rdcap;
977 struct scsi_read_cd_capacity scsi_cmd;
978 int size;
979 int blksize;
980
981 /*******************************************************\
982 * make up a scsi command and ask the scsi driver to do *
983 * it for you. *
984 \*******************************************************/
985 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd));
986 scsi_cmd.op_code = READ_CD_CAPACITY;
987
988 /*******************************************************\
989 * If the command works, interpret the result as a 4 byte*
990 * number of blocks *
991 \*******************************************************/
992 if (cd_scsi_cmd(unit,
993 (struct scsi_generic *)&scsi_cmd,
994 sizeof(scsi_cmd),
995 (u_char *)&rdcap,
996 sizeof(rdcap),
997 2000,
998 flags) != 0)
999 {
1000 printf("cd%d: could not get size\n", unit);
1001 return(0);
1002 } else {
1003 size = rdcap.addr_0 + 1 ;
1004 size += rdcap.addr_1 << 8;
1005 size += rdcap.addr_2 << 16;
1006 size += rdcap.addr_3 << 24;
1007 blksize = rdcap.length_0 ;
1008 blksize += rdcap.length_1 << 8;
1009 blksize += rdcap.length_2 << 16;
1010 blksize += rdcap.length_3 << 24;
1011 }
1012 if(cd_debug)printf("cd%d: %d %d byte blocks\n",unit,size,blksize);
1013 cd_data[unit]->params.disksize = size;
1014 cd_data[unit]->params.blksize = blksize;
1015 return(size);
1016 }
1017
1018 /*******************************************************\
1019 * Check with the device that it is ok, (via scsi driver)*
1020 \*******************************************************/
1021 cd_req_sense(unit, flags)
1022 {
1023 struct scsi_sense_data sense_data;
1024 struct scsi_sense scsi_cmd;
1025
1026 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd));
1027 scsi_cmd.op_code = REQUEST_SENSE;
1028 scsi_cmd.length = sizeof(sense_data);
1029
1030 if (cd_scsi_cmd(unit,
1031 (struct scsi_generic *)&scsi_cmd,
1032 sizeof(scsi_cmd),
1033 (u_char *)&sense_data,
1034 sizeof(sense_data),
1035 2000,
1036 flags) != 0)
1037 {
1038 return(ENXIO);
1039 }
1040 else
1041 return(0);
1042 }
1043
1044 /*******************************************************\
1045 * Get the requested page into the buffer given *
1046 \*******************************************************/
1047 cd_get_mode(unit,data,page)
1048 int unit;
1049 struct cd_mode_data *data;
1050 int page;
1051 {
1052 struct scsi_mode_sense scsi_cmd;
1053 int retval;
1054
1055 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd));
1056 bzero(data,sizeof(*data));
1057 scsi_cmd.op_code = MODE_SENSE;
1058 scsi_cmd.page_code = page;
1059 scsi_cmd.length = sizeof(*data) & 0xff;
1060 retval = cd_scsi_cmd(unit,
1061 (struct scsi_generic *)&scsi_cmd,
1062 sizeof(scsi_cmd),
1063 (u_char *)data,
1064 sizeof(*data),
1065 20000, /* should be immed */
1066 0);
1067 return (retval);
1068 }
1069 /*******************************************************\
1070 * Get the requested page into the buffer given *
1071 \*******************************************************/
1072 cd_set_mode(unit,data)
1073 int unit;
1074 struct cd_mode_data *data;
1075 {
1076 struct scsi_mode_select scsi_cmd;
1077
1078 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd));
1079 scsi_cmd.op_code = MODE_SELECT;
1080 scsi_cmd.pf = 1;
1081 scsi_cmd.length = sizeof(*data) & 0xff;
1082 data->header.data_length = 0;
1083 /*show_mem(data,sizeof(*data));/**/
1084 return (cd_scsi_cmd(unit,
1085 (struct scsi_generic *)&scsi_cmd,
1086 sizeof(scsi_cmd),
1087 (u_char *)data,
1088 sizeof(*data),
1089 20000, /* should be immed */
1090 0)
1091 );
1092 }
1093 /*******************************************************\
1094 * Get scsi driver to send a "start playing" command *
1095 \*******************************************************/
1096 cd_play(unit,blk,len)
1097 int unit,blk,len;
1098 {
1099 struct scsi_play scsi_cmd;
1100 int retval;
1101
1102 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd));
1103 scsi_cmd.op_code = PLAY;
1104 scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
1105 scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
1106 scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
1107 scsi_cmd.blk_addr[3] = blk & 0xff;
1108 scsi_cmd.xfer_len[0] = (len >> 8) & 0xff;
1109 scsi_cmd.xfer_len[1] = len & 0xff;
1110 retval = cd_scsi_cmd(unit,
1111 (struct scsi_generic *)&scsi_cmd,
1112 sizeof(scsi_cmd),
1113 0,
1114 0,
1115 200000, /* should be immed */
1116 0);
1117 return(retval);
1118 }
1119 /*******************************************************\
1120 * Get scsi driver to send a "start playing" command *
1121 \*******************************************************/
1122 cd_play_big(unit,blk,len)
1123 int unit,blk,len;
1124 {
1125 struct scsi_play_big scsi_cmd;
1126 int retval;
1127
1128 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd));
1129 scsi_cmd.op_code = PLAY_BIG;
1130 scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
1131 scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
1132 scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
1133 scsi_cmd.blk_addr[3] = blk & 0xff;
1134 scsi_cmd.xfer_len[0] = (len >> 24) & 0xff;
1135 scsi_cmd.xfer_len[1] = (len >> 16) & 0xff;
1136 scsi_cmd.xfer_len[2] = (len >> 8) & 0xff;
1137 scsi_cmd.xfer_len[3] = len & 0xff;
1138 retval = cd_scsi_cmd(unit,
1139 (struct scsi_generic *)&scsi_cmd,
1140 sizeof(scsi_cmd),
1141 0,
1142 0,
1143 20000, /* should be immed */
1144 0);
1145 return(retval);
1146 }
1147 /*******************************************************\
1148 * Get scsi driver to send a "start playing" command *
1149 \*******************************************************/
1150 cd_play_tracks(unit,strack,sindex,etrack,eindex)
1151 int unit,strack,sindex,etrack,eindex;
1152 {
1153 struct scsi_play_track scsi_cmd;
1154 int retval;
1155
1156 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd));
1157 scsi_cmd.op_code = PLAY_TRACK;
1158 scsi_cmd.start_track = strack;
1159 scsi_cmd.start_index = sindex;
1160 scsi_cmd.end_track = etrack;
1161 scsi_cmd.end_index = eindex;
1162 retval = cd_scsi_cmd(unit,
1163 (struct scsi_generic *)&scsi_cmd,
1164 sizeof(scsi_cmd),
1165 0,
1166 0,
1167 20000, /* should be immed */
1168 0);
1169 return(retval);
1170 }
1171 /*******************************************************\
1172 * Get scsi driver to send a "start up" command *
1173 \*******************************************************/
1174 cd_pause(unit,go)
1175 int unit,go;
1176 {
1177 struct scsi_pause scsi_cmd;
1178
1179 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd));
1180 scsi_cmd.op_code = PAUSE;
1181 scsi_cmd.resume = go;
1182
1183 return (cd_scsi_cmd(unit,
1184 (struct scsi_generic *)&scsi_cmd,
1185 sizeof(scsi_cmd),
1186 0,
1187 0,
1188 2000,
1189 0));
1190 }
1191 /*******************************************************\
1192 * Get scsi driver to send a "start up" command *
1193 \*******************************************************/
1194 cd_reset(unit)
1195 int unit;
1196 {
1197 return(cd_scsi_cmd(unit,0,0,0,0,2000,SCSI_RESET));
1198 }
1199 /*******************************************************\
1200 * Get scsi driver to send a "start up" command *
1201 \*******************************************************/
1202 cd_start_unit(unit,part,type)
1203 {
1204 struct scsi_start_stop scsi_cmd;
1205
1206 if(type==CD_EJECT && (cd_data[unit]->openparts&~(1<<part)) == 0 ) {
1207 cd_prevent_unit(unit,CD_EJECT,0);
1208 }
1209
1210 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd));
1211 scsi_cmd.op_code = START_STOP;
1212 scsi_cmd.start = type==CD_START?1:0;
1213 scsi_cmd.loej = type==CD_EJECT?1:0;
1214
1215 if (cd_scsi_cmd(unit,
1216 (struct scsi_generic *)&scsi_cmd,
1217 sizeof(scsi_cmd),
1218 0,
1219 0,
1220 2000,
1221 0) != 0) {
1222 return(ENXIO);
1223 } else
1224 return(0);
1225 }
1226 /*******************************************************\
1227 * Prevent or allow the user to remove the disk *
1228 \*******************************************************/
1229 cd_prevent_unit(unit,type,flags)
1230 int unit,type,flags;
1231 {
1232 struct scsi_prevent scsi_cmd;
1233
1234 if(type==CD_EJECT || type==PR_PREVENT || cd_data[unit]->openparts == 0 ) {
1235 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd));
1236 scsi_cmd.op_code = PREVENT_ALLOW;
1237 scsi_cmd.prevent=type==CD_EJECT?PR_ALLOW:type;
1238 if (cd_scsi_cmd(unit,
1239 (struct scsi_generic *)&scsi_cmd,
1240 sizeof(struct scsi_prevent),
1241 0,
1242 0,
1243 5000,
1244 0) != 0)
1245 {
1246 if(!(flags & SCSI_SILENT))
1247 printf("cannot prevent/allow on cd%d\n", unit);
1248 return(0);
1249 }
1250 }
1251 return(1);
1252 }
1253
1254 /******************************************************\
1255 * Read Subchannel *
1256 \******************************************************/
1257
1258 cd_read_subchannel(unit,mode,format,track,data,len)
1259 int unit,mode,format,len;
1260 struct cd_sub_channel_info *data;
1261 {
1262 struct scsi_read_subchannel scsi_cmd;
1263 int error;
1264
1265 bzero((struct scsi_generic *)&scsi_cmd,sizeof(scsi_cmd));
1266
1267 scsi_cmd.op_code=READ_SUBCHANNEL;
1268 if(mode==CD_MSF_FORMAT)
1269 scsi_cmd.msf=1;
1270 scsi_cmd.subQ=1;
1271 scsi_cmd.subchan_format=format;
1272 scsi_cmd.track=track;
1273 scsi_cmd.data_len[0]=(len)>>8;
1274 scsi_cmd.data_len[1]=(len)&0xff;
1275 return cd_scsi_cmd(unit,
1276 (struct scsi_generic *)&scsi_cmd,
1277 sizeof(struct scsi_read_subchannel),
1278 (u_char *)data,
1279 len,
1280 5000,
1281 0);
1282 }
1283
1284 /*******************************************************\
1285 * Read Table of contents *
1286 \*******************************************************/
1287 cd_read_toc(unit,mode,start,data,len)
1288 int unit,mode,start,len;
1289 struct cd_toc_entry *data;
1290 {
1291 struct scsi_read_toc scsi_cmd;
1292 int error;
1293 int ntoc;
1294
1295 bzero((struct scsi_generic *)&scsi_cmd,sizeof(scsi_cmd));
1296 /*if(len!=sizeof(struct ioc_toc_header))
1297 ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
1298 else*/
1299 ntoc=len;
1300
1301 scsi_cmd.op_code=READ_TOC;
1302 if(mode==CD_MSF_FORMAT)
1303 scsi_cmd.msf=1;
1304 scsi_cmd.from_track=start;
1305 scsi_cmd.data_len[0]=(ntoc)>>8;
1306 scsi_cmd.data_len[1]=(ntoc)&0xff;
1307 return cd_scsi_cmd(unit,
1308 (struct scsi_generic *)&scsi_cmd,
1309 sizeof(struct scsi_read_toc),
1310 (u_char *)data,
1311 len,
1312 5000,
1313 0);
1314 }
1315
1316
1317 #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
1318
1319 /*******************************************************\
1320 * Get the scsi driver to send a full inquiry to the *
1321 * device and use the results to fill out the disk *
1322 * parameter structure. *
1323 \*******************************************************/
1324
1325 int cd_get_parms(unit, flags)
1326 {
1327 struct cd_data *cd = cd_data[unit];
1328
1329
1330 if(!cd)
1331 return 0;
1332 if(cd->flags & CDVALID)
1333 return 0;
1334
1335 /*******************************************************\
1336 * give a number of sectors so that sec * trks * cyls *
1337 * is <= disk_size *
1338 \*******************************************************/
1339 if(cd_size(unit, flags))
1340 {
1341 cd->flags |= CDVALID;
1342 return(0);
1343 }
1344 else
1345 {
1346 return(ENXIO);
1347 }
1348 }
1349
1350 /*******************************************************\
1351 * close the device.. only called if we are the LAST *
1352 * occurence of an open device *
1353 \*******************************************************/
1354 int
1355 cdclose(dev_t dev)
1356 {
1357 unsigned char unit, part;
1358 unsigned int old_priority;
1359
1360 unit = UNIT(dev);
1361 part = PARTITION(dev);
1362 if(scsi_debug & TRACEOPENS)
1363 printf("closing cd%d part %d\n",unit,part);
1364 cd_data[unit]->partflags[part] &= ~CDOPEN;
1365 cd_data[unit]->openparts &= ~(1 << part);
1366 cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
1367 return(0);
1368 }
1369
1370 /*******************************************************\
1371 * ask the scsi driver to perform a command for us. *
1372 * Call it through the switch table, and tell it which *
1373 * sub-unit we want, and what target and lu we wish to *
1374 * talk to. Also tell it where to find the command *
1375 * how long int is. *
1376 * Also tell it where to read/write the data, and how *
1377 * long the data is supposed to be *
1378 \*******************************************************/
1379 int cd_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags)
1380
1381 int unit,flags;
1382 struct scsi_generic *scsi_cmd;
1383 int cmdlen;
1384 int timeout;
1385 u_char *data_addr;
1386 int datalen;
1387 {
1388 struct scsi_xfer *xs;
1389 int retval;
1390 int s;
1391 struct cd_data *cd = cd_data[unit];
1392
1393 if(scsi_debug & PRINTROUTINES) printf("\ncd_scsi_cmd%d ",unit);
1394 if(cd->sc_sw) /* If we have a scsi driver */
1395 {
1396 xs = cd_get_xs(unit,flags); /* should wait unless booting */
1397 if(!xs)
1398 {
1399 printf("cd%d: cd_scsi_cmd: controller busy"
1400 " (this should never happen)\n",unit);
1401 return(EBUSY);
1402 }
1403 xs->flags |= INUSE;
1404 /*******************************************************\
1405 * Fill out the scsi_xfer structure *
1406 \*******************************************************/
1407 xs->flags |= flags;
1408 xs->adapter = cd->ctlr;
1409 xs->targ = cd->targ;
1410 xs->lu = cd->lu;
1411 xs->retries = CD_RETRIES;
1412 xs->timeout = timeout;
1413 xs->cmd = scsi_cmd;
1414 xs->cmdlen = cmdlen;
1415 xs->data = data_addr;
1416 xs->datalen = datalen;
1417 xs->resid = datalen;
1418 xs->when_done = (flags & SCSI_NOMASK)
1419 ?(int (*)())0
1420 :cd_done;
1421 xs->done_arg = unit;
1422 xs->done_arg2 = (int)xs;
1423 retry: xs->error = XS_NOERROR;
1424 xs->bp = 0;
1425 retval = (*(cd->sc_sw->scsi_cmd))(xs);
1426 switch(retval)
1427 {
1428 case SUCCESSFULLY_QUEUED:
1429 s = splbio();
1430 while(!(xs->flags & ITSDONE))
1431 sleep(xs,PRIBIO+1);
1432 splx(s);
1433
1434 case HAD_ERROR:
1435 /*printf("err = %d ",xs->error);*/
1436 switch(xs->error)
1437 {
1438 case XS_NOERROR:
1439 retval = ESUCCESS;
1440 break;
1441 case XS_SENSE:
1442 retval = (cd_interpret_sense(unit,xs));
1443 break;
1444 case XS_DRIVER_STUFFUP:
1445 retval = EIO;
1446 break;
1447
1448
1449 case XS_BUSY:
1450 case XS_TIMEOUT:
1451 if(xs->retries-- )
1452 {
1453 xs->flags &= ~ITSDONE;
1454 goto retry;
1455 }
1456 retval = EIO;
1457 break;
1458 default:
1459 retval = EIO;
1460 printf("cd%d: unknown error category from scsi driver\n"
1461 ,unit);
1462 }
1463 break;
1464 case COMPLETE:
1465 retval = ESUCCESS;
1466 break;
1467 case TRY_AGAIN_LATER:
1468 if(xs->retries-- )
1469 {
1470 if(tsleep( 0,PRIBIO + 2,"retry",hz * 2))
1471 {
1472 xs->flags &= ~ITSDONE;
1473 goto retry;
1474 }
1475 }
1476 retval = EIO;
1477 break;
1478 default:
1479 retval = EIO;
1480 }
1481 cd_free_xs(unit,xs,flags);
1482 cdstart(unit); /* check if anything is waiting fr the xs */
1483 }
1484 else
1485 {
1486 printf("cd%d: not set up\n",unit);
1487 return(EINVAL);
1488 }
1489 return(retval);
1490 }
1491 /***************************************************************\
1492 * Look at the returned sense and act on the error and detirmine *
1493 * The unix error number to pass back... (0 = report no error) *
1494 \***************************************************************/
1495
1496 int cd_interpret_sense(unit,xs)
1497 int unit;
1498 struct scsi_xfer *xs;
1499 {
1500 struct scsi_sense_data *sense;
1501 int key;
1502 int silent;
1503
1504 /***************************************************************\
1505 * If the flags say errs are ok, then always return ok. *
1506 \***************************************************************/
1507 if (xs->flags & SCSI_ERR_OK) return(ESUCCESS);
1508 silent = (xs->flags & SCSI_SILENT);
1509
1510 sense = &(xs->sense);
1511 switch(sense->error_class)
1512 {
1513 case 7:
1514 {
1515 key=sense->ext.extended.sense_key;
1516 switch(key)
1517 {
1518 case 0x0:
1519 return(ESUCCESS);
1520 case 0x1:
1521 if(!silent)
1522 {
1523 printf("cd%d: soft error(corrected) ", unit);
1524 if(sense->valid)
1525 {
1526 printf("block no. %d (decimal)",
1527 (sense->ext.extended.info[0] <<24),
1528 (sense->ext.extended.info[1] <<16),
1529 (sense->ext.extended.info[2] <<8),
1530 (sense->ext.extended.info[3] ));
1531 }
1532 printf("\n");
1533 }
1534 return(ESUCCESS);
1535 case 0x2:
1536 if(!silent)printf("cd%d: not ready\n",
1537 unit);
1538 return(ENODEV);
1539 case 0x3:
1540 if(!silent)
1541 {
1542 printf("cd%d: medium error ", unit);
1543 if(sense->valid)
1544 {
1545 printf("block no. %d (decimal)",
1546 (sense->ext.extended.info[0] <<24),
1547 (sense->ext.extended.info[1] <<16),
1548 (sense->ext.extended.info[2] <<8),
1549 (sense->ext.extended.info[3] ));
1550 }
1551 printf("\n");
1552 }
1553 return(EIO);
1554 case 0x4:
1555 if(!silent)printf("cd%d: non-media hardware failure\n",
1556 unit);
1557 return(EIO);
1558 case 0x5:
1559 if(!silent)printf("cd%d: illegal request\n",
1560 unit);
1561 return(EINVAL);
1562 case 0x6:
1563 if(!silent)printf("cd%d: media change\n", unit);
1564 if (cd_data[unit]->openparts)
1565 cd_data[unit]->flags &= ~(CDVALID | CDHAVELABEL);
1566 {
1567 return(EIO);
1568 }
1569 return(ESUCCESS);
1570 case 0x7:
1571 if(!silent)
1572 {
1573 printf("cd%d: attempted protection violation ",
1574 unit);
1575 if(sense->valid)
1576 {
1577 printf("block no. %d (decimal)\n",
1578 (sense->ext.extended.info[0] <<24),
1579 (sense->ext.extended.info[1] <<16),
1580 (sense->ext.extended.info[2] <<8),
1581 (sense->ext.extended.info[3] ));
1582 }
1583 printf("\n");
1584 }
1585 return(EACCES);
1586 case 0x8:
1587 if(!silent)
1588 {
1589 printf("cd%d: block wrong state (worm)\n",
1590 unit);
1591 if(sense->valid)
1592 {
1593 printf("block no. %d (decimal)\n",
1594 (sense->ext.extended.info[0] <<24),
1595 (sense->ext.extended.info[1] <<16),
1596 (sense->ext.extended.info[2] <<8),
1597 (sense->ext.extended.info[3] ));
1598 }
1599 printf("\n");
1600 }
1601 return(EIO);
1602 case 0x9:
1603 if(!silent)printf("cd%d: vendor unique\n",
1604 unit);
1605 return(EIO);
1606 case 0xa:
1607 if(!silent)printf("cd%d: copy aborted\n",
1608 unit);
1609 return(EIO);
1610 case 0xb:
1611 if(!silent)printf("cd%d: command aborted\n",
1612 unit);
1613 return(EIO);
1614 case 0xc:
1615 if(!silent)
1616 {
1617 printf("cd%d: search returned\n",
1618 unit);
1619 if(sense->valid)
1620 {
1621 printf("block no. %d (decimal)\n",
1622 (sense->ext.extended.info[0] <<24),
1623 (sense->ext.extended.info[1] <<16),
1624 (sense->ext.extended.info[2] <<8),
1625 (sense->ext.extended.info[3] ));
1626 }
1627 printf("\n");
1628 }
1629 return(ESUCCESS);
1630 case 0xd:
1631 if(!silent)printf("cd%d: volume overflow\n",
1632 unit);
1633 return(ENOSPC);
1634 case 0xe:
1635 if(!silent)
1636 {
1637 printf("cd%d: verify miscompare\n",
1638 unit);
1639 if(sense->valid)
1640 {
1641 printf("block no. %d (decimal)\n",
1642 (sense->ext.extended.info[0] <<24),
1643 (sense->ext.extended.info[1] <<16),
1644 (sense->ext.extended.info[2] <<8),
1645 (sense->ext.extended.info[3] ));
1646 }
1647 printf("\n");
1648 }
1649 return(EIO);
1650 case 0xf:
1651 if(!silent)printf("cd%d: unknown error key\n",
1652 unit);
1653 return(EIO);
1654 }
1655 break;
1656 }
1657 case 0:
1658 case 1:
1659 case 2:
1660 case 3:
1661 case 4:
1662 case 5:
1663 case 6:
1664 {
1665 if(!silent)printf("cd%d: error class %d code %d\n",
1666 unit,
1667 sense->error_class,
1668 sense->error_code);
1669 if(sense->valid)
1670 if(!silent)printf("block no. %d (decimal)\n",
1671 (sense->ext.unextended.blockhi <<16),
1672 + (sense->ext.unextended.blockmed <<8),
1673 + (sense->ext.unextended.blocklow ));
1674 }
1675 return(EIO);
1676 }
1677 }
1678
1679
1680
1681
1682 int
1683 cdsize(dev_t dev)
1684 {
1685 return (-1);
1686 }
1687
1688 show_mem(address,num)
1689 unsigned char *address;
1690 int num;
1691 {
1692 int x,y;
1693 printf("------------------------------");
1694 for (y = 0; y<num; y += 1)
1695 {
1696 if(!(y % 16))
1697 printf("\n%03d: ",y);
1698 printf("%02x ",*address++);
1699 }
1700 printf("\n------------------------------\n");
1701 }
1702
1703