]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/scsi/cd.c
This is the Linux generic soundcard driver, version 1.0c. Supports
[FreeBSD/FreeBSD.git] / sys / scsi / cd.c
1 /*
2  * Written by Julian Elischer (julian@tfs.com)
3  * for TRW Financial Systems for use under the MACH(2.5) operating system.
4  *
5  * TRW Financial Systems, in accordance with their agreement with Carnegie
6  * Mellon University, makes this software available to CMU to distribute
7  * or use in any manner that they see fit as long as this message is kept with
8  * the software. For this reason TFS also grants any other persons or
9  * organisations permission to use or modify this software.
10  *
11  * TFS supplies this software to be publicly redistributed
12  * on the understanding that TFS is not responsible for the correct
13  * functioning of this software in any circumstances.
14  *
15  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
16  *
17  *      $Id: cd.c,v 1.9 1993/09/20 06:27:02 rgrimes Exp $
18  */
19
20 #define SPLCD splbio
21 #define ESUCCESS 0
22 #include <cd.h>
23 #include <sys/types.h>
24 #include <sys/param.h>
25 #include <sys/dkbad.h>
26 #include <sys/systm.h>
27 #include <sys/conf.h>
28 #include <sys/file.h>
29 #include <sys/stat.h>
30 #include <sys/ioctl.h>
31 #include <sys/buf.h>
32 #include <sys/uio.h>
33 #include <sys/malloc.h>
34 #include <sys/cdio.h>
35
36 #include <sys/errno.h>
37 #include <sys/disklabel.h>
38 #include <scsi/scsi_all.h>
39 #include <scsi/scsi_cd.h>
40 #include <scsi/scsi_disk.h>     /* rw_big and start_stop come from there */
41 #include <scsi/scsiconf.h>
42
43 long int cdstrats,cdqueues;
44
45
46 #include <ddb.h>
47 #if     NDDB > 0
48 int     Debugger();
49 #else   NDDB > 0
50 #define Debugger()
51 #endif  NDDB > 0
52
53
54 #define PAGESIZ         4096
55 #define SECSIZE 2048    /* XXX */ /* default only */
56 #define CDOUTSTANDING   2
57 #define CDQSIZE         4
58 #define CD_RETRIES      4
59
60 #define UNITSHIFT       3
61 #define PARTITION(z)    (minor(z) & 0x07)
62 #define RAW_PART        3
63 #define UNIT(z)         (  (minor(z) >> UNITSHIFT) )
64
65
66 extern  int hz;
67 int     cd_done();
68 int     cdstrategy();
69 int     cd_debug = 0;
70
71
72 struct  cd_data
73 {
74         int     flags;
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*/
84         struct  cd_parms
85         {
86                 int     blksize;
87                 u_long  disksize;               /* total number sectors */
88         }params;
89         struct  disklabel       disklabel;
90         int     partflags[MAXPARTITIONS];       /* per partition flags */
91 #define CDOPEN  0x01
92         int             openparts;              /* one bit for each open partition */
93         int             xfer_block_wait;
94         struct  scsi_xfer       *free_xfer;
95         struct  scsi_xfer       scsi_xfer[CDOUTSTANDING]; /* XXX */
96         struct  buf             buf_queue;
97 };
98
99 #define CD_STOP         0
100 #define CD_START        1
101 #define CD_EJECT        -2
102
103 struct  cd_driver
104 {
105         int     size;
106         struct  cd_data **cd_data;
107 }*cd_driver;
108
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;
116 {
117         int             unit,i;
118         unsigned char   *tbl;
119         struct cd_data  *cd, **cdrealloc;
120         struct cd_parms *dp;
121
122 #ifdef  CDDEBUG
123         if(scsi_debug & PRINTROUTINES) printf("cdattach: "); 
124 #endif  /*CDDEBUG*/
125         /*******************************************************\
126         * Check if we have resources allocated yet, if not      *
127         * allocate and initialize them                          *
128         \*******************************************************/
129         if (next_cd_unit == 0)
130         {
131                 cd_driver =
132                         malloc(sizeof(struct cd_driver),M_DEVBUF,M_NOWAIT);
133                 if(!cd_driver)
134                 {
135                         printf("cd%d: malloc failed for cd_driver\n",unit);
136                         return(0);
137                 }
138                 bzero(cd_driver,sizeof(cd_driver));
139                 cd_driver->size = 0;
140         }
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++;
148         /* XXX
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
153          */
154         if(unit >= cd_driver->size)
155         {
156                 cdrealloc =
157                         malloc(sizeof(cd_driver->cd_data) * next_cd_unit,
158                                 M_DEVBUF,M_NOWAIT);
159                 if(!cdrealloc)
160                 {
161                         printf("cd%d: malloc failed for cdrealloc\n",unit);
162                         return(0);
163                 }
164                 /* Make sure we have something to copy before we copy it */
165                 bzero(cdrealloc,sizeof(cd_driver->cd_data) * next_cd_unit);
166                 if(cd_driver->size)
167                 {
168                         bcopy(cd_driver->cd_data,cdrealloc,
169                                 sizeof(cd_driver->cd_data) * cd_driver->size);
170                         free(cd_driver->cd_data,M_DEVBUF);
171                 }
172                 cd_driver->cd_data = cdrealloc;
173                 cd_driver->cd_data[unit] = NULL;
174                 cd_driver->size++;
175         }
176         if(cd_driver->cd_data[unit])
177         {
178                 printf("cd%d: Already has storage!\n",unit);
179                 return(0);
180         }
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);
186         if(!cd)
187         {
188                 printf("cd%d: malloc failed for cd_data\n",unit);
189                 return(0);
190         }
191         bzero(cd,sizeof(struct cd_data));
192         dp  = &(cd->params);
193         /*******************************************************\
194         * Store information needed to contact our base driver   *
195         \*******************************************************/
196         cd->sc_sw       =       scsi_switch;
197         cd->ctlr        =       ctlr;
198         cd->targ        =       targ;
199         cd->lu          =       lu;
200         cd->cmdscount = CDOUTSTANDING; /* XXX (ask the board) */
201
202         i = cd->cmdscount;
203         while(i-- )
204         {
205                 cd->scsi_xfer[i].next = cd->free_xfer;
206                 cd->free_xfer = &cd->scsi_xfer[i];
207         }
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);
214         if(dp->disksize)
215         {
216                 printf("cd%d: cd present.[%d x %d byte records]\n",
217                                 unit,
218                                 cd->params.disksize,
219                                 cd->params.blksize);
220         }
221         else
222         {
223                 printf("cd%d: drive empty\n", unit);
224         }
225         cd->flags |= CDINIT;
226         return;
227 }
228
229 /*******************************************************\
230 *       open the device. Make sure the partition info   *
231 * is a up-to-date as can be.                            *
232 \*******************************************************/
233 cdopen(dev)
234 {
235         int errcode = 0;
236         int unit, part;
237         struct cd_parms cd_parms;
238         struct cd_data *cd;
239
240         unit = UNIT(dev);
241         part = PARTITION(dev);
242
243 #ifdef  CDDEBUG
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);
247 #endif  /*CDDEBUG*/
248         /*******************************************************\
249         * Check the unit is legal                               *
250         \*******************************************************/
251         if ( unit >= cd_driver->size )
252         {
253                 return(ENXIO);
254         }
255         cd = cd_driver->cd_data[unit];
256         /*******************************************************\
257         * Make sure the device has been initialised             *
258         \*******************************************************/
259         if ((cd == NULL) || (!(cd->flags & CDINIT)))
260                 return(ENXIO);
261
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))
268            && ( cd->openparts))
269                 return(ENXIO);
270
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);
278
279         /*******************************************************\
280         * Next time actually take notice of error returns       *
281         \*******************************************************/
282         if (cd_test_ready(unit, SCSI_SILENT) != 0) {
283 #ifdef  CDDEBUG
284                 if(scsi_debug & TRACEOPENS)
285                         printf("not ready\n");
286 #endif  /*CDDEBUG*/
287                 return(ENXIO);
288         }
289 #ifdef  CDDEBUG
290         if(scsi_debug & TRACEOPENS)
291                 printf("Device present\n");
292 #endif  /*CDDEBUG*/
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);
299 #ifdef  CDDEBUG
300         if(scsi_debug & TRACEOPENS)
301                 printf("started ");
302 #endif  /*CDDEBUG*/
303         /*******************************************************\
304         * Load the physical device parameters                   *
305         \*******************************************************/
306         cd_get_parms(unit, 0);
307 #ifdef  CDDEBUG
308         if(scsi_debug & TRACEOPENS)
309                 printf("Params loaded ");
310 #endif  /*CDDEBUG*/
311         /*******************************************************\
312         * Load the partition info if not already loaded         *
313         \*******************************************************/
314         cdgetdisklabel(unit);
315 #ifdef  CDDEBUG
316         if(scsi_debug & TRACEOPENS)
317                 printf("Disklabel fabricated ");
318 #endif  /*CDDEBUG*/
319         /*******************************************************\
320         * Check the partition is legal                          *
321         \*******************************************************/
322         if (( part >= cd->disklabel.d_npartitions ) 
323                 && (part != RAW_PART))
324         {
325 #ifdef  CDDEBUG
326                 if(scsi_debug & TRACEOPENS)
327                         printf("partition %d > %d\n",part
328                                 ,cd->disklabel.d_npartitions);
329 #endif  /*CDDEBUG*/
330                 cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
331                 return(ENXIO);
332         }
333         /*******************************************************\
334         *  Check that the partition exists                      *
335         \*******************************************************/
336         if (( cd->disklabel.d_partitions[part].p_fstype != FS_UNUSED )
337                 || (part == RAW_PART))
338         {
339                 cd->partflags[part] |= CDOPEN;
340                 cd->openparts |= (1 << part);
341 #ifdef  CDDEBUG
342                 if(scsi_debug & TRACEOPENS)
343                         printf("open complete\n");
344 #endif  /*CDDEBUG*/
345                 cd->flags |= CDVALID;
346         }
347         else
348         {
349 #ifdef  CDDEBUG
350                 if(scsi_debug & TRACEOPENS)
351                         printf("part %d type UNUSED\n",part);
352 #endif  /*CDDEBUG*/
353                 cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT);
354                 return(ENXIO);
355         }
356         return(0);
357 }
358
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)
364 int     flags;
365 int     unit;
366 {
367         struct scsi_xfer *xs;
368         struct cd_data *cd;
369         int     s;
370
371         cd = cd_driver->cd_data[unit];
372         if(flags & (SCSI_NOSLEEP |  SCSI_NOMASK))
373         {
374                 if (xs = cd->free_xfer)
375                 {
376                         cd->free_xfer = xs->next;
377                         xs->flags = 0;
378                 }
379         }
380         else
381         {
382                 s = SPLCD();
383                 while (!(xs = cd->free_xfer))
384                 {
385                         cd->xfer_block_wait++;  /* someone waiting! */
386                         sleep((caddr_t)&cd->free_xfer, PRIBIO+1);
387                         cd->xfer_block_wait--;
388                 }
389                 cd->free_xfer = xs->next;
390                 splx(s);
391                 xs->flags = 0;
392         }
393         return(xs);
394 }
395
396 /*******************************************************\
397 * Free a scsi_xfer, wake processes waiting for it       *
398 \*******************************************************/
399 cd_free_xs(unit,xs,flags)
400 struct scsi_xfer *xs;
401 int     unit;
402 int     flags;
403 {
404         struct cd_data *cd;
405         int     s;
406         
407         cd = cd_driver->cd_data[unit];
408         if(flags & SCSI_NOMASK)
409         {
410                 if (cd->xfer_block_wait)
411                 {
412                         printf("cd%d: doing a wakeup from NOMASK mode\n", unit);
413                         wakeup((caddr_t)&cd->free_xfer);
414                 }
415                 xs->next = cd->free_xfer;
416                 cd->free_xfer = xs;
417         }
418         else
419         {
420                 s = SPLCD();
421                 if (cd->xfer_block_wait)
422                         wakeup((caddr_t)&cd->free_xfer);
423                 xs->next = cd->free_xfer;
424                 cd->free_xfer = xs;
425                 splx(s);
426         }
427 }
428
429 /*******************************************************\
430 * trim the size of the transfer if needed,              *
431 * called by physio                                      *
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 */
436 void    cdminphys(bp)
437 struct buf      *bp;
438 {
439         (*(cd_driver->cd_data[UNIT(bp->b_dev)]->sc_sw->scsi_minphys))(bp);
440 }
441
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 \*******************************************************/
448
449 int     cdstrategy(bp)
450 struct  buf     *bp;
451 {
452         struct  buf     *dp;
453         unsigned int opri;
454         struct cd_data *cd;
455         int     unit;
456
457         cdstrats++;
458         unit = UNIT((bp->b_dev));
459         cd = cd_driver->cd_data[unit];
460 #ifdef  CDDEBUG
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);
464 #endif  /*CDDEBUG*/
465         cdminphys(bp);
466         /*******************************************************\
467         * If the device has been made invalid, error out        *
468         * maybe the media changed                               *
469         \*******************************************************/
470         if(!(cd->flags & CDVALID))
471         {
472                 bp->b_error = EIO;
473                 goto bad;
474         }
475         /*******************************************************\
476         * can't ever write to a CD                              *
477         \*******************************************************/
478         if ((bp->b_flags & B_READ) == 0) {
479                 bp->b_error = EROFS;
480                 goto bad;
481         }
482         /*******************************************************\
483         * If it's a null transfer, return immediatly            *
484         \*******************************************************/
485         if (bp->b_bcount == 0) {
486                 goto done;
487         }
488
489         /*******************************************************\
490         * Decide which unit and partition we are talking about  *
491         \*******************************************************/
492         if(PARTITION(bp->b_dev) != RAW_PART)
493         {
494                 if (!(cd->flags & CDHAVELABEL))
495                 {
496                         bp->b_error = EIO;
497                         goto bad;
498                 }
499                 /*
500                  * do bounds checking, adjust transfer. if error, process.
501                  * if end of partition, just return
502                  */
503                 if (bounds_check_with_label(bp,&cd->disklabel,1) <= 0)
504                         goto done;
505                 /* otherwise, process transfer request */
506         }
507
508         opri = SPLCD();
509         dp = &cd->buf_queue;
510
511         /*******************************************************\
512         * Place it in the queue of disk activities for this disk*
513         \*******************************************************/
514         disksort(dp, bp);
515
516         /*******************************************************\
517         * Tell the device to get going on the transfer if it's  *
518         * not doing anything, otherwise just wait for completion*
519         \*******************************************************/
520         cdstart(unit);
521
522         splx(opri);
523         return;
524 bad:
525         bp->b_flags |= B_ERROR;
526 done:
527
528         /*******************************************************\
529         * Correctly set the buf to indicate a completed xfer    *
530         \*******************************************************/
531         bp->b_resid = bp->b_bcount;
532         biodone(bp);
533         return;
534 }
535
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)      *
544 *                                                               *
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.                                      *
548 *                                                               *
549 * must be called at the correct (highish) spl level             *
550 \***************************************************************/
551 /* cdstart() is called at SPLCD  from cdstrategy and cd_done*/
552 cdstart(unit)
553 int     unit;
554 {
555         register struct buf     *bp = 0;
556         register struct buf     *dp;
557         struct  scsi_xfer       *xs;
558         struct  scsi_rw_big     cmd;
559         int                     blkno, nblk;
560         struct cd_data *cd;
561         struct partition *p ;
562
563 #ifdef  CDDEBUG
564         if(scsi_debug & PRINTROUTINES) printf("cdstart%d ",unit);
565 #endif  /*CDDEBUG*/
566         cd = cd_driver->cd_data[unit];
567         /*******************************************************\
568         * See if there is a buf to do and we are not already    *
569         * doing one                                             *
570         \*******************************************************/
571         if(!cd->free_xfer)
572         {
573                 return;    /* none for us, unit already underway */
574         }
575
576         if(cd->xfer_block_wait)    /* there is one, but a special waits */
577         {
578                 return; /* give the special that's waiting a chance to run */
579         }
580
581
582         dp = &cd->buf_queue;
583         if ((bp = dp->b_actf) != NULL)  /* yes, an assign */
584         {
585                 dp->b_actf = bp->av_forw;
586         }
587         else
588         { 
589                 return;
590         }
591
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))
598         {
599                 goto bad; /* no I/O.. media changed or something */
600         }
601
602         /*******************************************************\
603         * We have a buf, now we should move the data into       *
604         * a scsi_xfer definition and try start it               *
605         *                                                       *
606         *  First, translate the block to absolute               *
607         * and put it in terms of the logical blocksize of the   *
608         * device..                                              *
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)
613         {
614                 p = cd->disklabel.d_partitions + PARTITION(bp->b_dev);
615                 blkno += p->p_offset;
616         }
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*/
619
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;
637         xs->targ        =       cd->targ;
638         xs->lu          =       cd->lu;
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;
645         xs->done_arg    =       unit;
646         xs->done_arg2   =       (int)xs;
647         xs->error       =       XS_NOERROR;
648         xs->bp          =       bp;
649         xs->data        =       (u_char *)bp->b_un.b_addr;
650         xs->datalen     =       bp->b_bcount;
651
652         /*******************************************************\
653         * Pass all this info to the scsi driver.                *
654         \*******************************************************/
655         if ( (*(cd->sc_sw->scsi_cmd))(xs) != SUCCESSFULLY_QUEUED)
656         {
657                 printf("cd%d: oops not queued",unit);
658                 goto bad;
659         }       
660         cdqueues++;
661         return;
662 bad:    xs->error = XS_DRIVER_STUFFUP;
663         cd_done(unit,xs);
664 }
665
666 /*******************************************************\
667 * This routine is called by the scsi interrupt when     *
668 * the transfer is complete. (or failed)                 *
669 \*******************************************************/
670 int     cd_done(unit,xs)
671 int     unit;
672 struct  scsi_xfer       *xs;
673 {
674         struct  buf             *bp;
675         int     retval;
676         struct cd_data *cd = cd_driver->cd_data[unit];
677
678 #ifdef  CDDEBUG
679         if(scsi_debug & PRINTROUTINES) printf("cd_done%d ",unit);
680 #endif  /*CDDEBUG*/
681 #ifdef  PARANOIA
682         if (! (xs->flags & INUSE))      /* paranoia always pays off */
683                 panic("scsi_xfer not in use!");
684 #endif  /*PARANOIA*/
685         if(!(bp = xs->bp))
686         {
687                 wakeup(xs);
688                 return 0;
689         }
690         switch(xs->error)
691         {
692         case    XS_NOERROR:
693                 bp->b_error = 0;
694                 bp->b_resid = 0;
695                 break;
696
697         case    XS_SENSE:
698                 retval = (cd_interpret_sense(unit,xs));
699                 if(retval)
700                 {
701                         bp->b_flags |= B_ERROR;
702                         bp->b_error = retval;
703                 }
704                 break;
705
706         case    XS_TIMEOUT:
707                 printf("cd%d timeout\n",unit);
708
709         case    XS_BUSY:        
710                 /***********************************\
711                 * Just resubmit it straight back to *
712                 * the SCSI driver to try it again   *
713                 \***********************************/
714                 if(xs->retries--)
715                 {
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, */
722                                 return 0;
723                         }
724                         /* xs->error is set by the scsi driver */
725                 } /* Fall through */
726
727         case    XS_DRIVER_STUFFUP:
728                 bp->b_flags |= B_ERROR;
729                 bp->b_error = EIO;
730                 break;
731         default:
732                 printf("cd%d: unknown error category from scsi driver\n"
733                         ,unit);
734         }       
735         biodone(bp);
736         cd_free_xs(unit,xs,0);
737         cdstart(unit);  /* If there's anything waiting.. do it */
738         return 0;
739 }
740
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)
746 {
747         int error = 0;
748         unsigned int opri;
749         unsigned char unit, part;
750         register struct cd_data *cd;
751
752
753         /*******************************************************\
754         * Find the device that the user is talking about        *
755         \*******************************************************/
756         unit = UNIT(dev);
757         part = PARTITION(dev);
758         cd = cd_driver->cd_data[unit];
759 #ifdef  CDDEBUG
760         if(scsi_debug & PRINTROUTINES) printf("cdioctl%d ",unit);
761 #endif  /*CDDEBUG*/
762
763         /*******************************************************\
764         * If the device is not valid.. abandon ship             *
765         \*******************************************************/
766         if (!(cd_driver->cd_data[unit]->flags & CDVALID))
767                 return(EIO);
768         switch(cmd)
769         {
770
771         case DIOCSBAD:
772                         error = EINVAL;
773                 break;
774
775         case DIOCGDINFO:
776                 *(struct disklabel *)addr = cd->disklabel;
777                 break;
778
779         case DIOCGPART:
780                 ((struct partinfo *)addr)->disklab = &cd->disklabel;
781                 ((struct partinfo *)addr)->part =
782                     &cd->disklabel.d_partitions[PARTITION(dev)];
783                 break;
784
785         case DIOCWDINFO:
786         case DIOCSDINFO:
787                 if ((flag & FWRITE) == 0)
788                         error = EBADF;
789                 else
790                         error = setdisklabel(&cd->disklabel,
791                                         (struct disklabel *)addr,
792                          /*(cd->flags & DKFL_BSDLABEL) ? cd->openparts : */0,
793                                 0);
794                 if (error == 0) {
795                         cd->flags |= CDHAVELABEL;
796                 }
797                 break;
798
799         case DIOCWLABEL:
800                 error = EBADF;
801                 break;
802
803         case CDIOCPLAYTRACKS:
804                 {
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))
809                                 break;
810                         data.page.audio.flags &= ~CD_PA_SOTC;
811                         data.page.audio.flags |= CD_PA_IMMED;
812                         if(error = cd_set_mode(unit,&data))
813                                 break;
814                         return(cd_play_tracks(unit
815                                                 ,args->start_track
816                                                 ,args->start_index
817                                                 ,args->end_track
818                                                 ,args->end_index
819                                                 ));
820                 }
821                 break;
822         case CDIOCPLAYMSF:
823                 {
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))
828                                 break;
829                         data.page.audio.flags &= ~CD_PA_SOTC;
830                         data.page.audio.flags |= CD_PA_IMMED;
831                         if(error = cd_set_mode(unit,&data))
832                                 break;
833                         return(cd_play_msf(unit
834                                                 ,args->start_m
835                                                 ,args->start_s
836                                                 ,args->start_f
837                                                 ,args->end_m
838                                                 ,args->end_s
839                                                 ,args->end_f
840                                                 ));
841                 }
842                 break;
843         case CDIOCPLAYBLOCKS:
844                 {
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))
849                                 break;
850                         data.page.audio.flags &= ~CD_PA_SOTC;
851                         data.page.audio.flags |= CD_PA_IMMED;
852                         if(error = cd_set_mode(unit,&data))
853                                 break;
854                         return(cd_play(unit,args->blk,args->len));
855
856
857                 }
858                 break;
859         case CDIOCREADSUBCHANNEL:
860                 {
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)) {
867                                 error=EINVAL;
868                                 break;
869                         }
870                         if(error = cd_read_subchannel(unit,args->address_format,
871                                         args->data_format,args->track,&data,len)) {
872                                 break;
873                         }
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) {
877                                 error=EFAULT;
878                         }
879                 }
880                 break;
881         case CDIOREADTOCHEADER:
882                 {
883                         struct ioc_toc_header th;
884                         if( error = cd_read_toc(unit,0,0,&th,sizeof(th)))
885                                 break;
886                         th.len=(th.len&0xff)<<8+((th.len>>8)&0xff);
887                         bcopy(&th,addr,sizeof(th));
888                 }
889                 break;
890         case CDIOREADTOCENTRYS:
891                 {
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;
898
899                         if(len>sizeof(data) || len<sizeof(struct cd_toc_entry)) {
900                                 error=EINVAL;
901                                 break;
902                         }
903                         if(error = cd_read_toc(unit,te->address_format,
904                                                     te->starting_track,
905                                                     data,
906                                                     len))
907                                 break;
908                         len=MIN(len,((((th->len&0xff)<<8)+((th->len>>8)))+
909                                                                 sizeof(*th)));
910                         if(copyout(th,te->data,len)!=0) {
911                                 error=EFAULT;
912                         }
913                         
914                 }
915                 break;
916         case CDIOCSETPATCH:
917                 {
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))
921                                 break;
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))
927                                 break;
928                 }
929                 break;
930         case CDIOCGETVOL:
931                 {
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))
935                                 break;
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;
940                 }
941                 break;
942         case CDIOCSETVOL:
943                 {
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))
947                                 break;
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))
953                                 break;
954                 }
955                 break;
956         case CDIOCSETMONO:
957                 {
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))
961                                 break;
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))
967                                 break;
968                 }
969                 break;
970         case CDIOCSETSTERIO:
971                 {
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))
975                                 break;
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))
981                                 break;
982                 }
983                 break;
984         case CDIOCSETMUTE:
985                 {
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))
989                                 break;
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))
995                                 break;
996                 }
997                 break;
998         case CDIOCSETLEFT:
999                 {
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))
1003                                 break;
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))
1009                                 break;
1010                 }
1011                 break;
1012         case CDIOCSETRIGHT:
1013                 {
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))
1017                                 break;
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))
1023                                 break;
1024                 }
1025                 break;
1026         case CDIOCRESUME:
1027                 error = cd_pause(unit,1);
1028                 break;
1029         case CDIOCPAUSE:
1030                 error = cd_pause(unit,0);
1031                 break;
1032         case CDIOCSTART:
1033                 error = cd_start_unit(unit,part,CD_START);
1034                 break;
1035         case CDIOCSTOP:
1036                 error = cd_start_unit(unit,part,CD_STOP);
1037                 break;
1038         case CDIOCEJECT:
1039                 error = cd_start_unit(unit,part,CD_EJECT);
1040                 break;
1041         case CDIOCSETDEBUG:
1042                 scsi_debug = 0xfff; cd_debug = 0xfff;
1043                 break;
1044         case CDIOCCLRDEBUG:
1045                 scsi_debug = 0; cd_debug = 0;
1046                 break;
1047         case CDIOCRESET:
1048                 return(cd_reset(unit));
1049                 break;
1050         default:
1051                 error = ENOTTY;
1052                 break;
1053         }
1054         return (error);
1055 }
1056
1057
1058 /*******************************************************\
1059 * Load the label information on the named device        *
1060 *                                                       *
1061 * EVENTUALLY take information about different           *
1062 * data tracks from the TOC and put it in the disklabel  *
1063 \*******************************************************/
1064 int cdgetdisklabel(unit)
1065 unsigned char   unit;
1066 {
1067         /*unsigned int n, m;*/
1068         char *errstring;
1069         struct dos_partition *dos_partition_p;
1070         struct cd_data *cd;
1071
1072         cd = cd_driver->cd_data[unit];
1073         /*******************************************************\
1074         * If the info is already loaded, use it                 *
1075         \*******************************************************/
1076         if(cd->flags & CDHAVELABEL) return;
1077
1078         bzero(&cd->disklabel,sizeof(struct disklabel));
1079         /*******************************************************\
1080         * make partition 3 the whole disk in case of failure    *
1081         *   then get pdinfo                                     *
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;
1094
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;
1100
1101         cd->disklabel.d_magic = DISKMAGIC;
1102         cd->disklabel.d_magic2 = DISKMAGIC;
1103         cd->disklabel.d_checksum = dkcksum(&(cd->disklabel));
1104
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;
1110         return(ESUCCESS);
1111 }
1112
1113 /*******************************************************\
1114 * Get scsi driver to send a "are you ready" command     *
1115 \*******************************************************/
1116 cd_test_ready(unit,flags)
1117 int     unit,flags;
1118 {
1119         struct  scsi_test_unit_ready scsi_cmd;
1120
1121         bzero(&scsi_cmd, sizeof(scsi_cmd));
1122         scsi_cmd.op_code = TEST_UNIT_READY;
1123
1124         return (cd_scsi_cmd(unit,
1125                         &scsi_cmd,
1126                         sizeof(scsi_cmd),
1127                         0,
1128                         0,
1129                         100000,
1130                         NULL,
1131                         flags));
1132 }
1133
1134
1135 /*******************************************************\
1136 * Find out form the device what it's capacity is        *
1137 \*******************************************************/
1138 cd_size(unit, flags)
1139 {
1140         struct  scsi_read_cd_cap_data   rdcap;
1141         struct  scsi_read_cd_capacity   scsi_cmd;
1142         int size;
1143         int     blksize;
1144
1145         /*******************************************************\
1146         * make up a scsi command and ask the scsi driver to do  *
1147         * it for you.                                           *
1148         \*******************************************************/
1149         bzero(&scsi_cmd, sizeof(scsi_cmd));
1150         scsi_cmd.op_code = READ_CD_CAPACITY;
1151
1152         /*******************************************************\
1153         * If the command works, interpret the result as a 4 byte*
1154         * number of blocks                                      *
1155         \*******************************************************/
1156         if (cd_scsi_cmd(unit,
1157                         &scsi_cmd,
1158                         sizeof(scsi_cmd),
1159                         &rdcap,
1160                         sizeof(rdcap),  
1161                         2000,
1162                         NULL,
1163                         flags) != 0)
1164         {
1165                 printf("cd%d: could not get size\n", unit);
1166                 return(0);
1167         } else {
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;
1176         }
1177 #ifdef  CDDEBUG
1178         if(cd_debug)printf("cd%d: %d %d byte blocks\n",unit,size,blksize);
1179 #endif  /*CDDEBUG*/
1180         cd_driver->cd_data[unit]->params.disksize = size;
1181         cd_driver->cd_data[unit]->params.blksize = blksize;
1182         return(size);
1183 }
1184         
1185
1186 /*******************************************************\
1187 * Get the requested page into the buffer given          *
1188 \*******************************************************/
1189 cd_get_mode(unit,data,page)
1190 int     unit;
1191 struct  cd_mode_data *data;
1192 int     page;
1193 {
1194         struct scsi_mode_sense scsi_cmd;
1195         int     retval;
1196
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,
1203                         &scsi_cmd,
1204                         sizeof(scsi_cmd),
1205                         data,
1206                         sizeof(*data),
1207                         20000,  /* should be immed */
1208                         NULL,
1209                         0);
1210         return (retval);
1211 }
1212 /*******************************************************\
1213 * Get the requested page into the buffer given          *
1214 \*******************************************************/
1215 cd_set_mode(unit,data)
1216 int     unit;
1217 struct  cd_mode_data *data;
1218 {
1219         struct scsi_mode_select scsi_cmd;
1220
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,
1228                         &scsi_cmd,
1229                         sizeof(scsi_cmd),
1230                         data,
1231                         sizeof(*data),
1232                         20000,  /* should be immed */
1233                         NULL,
1234                         0)
1235         ); 
1236 }
1237 /*******************************************************\
1238 * Get scsi driver to send a "start playing" command     *
1239 \*******************************************************/
1240 cd_play(unit,blk,len)
1241 int     unit,blk,len;
1242 {
1243         struct scsi_play scsi_cmd;
1244         int     retval;
1245
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,
1255                         &scsi_cmd,
1256                         sizeof(scsi_cmd),
1257                         0,
1258                         0,
1259                         200000, /* should be immed */
1260                         NULL,
1261                         0);
1262         return(retval);
1263 }
1264 /*******************************************************\
1265 * Get scsi driver to send a "start playing" command     *
1266 \*******************************************************/
1267 cd_play_big(unit,blk,len)
1268 int     unit,blk,len;
1269 {
1270         struct scsi_play_big scsi_cmd;
1271         int     retval;
1272
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,
1284                         &scsi_cmd,
1285                         sizeof(scsi_cmd),
1286                         0,
1287                         0,
1288                         20000,  /* should be immed */
1289                         NULL,
1290                         0);
1291         return(retval);
1292 }
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;
1298 {
1299         struct scsi_play_track scsi_cmd;
1300         int     retval;
1301
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,
1309                         &scsi_cmd,
1310                         sizeof(scsi_cmd),
1311                         0,
1312                         0,
1313                         20000,  /* should be immed */
1314                         NULL,
1315                         0);
1316         return(retval);
1317 }
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;
1323 {
1324         struct scsi_play_msf scsi_cmd;
1325
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;
1334
1335         return (cd_scsi_cmd(unit,
1336                         &scsi_cmd,
1337                         sizeof(scsi_cmd),
1338                         0,
1339                         0,
1340                         2000,
1341                         NULL,
1342                         0));
1343 }
1344 /*******************************************************\
1345 * Get scsi driver to send a "start up" command          *
1346 \*******************************************************/
1347 cd_pause(unit,go)
1348 int     unit,go;
1349 {
1350         struct scsi_pause scsi_cmd;
1351
1352         bzero(&scsi_cmd, sizeof(scsi_cmd));
1353         scsi_cmd.op_code = PAUSE;
1354         scsi_cmd.resume = go;
1355
1356         return (cd_scsi_cmd(unit,
1357                         &scsi_cmd,
1358                         sizeof(scsi_cmd),
1359                         0,
1360                         0,
1361                         2000,
1362                         NULL,
1363                         0));
1364 }
1365 /*******************************************************\
1366 * Get scsi driver to send a "RESET" command             *
1367 \*******************************************************/
1368 cd_reset(unit)
1369 int     unit;
1370 {
1371         return(cd_scsi_cmd(unit,
1372                         0,
1373                         0,
1374                         0,
1375                         0,
1376                         2000,
1377                         NULL,
1378                         SCSI_RESET));
1379 }
1380 /*******************************************************\
1381 * Get scsi driver to send a "start up" command          *
1382 \*******************************************************/
1383 cd_start_unit(unit,part,type)
1384 {
1385         struct scsi_start_stop scsi_cmd;
1386         struct cd_data *cd = cd_driver->cd_data[unit];
1387
1388         if(type==CD_EJECT
1389         /*&& (cd->openparts  == 0)*/)/* trouble is WE have it open *//*XXX*/
1390         {
1391                 cd_prevent_unit(unit,PR_ALLOW,0);
1392         }
1393
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;
1398
1399         if (cd_scsi_cmd(unit,
1400                         &scsi_cmd,
1401                         sizeof(scsi_cmd),
1402                         0,
1403                         0,
1404                         2000,
1405                         NULL,
1406                         0) != 0) {
1407                 return(ENXIO);
1408         } else 
1409                 return(0);
1410 }
1411 /*******************************************************\
1412 * Prevent or allow the user to remove the disk          *
1413 \*******************************************************/
1414 cd_prevent_unit(unit,type,flags)
1415 int     unit,type,flags;
1416 {
1417         struct  scsi_prevent    scsi_cmd;
1418         struct cd_data *cd = cd_driver->cd_data[unit];
1419
1420         if(type==PR_PREVENT
1421         || ( type==PR_ALLOW && cd->openparts == 0 ))/*XXX*/
1422         {
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,
1427                         &scsi_cmd,
1428                         sizeof(struct   scsi_prevent),
1429                         0,
1430                         0,
1431                         5000,
1432                         NULL,
1433                         0) != 0)
1434                 {
1435                  if(!(flags & SCSI_SILENT))
1436                          printf("cd%d: cannot prevent/allow\n", unit);
1437                  return(0);
1438                 }
1439         }
1440         return(1);
1441 }
1442
1443 /******************************************************\
1444 * Read Subchannel                                      *
1445 \******************************************************/
1446
1447 cd_read_subchannel(unit,mode,format,track,data,len)
1448 int unit,mode,format,len;
1449 struct cd_sub_channel_info *data;
1450 {
1451         struct scsi_read_subchannel scsi_cmd;
1452         int error;
1453
1454         bzero(&scsi_cmd,sizeof(scsi_cmd));
1455
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,
1465                 &scsi_cmd,
1466                 sizeof(struct   scsi_read_subchannel),
1467                 data,
1468                 len,
1469                 5000,
1470                 NULL,
1471                 0);
1472 }
1473
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;
1480 {
1481         struct scsi_read_toc scsi_cmd;
1482         int error;
1483         int ntoc;
1484         
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);
1488           else*/
1489            ntoc=len;
1490
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,
1498                 &scsi_cmd,
1499                 sizeof(struct   scsi_read_toc),
1500                 data,
1501                 len,
1502                 5000,
1503                 NULL,
1504                 0);
1505 }
1506
1507
1508 #define b2tol(a)        (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
1509
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 \*******************************************************/
1515
1516 int     cd_get_parms(unit, flags)
1517 {
1518         struct cd_data *cd = cd_driver->cd_data[unit];
1519
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    *
1526         * is <= disk_size                                       *
1527         \*******************************************************/
1528         if(cd_size(unit, flags))
1529         {
1530                 cd->flags |= CDVALID;
1531                 return(0);
1532         }
1533         else
1534         {
1535                 return(ENXIO);
1536         }
1537 }
1538
1539 /*******************************************************\
1540 * close the device.. only called if we are the LAST     *
1541 * occurence of an open device                           *
1542 \*******************************************************/
1543 cdclose(dev)
1544 dev_t dev;
1545 {
1546         unsigned char unit, part;
1547         unsigned int old_priority;
1548
1549         unit = UNIT(dev);
1550         part = PARTITION(dev);
1551 #ifdef  CDDEBUG
1552         if(scsi_debug & TRACEOPENS)
1553                 printf("cd%d: closing part %d\n",unit,part);
1554 #endif
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);
1558         return(0);
1559 }
1560
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)
1571
1572 int     unit,flags;
1573 struct  scsi_generic *scsi_cmd;
1574 int     cmdlen;
1575 int     timeout;
1576 u_char  *data_addr;
1577 int     datalen;
1578 struct  buf     *bp;
1579 {
1580         struct  scsi_xfer *xs;
1581         int     retval;
1582         int     s;
1583         struct cd_data *cd = cd_driver->cd_data[unit];
1584
1585 #ifdef  CDDEBUG
1586         if(scsi_debug & PRINTROUTINES) printf("\ncd_scsi_cmd%d ",unit);
1587 #endif  /*CDDEBUG*/
1588 #ifdef  PARANOID
1589         if(!(cd->sc_sw))        /* If we have a scsi driver */
1590         {
1591                 /* !? how'd we GET here? */
1592                 panic("attempt to run bad cd device");
1593         }
1594 #endif  /*PARANOID*/
1595         xs = cd_get_xs(unit,flags); /* should wait unless booting */
1596         if(!xs)
1597         {
1598                 printf("cd%d: scsi_cmd controller busy"
1599                                 " (this should never happen)\n",unit); 
1600                         return(EBUSY);
1601         }
1602         xs->flags |= INUSE;
1603         /*******************************************************\
1604         * Fill out the scsi_xfer structure                      *
1605         \*******************************************************/
1606         xs->flags       |=      flags;
1607         xs->adapter     =       cd->ctlr;
1608         xs->targ        =       cd->targ;
1609         xs->lu          =       cd->lu;
1610         xs->retries     =       CD_RETRIES;
1611         xs->timeout     =       timeout;
1612         xs->cmd         =       scsi_cmd;
1613         xs->cmdlen      =       cmdlen;
1614         xs->data        =       data_addr;
1615         xs->datalen     =       datalen;
1616         xs->resid       =       datalen;
1617         xs->when_done   =       (flags & SCSI_NOMASK)
1618                                 ?(int (*)())0
1619                                 :cd_done;
1620         xs->done_arg    =       unit;
1621         xs->done_arg2   =       (int)xs;
1622         xs->bp          =       bp;
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   *
1629         *                                                       *
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 *
1635         *                                                       *
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 */
1642
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         \*******************************************************/
1648         switch(retval)
1649         {
1650         case    SUCCESSFULLY_QUEUED:
1651                 s = splbio();
1652                 while(!(xs->flags & ITSDONE))
1653                         sleep(xs,PRIBIO+1);
1654                 splx(s);
1655                 /* Fall through to check the result */
1656
1657         case    HAD_ERROR:
1658                 switch(xs->error)
1659                 {
1660                 case    XS_NOERROR:     /* usually this one */
1661                         retval = ESUCCESS;
1662                         break;
1663
1664                 case    XS_SENSE:
1665                         retval = (cd_interpret_sense(unit,xs));
1666                         break;
1667                 case    XS_BUSY:
1668                         /* should sleep here 1 sec */
1669                         /* fall through */
1670                 case    XS_TIMEOUT:
1671                         if(xs->retries-- )
1672                         {
1673                                 xs->flags &= ~ITSDONE;
1674                                 goto retry;
1675                         }
1676                         /* fall through */
1677                 case    XS_DRIVER_STUFFUP:
1678                         retval = EIO;
1679                         break;
1680                 default:
1681                         retval = EIO;
1682                         printf("cd%d: unknown error category from scsi driver\n"
1683                                 ,unit);
1684                 }       
1685                 break;
1686         case    COMPLETE:
1687                 retval = ESUCCESS;
1688                 break;
1689
1690         case    TRY_AGAIN_LATER:
1691                 if(xs->retries-- )
1692                 {
1693                         if(tsleep( 0,PRIBIO + 2,"retry",hz * 2))
1694                         {
1695                                 xs->flags &= ~ITSDONE;
1696                                 goto retry;
1697                         }
1698                 }
1699                 /* fall through */
1700         default:
1701                 retval = EIO;
1702         }
1703
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 */
1710         return(retval);
1711 }
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 \***************************************************************/
1716
1717 int     cd_interpret_sense(unit,xs)
1718 int     unit;
1719 struct  scsi_xfer *xs;
1720 {
1721         struct  scsi_sense_data *sense;
1722         int     key;
1723         int     silent;
1724         int     info;
1725         struct cd_data *cd = cd_driver->cd_data[unit];
1726
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"
1735         };
1736
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);
1742
1743         sense = &(xs->sense);
1744 #ifdef  CDDEBUG
1745         if(cd_debug)
1746         {
1747                 int count = 0;
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);
1763                 printf("extra: ");
1764                 while(count < sense->ext.extended.extra_len)
1765                 {
1766                         printf ("%x ",sense->ext.extended.extra_bytes[count++]);
1767                 }
1768                 printf("\n");
1769         }
1770 #endif  /*CDDEBUG*/
1771         switch(sense->error_code & SSD_ERRCODE)
1772         {
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);
1778         case 0x70:
1779                 if(sense->error_code & SSD_ERRCODE_VALID)
1780                 {
1781                         info = ntohl(*((long *)sense->ext.extended.info));
1782                 }
1783                 else
1784                 {
1785                         info = 0;
1786                 }
1787         
1788                 key=sense->ext.extended.flags & SSD_KEY;
1789         
1790                 if (!silent)
1791                 {
1792                         printf("cd%d: %s", unit, error_mes[key - 1]);
1793                         if(sense->error_code & SSD_ERRCODE_VALID)
1794                         {
1795                                 switch (key)
1796                                 {
1797                                 case    0x2:            /* NOT READY */
1798                                 case    0x5:            /* ILLEGAL REQUEST */
1799                                 case    0x6:            /* UNIT ATTENTION */
1800                                 case    0x7:            /* DATA PROTECT */
1801                                         break;
1802                                 case    0x8:            /* BLANK CHECK */
1803                                         printf(", requested size: %d (decimal)",
1804                                         info);
1805                                         break;
1806                                 default:
1807                                         printf(", info = %d (decimal)", info);
1808                                 }
1809                         }
1810                         printf("\n");
1811                 }
1812         
1813                 switch (key)
1814                 {
1815                 case    0x0:                            /* NO SENSE */
1816                 case    0x1:                            /* RECOVERED ERROR */
1817                         xs->resid = 0;
1818                 case    0xc:                            /* EQUAL */
1819                         return(ESUCCESS);
1820                 case    0x2:                            /* NOT READY */
1821                         cd->flags &= ~(CDVALID | CDHAVELABEL);
1822                         return(ENODEV);
1823                 case    0x5:                            /* ILLEGAL REQUEST */
1824                         return(EINVAL);
1825                 case    0x6:                            /* UNIT ATTENTION */
1826                         cd->flags &= ~(CDVALID | CDHAVELABEL);
1827                         if (cd->openparts)
1828                         {
1829                                 return(EIO);
1830                         }
1831                         return(ESUCCESS);
1832                 case    0x7:                            /* DATA PROTECT */
1833                         return(EACCES);
1834                 case    0xd:                            /* VOLUME OVERFLOW */
1835                         return(ENOSPC);
1836                 case    0x8:                            /* BLANK CHECK */
1837                         return(ESUCCESS);
1838                 default:
1839                         return(EIO);
1840                 }
1841         /*******************************\
1842         * Not code 70, just report it   *
1843         \*******************************/
1844         default:
1845                 if(!silent)
1846                 {
1847                         printf("cd%d: error code %d", unit,
1848                                 sense->error_code & SSD_ERRCODE);
1849                         if(sense->error_code & SSD_ERRCODE_VALID)
1850                         {
1851                                 printf(" at block no. %d (decimal)",
1852                                         (sense->ext.unextended.blockhi <<16)
1853                                         + (sense->ext.unextended.blockmed <<8)
1854                                         + (sense->ext.unextended.blocklow ));
1855                         }       
1856                         printf("\n");
1857                 }
1858                 return(EIO);
1859         }
1860 }
1861
1862
1863
1864
1865 int
1866 cdsize(dev_t dev)
1867 {
1868         return (-1);
1869 }
1870
1871 #if 0
1872 show_mem(address,num)
1873 unsigned char   *address;
1874 int     num;
1875 {
1876         int x,y;
1877         printf("------------------------------");
1878         for (y = 0; y<num; y += 1)
1879         {
1880                 if(!(y % 16))
1881                         printf("\n%03d: ",y);
1882                 printf("%02x ",*address++);
1883         }
1884         printf("\n------------------------------\n");
1885 }
1886 #endif