Annotation of Net2/scsi/cd.c, revision 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.