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

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

unix.superglobalmegacorp.com

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