Annotation of Net2/scsi/cd.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.