This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.0'.
[unix-history] / sys / scsi / cd.c
CommitLineData
15637ed4
RG
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 *
15637ed4
RG
15 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
16 *
78ed81a3 17 * $Id: cd.c,v 1.9 1993/09/20 06:27:02 rgrimes Exp $
15637ed4
RG
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
43long int cdstrats,cdqueues;
44
45
46#include <ddb.h>
47#if NDDB > 0
48int 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
66extern int hz;
67int cd_done();
68int cdstrategy();
69int cd_debug = 0;
70
15637ed4
RG
71
72struct 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 */
78ed81a3 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};
15637ed4
RG
98
99#define CD_STOP 0
100#define CD_START 1
101#define CD_EJECT -2
102
78ed81a3 103struct cd_driver
104{
105 int size;
106 struct cd_data **cd_data;
107}*cd_driver;
15637ed4
RG
108
109static 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\***********************************************************************/
114int cdattach(ctlr,targ,lu,scsi_switch)
115struct scsi_switch *scsi_switch;
116{
78ed81a3 117 int unit,i;
118 unsigned char *tbl;
119 struct cd_data *cd, **cdrealloc;
120 struct cd_parms *dp;
15637ed4 121
78ed81a3 122#ifdef CDDEBUG
15637ed4 123 if(scsi_debug & PRINTROUTINES) printf("cdattach: ");
78ed81a3 124#endif /*CDDEBUG*/
15637ed4 125 /*******************************************************\
78ed81a3 126 * Check if we have resources allocated yet, if not *
127 * allocate and initialize them *
15637ed4 128 \*******************************************************/
78ed81a3 129 if (next_cd_unit == 0)
15637ed4 130 {
78ed81a3 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);
15637ed4
RG
189 return(0);
190 }
78ed81a3 191 bzero(cd,sizeof(struct cd_data));
192 dp = &(cd->params);
15637ed4
RG
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
15637ed4
RG
202 i = cd->cmdscount;
203 while(i-- )
204 {
78ed81a3 205 cd->scsi_xfer[i].next = cd->free_xfer;
206 cd->free_xfer = &cd->scsi_xfer[i];
15637ed4
RG
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 {
78ed81a3 216 printf("cd%d: cd present.[%d x %d byte records]\n",
217 unit,
218 cd->params.disksize,
219 cd->params.blksize);
15637ed4
RG
220 }
221 else
222 {
78ed81a3 223 printf("cd%d: drive empty\n", unit);
15637ed4
RG
224 }
225 cd->flags |= CDINIT;
226 return;
15637ed4
RG
227}
228
15637ed4
RG
229/*******************************************************\
230* open the device. Make sure the partition info *
231* is a up-to-date as can be. *
232\*******************************************************/
233cdopen(dev)
234{
235 int errcode = 0;
236 int unit, part;
237 struct cd_parms cd_parms;
78ed81a3 238 struct cd_data *cd;
15637ed4
RG
239
240 unit = UNIT(dev);
241 part = PARTITION(dev);
78ed81a3 242
243#ifdef CDDEBUG
15637ed4
RG
244 if(scsi_debug & (PRINTROUTINES | TRACEOPENS))
245 printf("cdopen: dev=0x%x (unit %d (of %d),partition %d)\n"
78ed81a3 246 ,dev,unit,cd_driver->size,part);
247#endif /*CDDEBUG*/
15637ed4
RG
248 /*******************************************************\
249 * Check the unit is legal *
250 \*******************************************************/
78ed81a3 251 if ( unit >= cd_driver->size )
15637ed4
RG
252 {
253 return(ENXIO);
254 }
78ed81a3 255 cd = cd_driver->cd_data[unit];
15637ed4 256 /*******************************************************\
78ed81a3 257 * Make sure the device has been initialised *
15637ed4 258 \*******************************************************/
78ed81a3 259 if ((cd == NULL) || (!(cd->flags & CDINIT)))
15637ed4
RG
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);
78ed81a3 270
15637ed4
RG
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 \*******************************************************/
78ed81a3 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
15637ed4 284 if(scsi_debug & TRACEOPENS)
78ed81a3 285 printf("not ready\n");
286#endif /*CDDEBUG*/
15637ed4
RG
287 return(ENXIO);
288 }
78ed81a3 289#ifdef CDDEBUG
15637ed4
RG
290 if(scsi_debug & TRACEOPENS)
291 printf("Device present\n");
78ed81a3 292#endif /*CDDEBUG*/
15637ed4
RG
293 /*******************************************************\
294 * In case it is a funny one, tell it to start *
78ed81a3 295 * not needed for some drives *
15637ed4
RG
296 \*******************************************************/
297 cd_start_unit(unit,part,CD_START);
298 cd_prevent_unit(unit,PR_PREVENT,SCSI_SILENT);
78ed81a3 299#ifdef CDDEBUG
15637ed4
RG
300 if(scsi_debug & TRACEOPENS)
301 printf("started ");
78ed81a3 302#endif /*CDDEBUG*/
15637ed4
RG
303 /*******************************************************\
304 * Load the physical device parameters *
305 \*******************************************************/
306 cd_get_parms(unit, 0);
78ed81a3 307#ifdef CDDEBUG
15637ed4
RG
308 if(scsi_debug & TRACEOPENS)
309 printf("Params loaded ");
78ed81a3 310#endif /*CDDEBUG*/
15637ed4
RG
311 /*******************************************************\
312 * Load the partition info if not already loaded *
313 \*******************************************************/
314 cdgetdisklabel(unit);
78ed81a3 315#ifdef CDDEBUG
15637ed4
RG
316 if(scsi_debug & TRACEOPENS)
317 printf("Disklabel fabricated ");
78ed81a3 318#endif /*CDDEBUG*/
15637ed4
RG
319 /*******************************************************\
320 * Check the partition is legal *
321 \*******************************************************/
322 if (( part >= cd->disklabel.d_npartitions )
323 && (part != RAW_PART))
324 {
78ed81a3 325#ifdef CDDEBUG
15637ed4
RG
326 if(scsi_debug & TRACEOPENS)
327 printf("partition %d > %d\n",part
328 ,cd->disklabel.d_npartitions);
78ed81a3 329#endif /*CDDEBUG*/
15637ed4
RG
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);
78ed81a3 341#ifdef CDDEBUG
15637ed4
RG
342 if(scsi_debug & TRACEOPENS)
343 printf("open complete\n");
78ed81a3 344#endif /*CDDEBUG*/
15637ed4
RG
345 cd->flags |= CDVALID;
346 }
347 else
348 {
78ed81a3 349#ifdef CDDEBUG
15637ed4
RG
350 if(scsi_debug & TRACEOPENS)
351 printf("part %d type UNUSED\n",part);
78ed81a3 352#endif /*CDDEBUG*/
15637ed4
RG
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\*******************************************************/
363struct scsi_xfer *cd_get_xs(unit,flags)
364int flags;
365int unit;
366{
367 struct scsi_xfer *xs;
78ed81a3 368 struct cd_data *cd;
15637ed4
RG
369 int s;
370
78ed81a3 371 cd = cd_driver->cd_data[unit];
15637ed4
RG
372 if(flags & (SCSI_NOSLEEP | SCSI_NOMASK))
373 {
78ed81a3 374 if (xs = cd->free_xfer)
15637ed4 375 {
78ed81a3 376 cd->free_xfer = xs->next;
15637ed4
RG
377 xs->flags = 0;
378 }
379 }
380 else
381 {
382 s = SPLCD();
78ed81a3 383 while (!(xs = cd->free_xfer))
15637ed4 384 {
78ed81a3 385 cd->xfer_block_wait++; /* someone waiting! */
386 sleep((caddr_t)&cd->free_xfer, PRIBIO+1);
387 cd->xfer_block_wait--;
15637ed4 388 }
78ed81a3 389 cd->free_xfer = xs->next;
15637ed4
RG
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\*******************************************************/
399cd_free_xs(unit,xs,flags)
400struct scsi_xfer *xs;
401int unit;
402int flags;
403{
78ed81a3 404 struct cd_data *cd;
15637ed4
RG
405 int s;
406
78ed81a3 407 cd = cd_driver->cd_data[unit];
15637ed4
RG
408 if(flags & SCSI_NOMASK)
409 {
78ed81a3 410 if (cd->xfer_block_wait)
15637ed4 411 {
78ed81a3 412 printf("cd%d: doing a wakeup from NOMASK mode\n", unit);
413 wakeup((caddr_t)&cd->free_xfer);
15637ed4 414 }
78ed81a3 415 xs->next = cd->free_xfer;
416 cd->free_xfer = xs;
15637ed4
RG
417 }
418 else
419 {
420 s = SPLCD();
78ed81a3 421 if (cd->xfer_block_wait)
422 wakeup((caddr_t)&cd->free_xfer);
423 xs->next = cd->free_xfer;
424 cd->free_xfer = xs;
15637ed4
RG
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 */
436void cdminphys(bp)
437struct buf *bp;
438{
78ed81a3 439 (*(cd_driver->cd_data[UNIT(bp->b_dev)]->sc_sw->scsi_minphys))(bp);
15637ed4
RG
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
449int cdstrategy(bp)
450struct buf *bp;
451{
452 struct buf *dp;
453 unsigned int opri;
78ed81a3 454 struct cd_data *cd;
15637ed4
RG
455 int unit;
456
457 cdstrats++;
458 unit = UNIT((bp->b_dev));
78ed81a3 459 cd = cd_driver->cd_data[unit];
460#ifdef CDDEBUG
15637ed4
RG
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);
78ed81a3 464#endif /*CDDEBUG*/
15637ed4
RG
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();
78ed81a3 509 dp = &cd->buf_queue;
15637ed4
RG
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;
524bad:
525 bp->b_flags |= B_ERROR;
526done:
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*/
552cdstart(unit)
553int 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;
78ed81a3 560 struct cd_data *cd;
15637ed4
RG
561 struct partition *p ;
562
78ed81a3 563#ifdef CDDEBUG
15637ed4 564 if(scsi_debug & PRINTROUTINES) printf("cdstart%d ",unit);
78ed81a3 565#endif /*CDDEBUG*/
566 cd = cd_driver->cd_data[unit];
15637ed4
RG
567 /*******************************************************\
568 * See if there is a buf to do and we are not already *
569 * doing one *
570 \*******************************************************/
78ed81a3 571 if(!cd->free_xfer)
15637ed4
RG
572 {
573 return; /* none for us, unit already underway */
574 }
575
78ed81a3 576 if(cd->xfer_block_wait) /* there is one, but a special waits */
15637ed4
RG
577 {
578 return; /* give the special that's waiting a chance to run */
579 }
580
581
78ed81a3 582 dp = &cd->buf_queue;
15637ed4
RG
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 *
78ed81a3 605 * *
15637ed4
RG
606 * First, translate the block to absolute *
607 * and put it in terms of the logical blocksize of the *
608 * device.. *
78ed81a3 609 * really a bit silly until we have real partitions, but.*
15637ed4 610 \*******************************************************/
78ed81a3 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 }
15637ed4 617 nblk = (bp->b_bcount + (cd->params.blksize - 1)) / (cd->params.blksize);
78ed81a3 618 /* what if something asks for 512 bytes not on a 2k boundary? *//*XXX*/
15637ed4
RG
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;
662bad: 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\*******************************************************/
670int cd_done(unit,xs)
671int unit;
672struct scsi_xfer *xs;
673{
674 struct buf *bp;
675 int retval;
78ed81a3 676 struct cd_data *cd = cd_driver->cd_data[unit];
15637ed4 677
78ed81a3 678#ifdef CDDEBUG
15637ed4 679 if(scsi_debug & PRINTROUTINES) printf("cd_done%d ",unit);
78ed81a3 680#endif /*CDDEBUG*/
681#ifdef PARANOIA
15637ed4
RG
682 if (! (xs->flags & INUSE)) /* paranoia always pays off */
683 panic("scsi_xfer not in use!");
78ed81a3 684#endif /*PARANOIA*/
685 if(!(bp = xs->bp))
15637ed4 686 {
78ed81a3 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)
15637ed4 700 {
78ed81a3 701 bp->b_flags |= B_ERROR;
702 bp->b_error = retval;
703 }
704 break;
15637ed4 705
78ed81a3 706 case XS_TIMEOUT:
707 printf("cd%d timeout\n",unit);
15637ed4 708
78ed81a3 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 */
15637ed4 726
78ed81a3 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;
15637ed4 739}
78ed81a3 740
15637ed4
RG
741/*******************************************************\
742* Perform special action on behalf of the user *
743* Knows about the internals of this device *
744\*******************************************************/
745cdioctl(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);
78ed81a3 758 cd = cd_driver->cd_data[unit];
759#ifdef CDDEBUG
15637ed4 760 if(scsi_debug & PRINTROUTINES) printf("cdioctl%d ",unit);
78ed81a3 761#endif /*CDDEBUG*/
15637ed4
RG
762
763 /*******************************************************\
764 * If the device is not valid.. abandon ship *
765 \*******************************************************/
78ed81a3 766 if (!(cd_driver->cd_data[unit]->flags & CDVALID))
15637ed4
RG
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;
78ed81a3 810 data.page.audio.flags &= ~CD_PA_SOTC;
811 data.page.audio.flags |= CD_PA_IMMED;
15637ed4
RG
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;
78ed81a3 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;
15637ed4
RG
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;
78ed81a3 850 data.page.audio.flags &= ~CD_PA_SOTC;
851 data.page.audio.flags |= CD_PA_IMMED;
15637ed4
RG
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;
78ed81a3 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;
15637ed4
RG
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\*******************************************************/
1064int cdgetdisklabel(unit)
1065unsigned char unit;
1066{
1067 /*unsigned int n, m;*/
1068 char *errstring;
1069 struct dos_partition *dos_partition_p;
78ed81a3 1070 struct cd_data *cd;
15637ed4 1071
78ed81a3 1072 cd = cd_driver->cd_data[unit];
15637ed4 1073 /*******************************************************\
78ed81a3 1074 * If the info is already loaded, use it *
15637ed4
RG
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;
78ed81a3 1097 cd->disklabel.d_partitions[0].p_size
1098 = cd->params.disksize * (cd->params.blksize / 512);
15637ed4
RG
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
78ed81a3 1113/*******************************************************\
1114* Get scsi driver to send a "are you ready" command *
1115\*******************************************************/
1116cd_test_ready(unit,flags)
1117int 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
15637ed4
RG
1135/*******************************************************\
1136* Find out form the device what it's capacity is *
1137\*******************************************************/
1138cd_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,
78ed81a3 1162 NULL,
15637ed4
RG
1163 flags) != 0)
1164 {
78ed81a3 1165 printf("cd%d: could not get size\n", unit);
15637ed4
RG
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 }
78ed81a3 1177#ifdef CDDEBUG
15637ed4 1178 if(cd_debug)printf("cd%d: %d %d byte blocks\n",unit,size,blksize);
78ed81a3 1179#endif /*CDDEBUG*/
1180 cd_driver->cd_data[unit]->params.disksize = size;
1181 cd_driver->cd_data[unit]->params.blksize = blksize;
15637ed4
RG
1182 return(size);
1183}
1184
15637ed4
RG
1185
1186/*******************************************************\
1187* Get the requested page into the buffer given *
1188\*******************************************************/
1189cd_get_mode(unit,data,page)
1190int unit;
1191struct cd_mode_data *data;
1192int 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;
78ed81a3 1200 scsi_cmd.page = page;
15637ed4
RG
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 */
78ed81a3 1208 NULL,
15637ed4
RG
1209 0);
1210 return (retval);
1211}
1212/*******************************************************\
1213* Get the requested page into the buffer given *
1214\*******************************************************/
1215cd_set_mode(unit,data)
1216int unit;
1217struct 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;
78ed81a3 1223 scsi_cmd.byte2 |= SMS_PF;
15637ed4
RG
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 */
78ed81a3 1233 NULL,
15637ed4
RG
1234 0)
1235 );
1236}
1237/*******************************************************\
1238* Get scsi driver to send a "start playing" command *
1239\*******************************************************/
1240cd_play(unit,blk,len)
1241int 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 */
78ed81a3 1260 NULL,
15637ed4
RG
1261 0);
1262 return(retval);
1263}
1264/*******************************************************\
1265* Get scsi driver to send a "start playing" command *
1266\*******************************************************/
1267cd_play_big(unit,blk,len)
1268int 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 */
78ed81a3 1289 NULL,
15637ed4
RG
1290 0);
1291 return(retval);
1292}
1293/*******************************************************\
1294* Get scsi driver to send a "start playing" command *
1295\*******************************************************/
1296cd_play_tracks(unit,strack,sindex,etrack,eindex)
1297int 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 */
78ed81a3 1314 NULL,
15637ed4
RG
1315 0);
1316 return(retval);
1317}
1318/*******************************************************\
78ed81a3 1319* Get scsi driver to send a "play msf" command *
1320\*******************************************************/
1321cd_play_msf(unit,startm,starts,startf,endm,ends,endf)
1322int 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/*******************************************************\
15637ed4
RG
1345* Get scsi driver to send a "start up" command *
1346\*******************************************************/
1347cd_pause(unit,go)
1348int 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,
78ed81a3 1362 NULL,
15637ed4
RG
1363 0));
1364}
1365/*******************************************************\
78ed81a3 1366* Get scsi driver to send a "RESET" command *
15637ed4
RG
1367\*******************************************************/
1368cd_reset(unit)
1369int unit;
1370{
78ed81a3 1371 return(cd_scsi_cmd(unit,
1372 0,
1373 0,
1374 0,
1375 0,
1376 2000,
1377 NULL,
1378 SCSI_RESET));
15637ed4
RG
1379}
1380/*******************************************************\
1381* Get scsi driver to send a "start up" command *
1382\*******************************************************/
1383cd_start_unit(unit,part,type)
1384{
1385 struct scsi_start_stop scsi_cmd;
78ed81a3 1386 struct cd_data *cd = cd_driver->cd_data[unit];
15637ed4 1387
78ed81a3 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);
15637ed4
RG
1392 }
1393
1394 bzero(&scsi_cmd, sizeof(scsi_cmd));
1395 scsi_cmd.op_code = START_STOP;
78ed81a3 1396 scsi_cmd.how |= (type==CD_START)?SSS_START:0;
1397 scsi_cmd.how |= (type==CD_EJECT)?SSS_LOEJ:0;
15637ed4
RG
1398
1399 if (cd_scsi_cmd(unit,
1400 &scsi_cmd,
1401 sizeof(scsi_cmd),
1402 0,
1403 0,
1404 2000,
78ed81a3 1405 NULL,
15637ed4
RG
1406 0) != 0) {
1407 return(ENXIO);
1408 } else
1409 return(0);
1410}
1411/*******************************************************\
1412* Prevent or allow the user to remove the disk *
1413\*******************************************************/
1414cd_prevent_unit(unit,type,flags)
1415int unit,type,flags;
1416{
1417 struct scsi_prevent scsi_cmd;
78ed81a3 1418 struct cd_data *cd = cd_driver->cd_data[unit];
15637ed4 1419
78ed81a3 1420 if(type==PR_PREVENT
1421 || ( type==PR_ALLOW && cd->openparts == 0 ))/*XXX*/
1422 {
15637ed4
RG
1423 bzero(&scsi_cmd, sizeof(scsi_cmd));
1424 scsi_cmd.op_code = PREVENT_ALLOW;
78ed81a3 1425 scsi_cmd.how = type;
15637ed4
RG
1426 if (cd_scsi_cmd(unit,
1427 &scsi_cmd,
1428 sizeof(struct scsi_prevent),
1429 0,
1430 0,
1431 5000,
78ed81a3 1432 NULL,
15637ed4
RG
1433 0) != 0)
1434 {
1435 if(!(flags & SCSI_SILENT))
78ed81a3 1436 printf("cd%d: cannot prevent/allow\n", unit);
15637ed4
RG
1437 return(0);
1438 }
1439 }
1440 return(1);
1441}
1442
1443/******************************************************\
1444* Read Subchannel *
1445\******************************************************/
1446
1447cd_read_subchannel(unit,mode,format,track,data,len)
1448int unit,mode,format,len;
1449struct 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)
78ed81a3 1458 scsi_cmd.byte2 |= CD_MSF;
1459 scsi_cmd.byte3=SRS_SUBQ;
15637ed4
RG
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,
78ed81a3 1470 NULL,
15637ed4
RG
1471 0);
1472}
1473
1474/*******************************************************\
1475* Read Table of contents *
1476\*******************************************************/
1477cd_read_toc(unit,mode,start,data,len)
1478int unit,mode,start,len;
1479struct 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)
78ed81a3 1493 scsi_cmd.byte2 |= CD_MSF;
15637ed4
RG
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,
78ed81a3 1503 NULL,
15637ed4
RG
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
1516int cd_get_parms(unit, flags)
1517{
78ed81a3 1518 struct cd_data *cd = cd_driver->cd_data[unit];
15637ed4
RG
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\*******************************************************/
1543cdclose(dev)
1544dev_t dev;
1545{
1546 unsigned char unit, part;
1547 unsigned int old_priority;
1548
1549 unit = UNIT(dev);
1550 part = PARTITION(dev);
78ed81a3 1551#ifdef CDDEBUG
15637ed4 1552 if(scsi_debug & TRACEOPENS)
78ed81a3 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);
15637ed4
RG
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\*******************************************************/
78ed81a3 1570int cd_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,bp,flags)
15637ed4
RG
1571
1572int unit,flags;
1573struct scsi_generic *scsi_cmd;
1574int cmdlen;
1575int timeout;
1576u_char *data_addr;
1577int datalen;
78ed81a3 1578struct buf *bp;
15637ed4
RG
1579{
1580 struct scsi_xfer *xs;
1581 int retval;
1582 int s;
78ed81a3 1583 struct cd_data *cd = cd_driver->cd_data[unit];
15637ed4 1584
78ed81a3 1585#ifdef CDDEBUG
15637ed4 1586 if(scsi_debug & PRINTROUTINES) printf("\ncd_scsi_cmd%d ",unit);
78ed81a3 1587#endif /*CDDEBUG*/
1588#ifdef PARANOID
1589 if(!(cd->sc_sw)) /* If we have a scsi driver */
15637ed4 1590 {
78ed81a3 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;
1623retry: 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 */
15637ed4 1642
78ed81a3 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 */
15637ed4 1656
78ed81a3 1657 case HAD_ERROR:
1658 switch(xs->error)
1659 {
1660 case XS_NOERROR: /* usually this one */
15637ed4
RG
1661 retval = ESUCCESS;
1662 break;
78ed81a3 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:
15637ed4
RG
1671 if(xs->retries-- )
1672 {
78ed81a3 1673 xs->flags &= ~ITSDONE;
1674 goto retry;
15637ed4 1675 }
78ed81a3 1676 /* fall through */
1677 case XS_DRIVER_STUFFUP:
15637ed4
RG
1678 retval = EIO;
1679 break;
1680 default:
1681 retval = EIO;
78ed81a3 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 }
15637ed4 1698 }
78ed81a3 1699 /* fall through */
1700 default:
1701 retval = EIO;
15637ed4 1702 }
78ed81a3 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 */
15637ed4
RG
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
1717int cd_interpret_sense(unit,xs)
1718int unit;
1719struct scsi_xfer *xs;
1720{
1721 struct scsi_sense_data *sense;
1722 int key;
1723 int silent;
78ed81a3 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 };
15637ed4
RG
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);
78ed81a3 1744#ifdef CDDEBUG
1745 if(cd_debug)
15637ed4 1746 {
78ed81a3 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)
15637ed4 1765 {
78ed81a3 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)
15637ed4 1780 {
78ed81a3 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)
15637ed4 1794 {
78ed81a3 1795 switch (key)
15637ed4 1796 {
78ed81a3 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);
15637ed4 1808 }
15637ed4 1809 }
78ed81a3 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 */
15637ed4 1819 return(ESUCCESS);
78ed81a3 1820 case 0x2: /* NOT READY */
1821 cd->flags &= ~(CDVALID | CDHAVELABEL);
15637ed4 1822 return(ENODEV);
78ed81a3 1823 case 0x5: /* ILLEGAL REQUEST */
15637ed4 1824 return(EINVAL);
78ed81a3 1825 case 0x6: /* UNIT ATTENTION */
1826 cd->flags &= ~(CDVALID | CDHAVELABEL);
1827 if (cd->openparts)
15637ed4
RG
1828 {
1829 return(EIO);
1830 }
1831 return(ESUCCESS);
78ed81a3 1832 case 0x7: /* DATA PROTECT */
15637ed4 1833 return(EACCES);
78ed81a3 1834 case 0xd: /* VOLUME OVERFLOW */
15637ed4 1835 return(ENOSPC);
78ed81a3 1836 case 0x8: /* BLANK CHECK */
1837 return(ESUCCESS);
1838 default:
15637ed4
RG
1839 return(EIO);
1840 }
78ed81a3 1841 /*******************************\
1842 * Not code 70, just report it *
1843 \*******************************/
1844 default:
1845 if(!silent)
15637ed4 1846 {
78ed81a3 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");
15637ed4
RG
1857 }
1858 return(EIO);
1859 }
1860}
1861
1862
1863
1864
1865int
1866cdsize(dev_t dev)
1867{
1868 return (-1);
1869}
1870
78ed81a3 1871#if 0
15637ed4
RG
1872show_mem(address,num)
1873unsigned char *address;
1874int 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}
78ed81a3 1886#endif