Annotation of Net2/scsi/sd.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Written by Julian Elischer ([email protected])
        !             3:  * for TRW Financial Systems for use under the MACH(2.5) operating system.
        !             4:  *
        !             5:  * TRW Financial Systems, in accordance with their agreement with Carnegie
        !             6:  * Mellon University, makes this software available to CMU to distribute
        !             7:  * or use in any manner that they see fit as long as this message is kept with
        !             8:  * the software. For this reason TFS also grants any other persons or
        !             9:  * organisations permission to use or modify this software.
        !            10:  *
        !            11:  * TFS supplies this software to be publicly redistributed
        !            12:  * on the understanding that TFS is not responsible for the correct
        !            13:  * functioning of this software in any circumstances.
        !            14:  *
        !            15:  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
        !            16:  * --------------------         -----   ----------------------
        !            17:  * CURRENT PATCH LEVEL:         1       00098
        !            18:  * --------------------         -----   ----------------------
        !            19:  *
        !            20:  * 16 Feb 93   Julian Elischer         ADDED for SCSI system
        !            21:  *
        !            22:  */
        !            23: 
        !            24: /*
        !            25:  * Ported to run under 386BSD by Julian Elischer ([email protected]) Sept 1992
        !            26:  */
        !            27: 
        !            28: #define SPLSD splbio
        !            29: #define ESUCCESS 0
        !            30: #include <sd.h>
        !            31: #include <sys/types.h>
        !            32: #include <sys/param.h>
        !            33: #include <sys/dkbad.h>
        !            34: #include <sys/systm.h>
        !            35: #include <sys/conf.h>
        !            36: #include <sys/file.h>
        !            37: #include <sys/stat.h>
        !            38: #include <sys/ioctl.h>
        !            39: #include <sys/buf.h>
        !            40: #include <sys/uio.h>
        !            41: #include <sys/malloc.h>
        !            42: #include <sys/errno.h>
        !            43: #include <sys/disklabel.h>
        !            44: #include <scsi/scsi_all.h>
        !            45: #include <scsi/scsi_disk.h>
        !            46: #include <scsi/scsiconf.h>
        !            47: 
        !            48: long int sdstrats,sdqueues;
        !            49: 
        !            50: 
        !            51: #ifdef DDB
        !            52: int    Debugger();
        !            53: #else  
        !            54: #define Debugger()
        !            55: #endif
        !            56: 
        !            57: 
        !            58: #define PAGESIZ        4096
        !            59: #define SECSIZE 512
        !            60: #define PDLOCATION     29      
        !            61: #define BOOTRECORDSIGNATURE                    (0x55aa & 0x00ff)
        !            62: #define        SDOUTSTANDING   2
        !            63: #define SDQSIZE                4
        !            64: #define        SD_RETRIES      4
        !            65: 
        !            66: #define MAKESDDEV(maj, unit, part)     (makedev(maj,((unit<<3)+part)))
        !            67: #define        UNITSHIFT       3
        !            68: #define PARTITION(z)   (minor(z) & 0x07)
        !            69: #define        RAW_PART        3
        !            70: #define UNIT(z)                (  (minor(z) >> UNITSHIFT) )
        !            71: 
        !            72: #define WHOLE_DISK(unit) ( (unit << UNITSHIFT) + RAW_PART )
        !            73: 
        !            74: struct buf sd_buf_queue[NSD];
        !            75: int    sd_done();
        !            76: int    sdstrategy();
        !            77: 
        !            78: int    sd_debug = 0;
        !            79: 
        !            80: struct scsi_xfer       *sd_free_xfer[NSD];
        !            81: int                    sd_xfer_block_wait[NSD];
        !            82: 
        !            83: struct sd_data
        !            84: {
        !            85:        int     flags;
        !            86: #define        SDVALID         0x02            /* PARAMS LOADED        */
        !            87: #define        SDINIT          0x04            /* device has been init'd */
        !            88: #define        SDWAIT          0x08            /* device has someone waiting */
        !            89: #define SDHAVELABEL    0x10            /* have read the label */
        !            90: #define SDDOSPART      0x20            /* Have read the DOS partition table */
        !            91: #define SDWRITEPROT    0x40            /* Device in readonly mode (S/W)*/
        !            92:        struct  scsi_switch *sc_sw;     /* address of scsi low level switch */
        !            93:        int     ctlr;                   /* so they know which one we want */
        !            94:        int     targ;                   /* our scsi target ID */
        !            95:        int     lu;                     /* out scsi lu */
        !            96:        long int        ad_info;        /* info about the adapter */
        !            97:        int     cmdscount;              /* cmds allowed outstanding by board*/
        !            98:        int     wlabel;                 /* label is writable */
        !            99:        struct  disk_parms
        !           100:        {
        !           101:                u_char  heads;          /* Number of heads */
        !           102:                u_short cyls;           /* Number of cylinders */
        !           103:                u_char  sectors;/*dubious*/     /* Number of sectors/track */
        !           104:                u_short secsiz;         /* Number of bytes/sector */
        !           105:                u_long  disksize;               /* total number sectors */
        !           106:        }params;
        !           107:        struct  disklabel       disklabel;
        !           108:        struct  dos_partition dosparts[NDOSPART]; /* DOS view of disk */
        !           109:        int     partflags[MAXPARTITIONS];       /* per partition flags */
        !           110: #define SDOPEN 0x01
        !           111:        int             openparts;              /* one bit for each open partition */
        !           112:        unsigned int    sd_start_of_unix;       /* unix vs dos partitions */
        !           113: }sd_data[NSD];
        !           114: 
        !           115: 
        !           116: static int     next_sd_unit = 0;
        !           117: /***********************************************************************\
        !           118: * The routine called by the low level scsi routine when it discovers   *
        !           119: * A device suitable for this driver                                    *
        !           120: \***********************************************************************/
        !           121: 
        !           122: int    sdattach(ctlr,targ,lu,scsi_switch)
        !           123: struct scsi_switch *scsi_switch;
        !           124: {
        !           125:        int     unit,i;
        !           126:        unsigned char *tbl;
        !           127:        struct sd_data *sd;
        !           128:        struct disk_parms *dp;
        !           129:        long int        ad_info;
        !           130:        struct  scsi_xfer       *sd_scsi_xfer;
        !           131: 
        !           132:        unit = next_sd_unit++;
        !           133:        sd = sd_data + unit;
        !           134:        dp  = &(sd->params);
        !           135:        if(scsi_debug & PRINTROUTINES) printf("sdattach: "); 
        !           136:        /*******************************************************\
        !           137:        * Check we have the resources for another drive         *
        !           138:        \*******************************************************/
        !           139:        if( unit >= NSD)
        !           140:        {
        !           141:                printf("Too many scsi disks..(%d > %d) reconfigure kernel",(unit + 1),NSD);
        !           142:                return(0);
        !           143:        }
        !           144:        /*******************************************************\
        !           145:        * Store information needed to contact our base driver   *
        !           146:        \*******************************************************/
        !           147:        sd->sc_sw       =       scsi_switch;
        !           148:        sd->ctlr        =       ctlr;
        !           149:        sd->targ        =       targ;
        !           150:        sd->lu          =       lu;
        !           151:        if(sd->sc_sw->adapter_info)
        !           152:        {
        !           153:                sd->ad_info = ( (*(sd->sc_sw->adapter_info))(ctlr));
        !           154:                sd->cmdscount = sd->ad_info & AD_INF_MAX_CMDS;
        !           155:                if(sd->cmdscount > SDOUTSTANDING)
        !           156:                {
        !           157:                        sd->cmdscount = SDOUTSTANDING;
        !           158:                }
        !           159:        }
        !           160:        else
        !           161:        {
        !           162:                sd->ad_info = 1;
        !           163:                sd->cmdscount = 1;
        !           164:        }
        !           165: 
        !           166:        i = sd->cmdscount;
        !           167:        sd_scsi_xfer = (struct scsi_xfer *)malloc(sizeof(struct scsi_xfer) * i
        !           168:                                ,M_TEMP, M_NOWAIT);
        !           169:        while(i-- )
        !           170:        {
        !           171:                sd_scsi_xfer->next = sd_free_xfer[unit];
        !           172:                sd_free_xfer[unit] = sd_scsi_xfer;
        !           173:                sd_scsi_xfer++;
        !           174:        }
        !           175:        /*******************************************************\
        !           176:        * Use the subdriver to request information regarding    *
        !           177:        * the drive. We cannot use interrupts yet, so the       *
        !           178:        * request must specify this.                            *
        !           179:        \*******************************************************/
        !           180:        sd_get_parms(unit,  SCSI_NOSLEEP |  SCSI_NOMASK);
        !           181:        printf("        sd%d: %dMB, cyls %d, heads %d, secs %d, bytes/sec %d\n",
        !           182:                unit,
        !           183:                (         dp->cyls 
        !           184:                        * dp->heads 
        !           185:                        * dp->sectors
        !           186:                        * dp->secsiz
        !           187:                )
        !           188:                / (1024 * 1024),
        !           189:                dp->cyls,
        !           190:                dp->heads,
        !           191:                dp->sectors,
        !           192:                dp->secsiz);
        !           193:        /*******************************************************\
        !           194:        * Set up the bufs for this device                       *
        !           195:        \*******************************************************/
        !           196:        sd->flags |= SDINIT;
        !           197:        return;
        !           198: 
        !           199: }
        !           200: 
        !           201: 
        !           202: 
        !           203: /*******************************************************\
        !           204: *      open the device. Make sure the partition info   *
        !           205: * is a up-to-date as can be.                           *
        !           206: \*******************************************************/
        !           207: sdopen(dev)
        !           208: {
        !           209:        int errcode = 0;
        !           210:        int unit, part;
        !           211:        struct disk_parms disk_parms;
        !           212:        struct sd_data *sd ;
        !           213: 
        !           214:        unit = UNIT(dev);
        !           215:        part = PARTITION(dev);
        !           216:        sd = sd_data + unit;
        !           217:        if(scsi_debug & (PRINTROUTINES | TRACEOPENS))
        !           218:                printf("sdopen: dev=0x%x (unit %d (of %d),partition %d)\n"
        !           219:                                ,   dev,      unit,   NSD,         part);
        !           220:        /*******************************************************\
        !           221:        * Check the unit is legal                               *
        !           222:        \*******************************************************/
        !           223:        if ( unit >= NSD )
        !           224:        {
        !           225:                return(ENXIO);
        !           226:        }
        !           227:        /*******************************************************\
        !           228:        * Make sure the disk has been initialised               *
        !           229:        * At some point in the future, get the scsi driver      *
        !           230:        * to look for a new device if we are not initted        *
        !           231:        \*******************************************************/
        !           232:        if (! (sd->flags & SDINIT))
        !           233:        {
        !           234:                return(ENXIO);
        !           235:        }
        !           236: 
        !           237:        /*******************************************************\
        !           238:        * If it's been invalidated, and not everybody has       *
        !           239:        * closed it then forbid re-entry.                       *
        !           240:        \*******************************************************/
        !           241:        if ((! (sd->flags & SDVALID))
        !           242:           && ( sd->openparts))
        !           243:                return(ENXIO);
        !           244:        /*******************************************************\
        !           245:        * Check that it is still responding and ok.             *
        !           246:        * "unit attention errors should occur here if the drive *
        !           247:        * has been restarted or the pack changed                *
        !           248:        \*******************************************************/
        !           249: 
        !           250:        if(scsi_debug & TRACEOPENS)
        !           251:                printf("device is ");
        !           252:        if (sd_test_unit_ready(unit,0))
        !           253:        {
        !           254:                if(scsi_debug & TRACEOPENS) printf("not reponding\n");
        !           255:                return(ENXIO);
        !           256:        }
        !           257:        if(scsi_debug & TRACEOPENS)
        !           258:                printf("ok\n");
        !           259:        /*******************************************************\
        !           260:        * In case it is a funny one, tell it to start           *
        !           261:        * not needed for  most hard drives (ignore failure)     *
        !           262:        \*******************************************************/
        !           263:        sd_start_unit(unit,SCSI_ERR_OK|SCSI_SILENT);
        !           264:        if(scsi_debug & TRACEOPENS)
        !           265:                printf("started ");
        !           266:        /*******************************************************\
        !           267:        * Load the physical device parameters                   *
        !           268:        \*******************************************************/
        !           269:        sd_get_parms(unit, 0);  /* sets SDVALID */
        !           270:        if (sd->params.secsiz != SECSIZE)
        !           271:        {
        !           272:                printf("sd%d: Can't deal with %d bytes logical blocks\n"
        !           273:                        ,unit, sd->params.secsiz);
        !           274:                Debugger();
        !           275:                return(ENXIO);
        !           276:        }
        !           277:        if(scsi_debug & TRACEOPENS)
        !           278:                printf("Params loaded ");
        !           279:        /*******************************************************\
        !           280:        * Load the partition info if not already loaded         *
        !           281:        \*******************************************************/
        !           282:        sd_prevent(unit,PR_PREVENT,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
        !           283:        if((errcode = sdgetdisklabel(unit)) && (part != RAW_PART))
        !           284:        {
        !           285:                sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
        !           286:                return(errcode);
        !           287:        }
        !           288:        if(scsi_debug & TRACEOPENS)
        !           289:                printf("Disklabel loaded ");
        !           290:        /*******************************************************\
        !           291:        * Check the partition is legal                          *
        !           292:        \*******************************************************/
        !           293:        if ( part >= MAXPARTITIONS ) {
        !           294:                sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
        !           295:                return(ENXIO);
        !           296:        }
        !           297:        if(scsi_debug & TRACEOPENS)
        !           298:                printf("ok");
        !           299:        /*******************************************************\
        !           300:        *  Check that the partition exists                      *
        !           301:        \*******************************************************/
        !           302:        if (( sd->disklabel.d_partitions[part].p_size == 0 )
        !           303:                && (part != RAW_PART))
        !           304:        {
        !           305:                sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */
        !           306:                return(ENXIO);
        !           307:        }
        !           308:        sd->partflags[part] |= SDOPEN;
        !           309:        sd->openparts |= (1 << part);
        !           310:        if(scsi_debug & TRACEOPENS)
        !           311:                printf("open %d %d\n",sdstrats,sdqueues);
        !           312:        return(0);
        !           313: }
        !           314: 
        !           315: /*******************************************************\
        !           316: * Get ownership of a scsi_xfer                         *
        !           317: * If need be, sleep on it, until it comes free         *
        !           318: \*******************************************************/
        !           319: struct scsi_xfer *sd_get_xs(unit,flags)
        !           320: int    flags;
        !           321: int    unit;
        !           322: {
        !           323:        struct scsi_xfer *xs;
        !           324:        int     s;
        !           325: 
        !           326:        if(flags & (SCSI_NOSLEEP |  SCSI_NOMASK))
        !           327:        {
        !           328:                if (xs = sd_free_xfer[unit])
        !           329:                {
        !           330:                        sd_free_xfer[unit] = xs->next;
        !           331:                        xs->flags = 0;
        !           332:                }
        !           333:        }
        !           334:        else
        !           335:        {
        !           336:                s = SPLSD();
        !           337:                while (!(xs = sd_free_xfer[unit]))
        !           338:                {
        !           339:                        sd_xfer_block_wait[unit]++;  /* someone waiting! */
        !           340:                        sleep((caddr_t)&sd_free_xfer[unit], PRIBIO+1);
        !           341:                        sd_xfer_block_wait[unit]--;
        !           342:                }
        !           343:                sd_free_xfer[unit] = xs->next;
        !           344:                splx(s);
        !           345:                xs->flags = 0;
        !           346:        }
        !           347:        return(xs);
        !           348: }
        !           349: 
        !           350: /*******************************************************\
        !           351: * Free a scsi_xfer, wake processes waiting for it      *
        !           352: \*******************************************************/
        !           353: sd_free_xs(unit,xs,flags)
        !           354: struct scsi_xfer *xs;
        !           355: int    unit;
        !           356: int    flags;
        !           357: {
        !           358:        int     s;
        !           359:        
        !           360:        if(flags & SCSI_NOMASK)
        !           361:        {
        !           362:                if (sd_xfer_block_wait[unit])
        !           363:                {
        !           364:                        printf("doing a wakeup from NOMASK mode\n");
        !           365:                        wakeup((caddr_t)&sd_free_xfer[unit]);
        !           366:                }
        !           367:                xs->next = sd_free_xfer[unit];
        !           368:                sd_free_xfer[unit] = xs;
        !           369:        }
        !           370:        else
        !           371:        {
        !           372:                s = SPLSD();
        !           373:                if (sd_xfer_block_wait[unit])
        !           374:                        wakeup((caddr_t)&sd_free_xfer[unit]);
        !           375:                xs->next = sd_free_xfer[unit];
        !           376:                sd_free_xfer[unit] = xs;
        !           377:                splx(s);
        !           378:        }
        !           379: }
        !           380: 
        !           381: /*******************************************************\
        !           382: * trim the size of the transfer if needed,             *
        !           383: * called by physio                                     *
        !           384: * basically the smaller of our max and the scsi driver's*
        !           385: * minphys (note we have no max)                                *
        !           386: \*******************************************************/
        !           387: /* Trim buffer length if buffer-size is bigger than page size */
        !           388: void   sdminphys(bp)
        !           389: struct buf     *bp;
        !           390: {
        !           391:        (*(sd_data[UNIT(bp->b_dev)].sc_sw->scsi_minphys))(bp);
        !           392: }
        !           393: 
        !           394: /*******************************************************\
        !           395: * Actually translate the requested transfer into       *
        !           396: * one the physical driver can understand               *
        !           397: * The transfer is described by a buf and will include  *
        !           398: * only one physical transfer.                          *
        !           399: \*******************************************************/
        !           400: 
        !           401: int    sdstrategy(bp)
        !           402: struct buf     *bp;
        !           403: {
        !           404:        struct  buf     *dp;
        !           405:        unsigned int opri;
        !           406:        struct sd_data *sd ;
        !           407:        int     unit;
        !           408: 
        !           409:        sdstrats++;
        !           410:        unit = UNIT((bp->b_dev));
        !           411:        sd = sd_data + unit;
        !           412:        if(scsi_debug & PRINTROUTINES) printf("\nsdstrategy ");
        !           413:        if(scsi_debug & SHOWREQUESTS) printf("sd%d: %d bytes @ blk%d\n",
        !           414:                                        unit,bp->b_bcount,bp->b_blkno);
        !           415:        sdminphys(bp);
        !           416:        /*******************************************************\
        !           417:        * If the device has been made invalid, error out        *
        !           418:        \*******************************************************/
        !           419:        if(!(sd->flags & SDVALID))
        !           420:        {
        !           421:                bp->b_error = EIO;
        !           422:                goto bad;
        !           423:        }
        !           424:        /*******************************************************\
        !           425:        * "soft" write protect check                            *
        !           426:        \*******************************************************/
        !           427:        if ((sd->flags & SDWRITEPROT) && (bp->b_flags & B_READ) == 0) {
        !           428:                bp->b_error = EROFS;
        !           429:                goto bad;
        !           430:        }
        !           431:        /*******************************************************\
        !           432:        * If it's a null transfer, return immediatly            *
        !           433:        \*******************************************************/
        !           434:        if (bp->b_bcount == 0)
        !           435:        {
        !           436:                goto done;
        !           437:        }
        !           438: 
        !           439:        /*******************************************************\
        !           440:        * Decide which unit and partition we are talking about  *
        !           441:        * only raw is ok if no label                            *
        !           442:        \*******************************************************/
        !           443:        if(PARTITION(bp->b_dev) != RAW_PART)
        !           444:        {
        !           445:                if (!(sd->flags & SDHAVELABEL))
        !           446:                {
        !           447:                        bp->b_error = EIO;
        !           448:                        goto bad;
        !           449:                }
        !           450: 
        !           451:                /*
        !           452:                 * do bounds checking, adjust transfer. if error, process.
        !           453:                 * if end of partition, just return
        !           454:                 */
        !           455:                if (bounds_check_with_label(bp,&sd->disklabel,sd->wlabel) <= 0)
        !           456:                        goto done;
        !           457:                /* otherwise, process transfer request */
        !           458:        }
        !           459: 
        !           460:        opri = SPLSD();
        !           461:        dp = &sd_buf_queue[unit];
        !           462: 
        !           463:        /*******************************************************\
        !           464:        * Place it in the queue of disk activities for this disk*
        !           465:        \*******************************************************/
        !           466:        disksort(dp, bp);
        !           467: 
        !           468:        /*******************************************************\
        !           469:        * Tell the device to get going on the transfer if it's  *
        !           470:        * not doing anything, otherwise just wait for completion*
        !           471:        \*******************************************************/
        !           472:        sdstart(unit);
        !           473: 
        !           474:        splx(opri);
        !           475:        return;
        !           476: bad:
        !           477:        bp->b_flags |= B_ERROR;
        !           478: done:
        !           479: 
        !           480:        /*******************************************************\
        !           481:        * Correctly set the buf to indicate a completed xfer    *
        !           482:        \*******************************************************/
        !           483:        bp->b_resid = bp->b_bcount;
        !           484:        biodone(bp);
        !           485:        return;
        !           486: }
        !           487: 
        !           488: /***************************************************************\
        !           489: * sdstart looks to see if there is a buf waiting for the device        *
        !           490: * and that the device is not already busy. If both are true,   *
        !           491: * It deques the buf and creates a scsi command to perform the  *
        !           492: * transfer in the buf. The transfer request will call sd_done  *
        !           493: * on completion, which will in turn call this routine again    *
        !           494: * so that the next queued transfer is performed.               *
        !           495: * The bufs are queued by the strategy routine (sdstrategy)     *
        !           496: *                                                              *
        !           497: * This routine is also called after other non-queued requests  *
        !           498: * have been made of the scsi driver, to ensure that the queue  *
        !           499: * continues to be drained.                                     *
        !           500: *                                                              *
        !           501: * must be called at the correct (highish) spl level            *
        !           502: \***************************************************************/
        !           503: /* sdstart() is called at SPLSD  from sdstrategy and sd_done*/
        !           504: sdstart(unit)
        !           505: int    unit;
        !           506: {
        !           507:        int                     drivecount;
        !           508:        register struct buf     *bp = 0;
        !           509:        register struct buf     *dp;
        !           510:        struct  scsi_xfer       *xs;
        !           511:        struct  scsi_rw_big     cmd;
        !           512:        int                     blkno, nblk;
        !           513:        struct sd_data *sd = sd_data + unit;
        !           514:        struct partition *p ;
        !           515: 
        !           516:        if(scsi_debug & PRINTROUTINES) printf("sdstart%d ",unit);
        !           517:        /*******************************************************\
        !           518:        * See if there is a buf to do and we are not already    *
        !           519:        * doing one                                             *
        !           520:        \*******************************************************/
        !           521:        if(!sd_free_xfer[unit])
        !           522:        {
        !           523:                return;    /* none for us, unit already underway */
        !           524:        }
        !           525: 
        !           526:        if(sd_xfer_block_wait[unit])    /* there is one, but a special waits */
        !           527:        {
        !           528:                return; /* give the special that's waiting a chance to run */
        !           529:        }
        !           530: 
        !           531: 
        !           532:        dp = &sd_buf_queue[unit];
        !           533:        if ((bp = dp->b_actf) != NULL)  /* yes, an assign */
        !           534:        {
        !           535:                dp->b_actf = bp->av_forw;
        !           536:        }
        !           537:        else
        !           538:        { 
        !           539:                return;
        !           540:        }
        !           541: 
        !           542:        xs=sd_get_xs(unit,0);   /* ok we can grab it */
        !           543:        xs->flags = INUSE;    /* Now ours */
        !           544:        /*******************************************************\
        !           545:        *  If the device has become invalid, abort all the      *
        !           546:        * reads and writes until all files have been closed and *
        !           547:        * re-openned                                            *
        !           548:        \*******************************************************/
        !           549:        if(!(sd->flags & SDVALID))
        !           550:        {
        !           551:                xs->error = XS_DRIVER_STUFFUP;
        !           552:                sd_done(unit,xs);  /* clean up (calls sdstart) */
        !           553:                return ;
        !           554:        }
        !           555:        /*******************************************************\
        !           556:        * We have a buf, now we should move the data into       *
        !           557:        * a scsi_xfer definition and try start it               *
        !           558:        \*******************************************************/
        !           559:        /*******************************************************\
        !           560:        *  First, translate the block to absolute               *
        !           561:        \*******************************************************/
        !           562:        p = sd->disklabel.d_partitions + PARTITION(bp->b_dev);
        !           563:        blkno = bp->b_blkno + p->p_offset;
        !           564:        nblk = (bp->b_bcount + 511) >> 9;
        !           565: 
        !           566:        /*******************************************************\
        !           567:        *  Fill out the scsi command                            *
        !           568:        \*******************************************************/
        !           569:        bzero(&cmd, sizeof(cmd));
        !           570:        cmd.op_code             =       (bp->b_flags & B_READ) 
        !           571:                                                ? READ_BIG : WRITE_BIG;
        !           572:        cmd.addr_3      =       (blkno & 0xff000000) >> 24;
        !           573:        cmd.addr_2      =       (blkno & 0xff0000) >> 16;
        !           574:        cmd.addr_1      =       (blkno & 0xff00) >> 8;
        !           575:        cmd.addr_0      =       blkno & 0xff;
        !           576:        cmd.length2     =       (nblk & 0xff00) >> 8;
        !           577:        cmd.length1     =       (nblk & 0xff);
        !           578:        /*******************************************************\
        !           579:        * Fill out the scsi_xfer structure                      *
        !           580:        *       Note: we cannot sleep as we may be an interrupt *
        !           581:        \*******************************************************/
        !           582:        xs->flags       |=      SCSI_NOSLEEP;
        !           583:        xs->adapter     =       sd->ctlr;
        !           584:        xs->targ        =       sd->targ;
        !           585:        xs->lu          =       sd->lu;
        !           586:        xs->retries     =       SD_RETRIES;
        !           587:        xs->timeout     =       10000;/* 10000 millisecs for a disk !*/
        !           588:        xs->cmd         =       (struct scsi_generic *)&cmd;
        !           589:        xs->cmdlen      =       sizeof(cmd);
        !           590:        xs->resid       =       bp->b_bcount;
        !           591:        xs->when_done   =       sd_done;
        !           592:        xs->done_arg    =       unit;
        !           593:        xs->done_arg2   =       (int)xs;
        !           594:        xs->error       =       XS_NOERROR;
        !           595:        xs->bp          =       bp;
        !           596:        xs->data        =       (u_char *)bp->b_un.b_addr;
        !           597:        xs->datalen     =       bp->b_bcount;
        !           598:        /*******************************************************\
        !           599:        * Pass all this info to the scsi driver.                *
        !           600:        \*******************************************************/
        !           601: 
        !           602: 
        !           603: 
        !           604:        if ( (*(sd->sc_sw->scsi_cmd))(xs) != SUCCESSFULLY_QUEUED)
        !           605:        {
        !           606:                printf("sd%d: oops not queued",unit);
        !           607:                xs->error = XS_DRIVER_STUFFUP;
        !           608:                sd_done(unit,xs);  /* clean up (calls sdstart) */
        !           609:        }
        !           610:        sdqueues++;
        !           611: }
        !           612: 
        !           613: /*******************************************************\
        !           614: * This routine is called by the scsi interrupt when    *
        !           615: * the transfer is complete.
        !           616: \*******************************************************/
        !           617: int    sd_done(unit,xs)
        !           618: int    unit;
        !           619: struct scsi_xfer       *xs;
        !           620: {
        !           621:        struct  buf             *bp;
        !           622:        int     retval;
        !           623:        int     retries = 0;
        !           624: 
        !           625:        if(scsi_debug & PRINTROUTINES) printf("sd_done%d ",unit);
        !           626:        if (! (xs->flags & INUSE))
        !           627:                panic("scsi_xfer not in use!");
        !           628:        if(bp = xs->bp)
        !           629:        {
        !           630:                switch(xs->error)
        !           631:                {
        !           632:                case    XS_NOERROR:
        !           633:                        bp->b_error = 0;
        !           634:                        bp->b_resid = 0;
        !           635:                        break;
        !           636: 
        !           637:                case    XS_SENSE:
        !           638:                        retval = (sd_interpret_sense(unit,xs));
        !           639:                        if(retval)
        !           640:                        {
        !           641:                                bp->b_flags |= B_ERROR;
        !           642:                                bp->b_error = retval;
        !           643:                        }
        !           644:                        break;
        !           645: 
        !           646:                case    XS_TIMEOUT:
        !           647:                        printf("sd%d timeout\n",unit);
        !           648: 
        !           649:                case    XS_BUSY:        /* should retry */ /* how? */
        !           650:                        /************************************************/
        !           651:                        /* SHOULD put buf back at head of queue         */
        !           652:                        /* and decrement retry count in (*xs)           */
        !           653:                        /* HOWEVER, this should work as a kludge        */
        !           654:                        /************************************************/
        !           655:                        if(xs->retries--)
        !           656:                        {
        !           657:                                xs->error = XS_NOERROR;
        !           658:                                xs->flags &= ~ITSDONE;
        !           659:                                if ( (*(sd_data[unit].sc_sw->scsi_cmd))(xs)
        !           660:                                        == SUCCESSFULLY_QUEUED)
        !           661:                                {       /* don't wake the job, ok? */
        !           662:                                        return;
        !           663:                                }
        !           664:                                xs->flags |= ITSDONE;
        !           665:                        } /* fall through */
        !           666: 
        !           667:                case    XS_DRIVER_STUFFUP:
        !           668:                        bp->b_flags |= B_ERROR;
        !           669:                        bp->b_error = EIO;
        !           670:                        break;
        !           671:                default:
        !           672:                        printf("sd%d: unknown error category from scsi driver\n"
        !           673:                                ,unit);
        !           674:                }       
        !           675:                biodone(bp);
        !           676:                sd_free_xs(unit,xs,0);
        !           677:                sdstart(unit);  /* If there's anything waiting.. do it */
        !           678:        }
        !           679:        else /* special has finished */
        !           680:        {
        !           681:                wakeup(xs);
        !           682:        }
        !           683: }
        !           684: /*******************************************************\
        !           685: * Perform special action on behalf of the user         *
        !           686: * Knows about the internals of this device             *
        !           687: \*******************************************************/
        !           688: sdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
        !           689: {
        !           690:        /* struct sd_cmd_buf *args;*/
        !           691:        int error = 0;
        !           692:        unsigned int opri;
        !           693:        unsigned char unit, part;
        !           694:        register struct sd_data *sd;
        !           695: 
        !           696: 
        !           697:        /*******************************************************\
        !           698:        * Find the device that the user is talking about        *
        !           699:        \*******************************************************/
        !           700:        unit = UNIT(dev);
        !           701:        part = PARTITION(dev);
        !           702:        sd = &sd_data[unit];
        !           703:        if(scsi_debug & PRINTROUTINES) printf("sdioctl%d ",unit);
        !           704: 
        !           705:        /*******************************************************\
        !           706:        * If the device is not valid.. abandon ship             *
        !           707:        \*******************************************************/
        !           708:        if (!(sd_data[unit].flags & SDVALID))
        !           709:                return(EIO);
        !           710:        switch(cmd)
        !           711:        {
        !           712: 
        !           713:        case DIOCSBAD:
        !           714:                         error = EINVAL;
        !           715:                break;
        !           716: 
        !           717:        case DIOCGDINFO:
        !           718:                *(struct disklabel *)addr = sd->disklabel;
        !           719:                break;
        !           720: 
        !           721:         case DIOCGPART:
        !           722:                 ((struct partinfo *)addr)->disklab = &sd->disklabel;
        !           723:                 ((struct partinfo *)addr)->part =
        !           724:                     &sd->disklabel.d_partitions[PARTITION(dev)];
        !           725:                 break;
        !           726: 
        !           727:         case DIOCSDINFO:
        !           728:                 if ((flag & FWRITE) == 0)
        !           729:                         error = EBADF;
        !           730:                 else
        !           731:                         error = setdisklabel(&sd->disklabel,
        !           732:                                        (struct disklabel *)addr,
        !           733:                          /*(sd->flags & DKFL_BSDLABEL) ? sd->openparts : */0,
        !           734:                                sd->dosparts);
        !           735:                 if (error == 0) {
        !           736:                        sd->flags |= SDHAVELABEL;
        !           737:                }
        !           738:                 break;
        !           739: 
        !           740:         case DIOCWLABEL:
        !           741:                sd->flags &= ~SDWRITEPROT;
        !           742:                 if ((flag & FWRITE) == 0)
        !           743:                         error = EBADF;
        !           744:                 else
        !           745:                         sd->wlabel = *(int *)addr;
        !           746:                 break;
        !           747: 
        !           748:         case DIOCWDINFO:
        !           749:                sd->flags &= ~SDWRITEPROT;
        !           750:                 if ((flag & FWRITE) == 0)
        !           751:                         error = EBADF;
        !           752:                 else
        !           753:                {
        !           754:                        if ((error = setdisklabel(&sd->disklabel
        !           755:                                                , (struct disklabel *)addr
        !           756:                        , /*(sd->flags & SDHAVELABEL) ? sd->openparts :*/ 0
        !           757:                                                , sd->dosparts)) == 0)
        !           758:                        {
        !           759:                                int wlab;
        !           760: 
        !           761:                                sd->flags |= SDHAVELABEL; /* ok write will succeed */
        !           762: 
        !           763:                                /* simulate opening partition 0 so write succeeds */
        !           764:                                sd->openparts |= (1 << 0);            /* XXX */
        !           765:                                wlab = sd->wlabel;
        !           766:                                sd->wlabel = 1;
        !           767:                                error = writedisklabel(dev, sdstrategy,
        !           768:                                        &sd->disklabel, sd->dosparts);
        !           769:                                sd->wlabel = wlab;
        !           770:                        }
        !           771:                }
        !           772:                 break;
        !           773: 
        !           774: 
        !           775:        default:
        !           776:                error = ENOTTY;
        !           777:                break;
        !           778:        }
        !           779:        return (error);
        !           780: }
        !           781: 
        !           782: 
        !           783: /*******************************************************\
        !           784: * Load the label information on the named device       *
        !           785: \*******************************************************/
        !           786: int sdgetdisklabel(unit)
        !           787: unsigned char  unit;
        !           788: {
        !           789:        /*unsigned int n, m;*/
        !           790:        char *errstring;
        !           791:        struct dos_partition *dos_partition_p;
        !           792:        struct sd_data *sd = sd_data + unit;
        !           793: 
        !           794:        /*******************************************************\
        !           795:        * If the inflo is already loaded, use it                *
        !           796:        \*******************************************************/
        !           797:        if(sd->flags & SDHAVELABEL) return(ESUCCESS);
        !           798: 
        !           799:        bzero(&sd->disklabel,sizeof(struct disklabel));
        !           800:        /*******************************************************\
        !           801:        * make partition 3 the whole disk in case of failure    *
        !           802:        *   then get pdinfo                                     *
        !           803:        \*******************************************************/
        !           804:        sd->disklabel.d_partitions[0].p_offset = 0;
        !           805:        sd->disklabel.d_partitions[0].p_size = sd->params.disksize;
        !           806:        sd->disklabel.d_partitions[RAW_PART].p_offset = 0;
        !           807:        sd->disklabel.d_partitions[RAW_PART].p_size = sd->params.disksize;
        !           808:        sd->disklabel.d_npartitions = MAXPARTITIONS;
        !           809:        sd->disklabel.d_secsize = 512; /* as long as it's not 0 */
        !           810:        sd->disklabel.d_ntracks = sd->params.heads;
        !           811:        sd->disklabel.d_nsectors = sd->params.sectors;
        !           812:        sd->disklabel.d_ncylinders = sd->params.cyls;
        !           813:        sd->disklabel.d_secpercyl = sd->params.heads * sd->params.sectors;
        !           814:        if (sd->disklabel.d_secpercyl == 0)
        !           815:        {
        !           816:                sd->disklabel.d_secpercyl = 100;
        !           817:                                        /* as long as it's not 0 */
        !           818:                                        /* readdisklabel divides by it */
        !           819:        }
        !           820: 
        !           821:        /*******************************************************\
        !           822:        * all the generic bisklabel extraction routine          *
        !           823:        \*******************************************************/
        !           824:        if(errstring = readdisklabel(makedev(0 ,(unit<<UNITSHIFT )+3)
        !           825:                                        , sdstrategy
        !           826:                                        , &sd->disklabel
        !           827:                                        , sd->dosparts
        !           828:                                        , 0
        !           829:                                        , 0))
        !           830:        {
        !           831:                printf("sd%d: %s\n",unit, errstring);
        !           832:                return(ENXIO);
        !           833:        }
        !           834:        /*******************************************************\
        !           835:        * leave partition 2 "open" for raw I/O                  *
        !           836:        \*******************************************************/
        !           837: 
        !           838:        sd->flags |= SDHAVELABEL; /* WE HAVE IT ALL NOW */
        !           839:        return(ESUCCESS);
        !           840: }
        !           841: 
        !           842: /*******************************************************\
        !           843: * Find out from the device what it's capacity is       *
        !           844: \*******************************************************/
        !           845: sd_size(unit, flags)
        !           846: {
        !           847:        struct scsi_read_cap_data rdcap;
        !           848:        struct scsi_read_capacity scsi_cmd;
        !           849:        int size;
        !           850: 
        !           851:        /*******************************************************\
        !           852:        * make up a scsi command and ask the scsi driver to do  *
        !           853:        * it for you.                                           *
        !           854:        \*******************************************************/
        !           855:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !           856:        scsi_cmd.op_code = READ_CAPACITY;
        !           857: 
        !           858:        /*******************************************************\
        !           859:        * If the command works, interpret the result as a 4 byte*
        !           860:        * number of blocks                                      *
        !           861:        \*******************************************************/
        !           862:        if (sd_scsi_cmd(unit,
        !           863:                        &scsi_cmd,
        !           864:                        sizeof(scsi_cmd),
        !           865:                        &rdcap,
        !           866:                        sizeof(rdcap),  
        !           867:                        2000,
        !           868:                        flags) != 0)
        !           869:        {
        !           870:                printf("could not get size of unit %d\n", unit);
        !           871:                return(0);
        !           872:        } else {
        !           873:                size = rdcap.addr_0 + 1 ;
        !           874:                size += rdcap.addr_1 << 8;
        !           875:                size += rdcap.addr_2 << 16;
        !           876:                size += rdcap.addr_3 << 24;
        !           877:        }
        !           878:        return(size);
        !           879: }
        !           880:        
        !           881: /*******************************************************\
        !           882: * Get scsi driver to send a "are you ready?" command   *
        !           883: \*******************************************************/
        !           884: sd_test_unit_ready(unit,flags)
        !           885: int    unit,flags;
        !           886: {
        !           887:        struct  scsi_test_unit_ready scsi_cmd;
        !           888: 
        !           889:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !           890:        scsi_cmd.op_code = TEST_UNIT_READY;
        !           891: 
        !           892:        return (sd_scsi_cmd(unit,
        !           893:                        &scsi_cmd,
        !           894:                        sizeof(scsi_cmd),
        !           895:                        0,
        !           896:                        0,
        !           897:                        100000,
        !           898:                        flags));
        !           899: }
        !           900: 
        !           901: /*******************************************************\
        !           902: * Prevent or allow the user to remove the tape         *
        !           903: \*******************************************************/
        !           904: sd_prevent(unit,type,flags)
        !           905: int    unit,type,flags;
        !           906: {
        !           907:        struct  scsi_prevent    scsi_cmd;
        !           908: 
        !           909:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !           910:        scsi_cmd.op_code = PREVENT_ALLOW;
        !           911:        scsi_cmd.prevent=type;
        !           912:        return (sd_scsi_cmd(unit,
        !           913:                        &scsi_cmd,
        !           914:                        sizeof(scsi_cmd),
        !           915:                        0,
        !           916:                        0,
        !           917:                        5000,
        !           918:                        flags) );
        !           919: }
        !           920: /*******************************************************\
        !           921: * Get scsi driver to send a "start up" command         *
        !           922: \*******************************************************/
        !           923: sd_start_unit(unit,flags)
        !           924: int    unit,flags;
        !           925: {
        !           926:        struct scsi_start_stop scsi_cmd;
        !           927: 
        !           928:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !           929:        scsi_cmd.op_code = START_STOP;
        !           930:        scsi_cmd.start = 1;
        !           931: 
        !           932:        return (sd_scsi_cmd(unit,
        !           933:                        &scsi_cmd,
        !           934:                        sizeof(scsi_cmd),
        !           935:                        0,
        !           936:                        0,
        !           937:                        2000,
        !           938:                        flags));
        !           939: }
        !           940: 
        !           941: /*******************************************************\
        !           942: * Tell the device to map out a defective block         *
        !           943: \*******************************************************/
        !           944: sd_reassign_blocks(unit,block)
        !           945: {
        !           946:        struct  scsi_reassign_blocks            scsi_cmd;
        !           947:        struct  scsi_reassign_blocks_data       rbdata;
        !           948: 
        !           949: 
        !           950:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !           951:        bzero(&rbdata, sizeof(rbdata));
        !           952:        scsi_cmd.op_code = REASSIGN_BLOCKS;
        !           953: 
        !           954:        rbdata.length_msb = 0;
        !           955:        rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]);
        !           956:        rbdata.defect_descriptor[0].dlbaddr_3 = ((block >> 24) & 0xff);
        !           957:        rbdata.defect_descriptor[0].dlbaddr_2 = ((block >> 16) & 0xff);
        !           958:        rbdata.defect_descriptor[0].dlbaddr_1 = ((block >>  8) & 0xff);
        !           959:        rbdata.defect_descriptor[0].dlbaddr_0 = ((block      ) & 0xff);
        !           960: 
        !           961:        return(sd_scsi_cmd(unit,
        !           962:                        &scsi_cmd,
        !           963:                        sizeof(scsi_cmd),
        !           964:                        &rbdata,
        !           965:                        sizeof(rbdata),
        !           966:                        5000,
        !           967:                        0));
        !           968: }
        !           969: 
        !           970: #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
        !           971: 
        !           972: /*******************************************************\
        !           973: * Get the scsi driver to send a full inquiry to the    *
        !           974: * device and use the results to fill out the disk      *
        !           975: * parameter structure.                                 *
        !           976: \*******************************************************/
        !           977: 
        !           978: int    sd_get_parms(unit, flags)
        !           979: {
        !           980:        struct sd_data *sd = sd_data + unit;
        !           981:        struct disk_parms *disk_parms = &sd->params;
        !           982:        struct  scsi_mode_sense         scsi_cmd;
        !           983:        struct  scsi_mode_sense_data
        !           984:        {
        !           985:                struct  scsi_mode_header        header;
        !           986:                struct  blk_desc                blk_desc;
        !           987:                union   disk_pages              pages;
        !           988:        }scsi_sense;
        !           989:        int sectors;
        !           990: 
        !           991:        /*******************************************************\
        !           992:        * First check if we have it all loaded                  *
        !           993:        \*******************************************************/
        !           994:                if(sd->flags & SDVALID) return(0);
        !           995:        /*******************************************************\
        !           996:        * First do a mode sense page 3                          *
        !           997:        \*******************************************************/
        !           998:        if (sd_debug)
        !           999:        {
        !          1000:                bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1001:                scsi_cmd.op_code = MODE_SENSE;
        !          1002:                scsi_cmd.page_code = 3;
        !          1003:                scsi_cmd.length = 0x24;
        !          1004:                /*******************************************************\
        !          1005:                * do the command, but we don't need the results         *
        !          1006:                * just print them for our interest's sake               *
        !          1007:                \*******************************************************/
        !          1008:                if (sd_scsi_cmd(unit,
        !          1009:                                &scsi_cmd,
        !          1010:                                sizeof(scsi_cmd),
        !          1011:                                &scsi_sense,
        !          1012:                                sizeof(scsi_sense),
        !          1013:                                2000,
        !          1014:                                flags) != 0)
        !          1015:                {
        !          1016:                        printf("could not mode sense (3) for unit %d\n", unit);
        !          1017:                        return(ENXIO);
        !          1018:                } 
        !          1019:                printf("unit %d: %d trk/zone, %d alt_sec/zone, %d alt_trk/zone, %d alt_trk/lun\n",
        !          1020:                        unit,
        !          1021:                        b2tol(scsi_sense.pages.disk_format.trk_z),
        !          1022:                        b2tol(scsi_sense.pages.disk_format.alt_sec),
        !          1023:                        b2tol(scsi_sense.pages.disk_format.alt_trk_z),
        !          1024:                        b2tol(scsi_sense.pages.disk_format.alt_trk_v));
        !          1025:                printf("         %d sec/trk, %d bytes/sec, %d interleave, %d %d bytes/log_blk\n",
        !          1026:                        b2tol(scsi_sense.pages.disk_format.ph_sec_t),
        !          1027:                        b2tol(scsi_sense.pages.disk_format.bytes_s),
        !          1028:                        b2tol(scsi_sense.pages.disk_format.interleave),
        !          1029:                        sd_size(unit, flags),
        !          1030:                        _3btol(scsi_sense.blk_desc.blklen));
        !          1031:        }
        !          1032: 
        !          1033: 
        !          1034:        /*******************************************************\
        !          1035:        * do a "mode sense page 4"                              *
        !          1036:        \*******************************************************/
        !          1037:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1038:        scsi_cmd.op_code = MODE_SENSE;
        !          1039:        scsi_cmd.page_code = 4;
        !          1040:        scsi_cmd.length = 0x20;
        !          1041:        /*******************************************************\
        !          1042:        * If the command worked, use the results to fill out    *
        !          1043:        * the parameter structure                               *
        !          1044:        \*******************************************************/
        !          1045:        if (sd_scsi_cmd(unit,
        !          1046:                        &scsi_cmd,
        !          1047:                        sizeof(scsi_cmd),
        !          1048:                        &scsi_sense,
        !          1049:                        sizeof(scsi_sense),
        !          1050:                        2000,
        !          1051:                        flags) != 0)
        !          1052:        {
        !          1053:                printf("could not mode sense (4) for unit %d\n", unit);
        !          1054:                printf(" using ficticious geometry\n");
        !          1055:                /* use adaptec standard ficticious geometry */
        !          1056:                sectors = sd_size(unit, flags);
        !          1057:                disk_parms->heads = 64;
        !          1058:                disk_parms->sectors = 32;
        !          1059:                disk_parms->cyls = sectors/(64 * 32);
        !          1060:                disk_parms->secsiz = SECSIZE;
        !          1061:        } 
        !          1062:        else
        !          1063:        {
        !          1064: 
        !          1065:                if (sd_debug)
        !          1066:                {
        !          1067:                printf("         %d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n",
        !          1068:                        _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2),
        !          1069:                        scsi_sense.pages.rigid_geometry.nheads,
        !          1070:                        b2tol(scsi_sense.pages.rigid_geometry.st_cyl_wp),
        !          1071:                        b2tol(scsi_sense.pages.rigid_geometry.st_cyl_rwc),
        !          1072:                        b2tol(scsi_sense.pages.rigid_geometry.land_zone));
        !          1073:                }
        !          1074: 
        !          1075:                /*******************************************************\
        !          1076:                * KLUDGE!!(for zone recorded disks)                     *
        !          1077:                * give a number of sectors so that sec * trks * cyls    *
        !          1078:                * is <= disk_size                                       *
        !          1079:                \*******************************************************/
        !          1080:                disk_parms->heads = scsi_sense.pages.rigid_geometry.nheads;
        !          1081:                disk_parms->cyls = _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2);
        !          1082:                disk_parms->secsiz = _3btol(&scsi_sense.blk_desc.blklen);
        !          1083: 
        !          1084:                sectors = sd_size(unit, flags);
        !          1085:                sectors /= disk_parms->cyls;
        !          1086:                sectors /= disk_parms->heads;
        !          1087:                disk_parms->sectors = sectors; /* dubious on SCSI*/
        !          1088:        }
        !          1089: 
        !          1090:        sd->flags |= SDVALID;
        !          1091:        return(0);
        !          1092: }
        !          1093: 
        !          1094: /*******************************************************\
        !          1095: * close the device.. only called if we are the LAST    *
        !          1096: * occurence of an open device                          *
        !          1097: \*******************************************************/
        !          1098: sdclose(dev)
        !          1099: dev_t dev;
        !          1100: {
        !          1101:        unsigned char unit, part;
        !          1102:        unsigned int old_priority;
        !          1103: 
        !          1104:        unit = UNIT(dev);
        !          1105:        part = PARTITION(dev);
        !          1106:        sd_data[unit].partflags[part] &= ~SDOPEN;
        !          1107:        sd_data[unit].openparts &= ~(1 << part);
        !          1108:        if(sd_data[unit].openparts == 0) /* if all partitions closed */
        !          1109:        {
        !          1110:                sd_prevent(unit,PR_ALLOW,SCSI_SILENT|SCSI_ERR_OK);
        !          1111:        }
        !          1112:        return(0);
        !          1113: }
        !          1114: 
        !          1115: /*******************************************************\
        !          1116: * ask the scsi driver to perform a command for us.     *
        !          1117: * Call it through the switch table, and tell it which  *
        !          1118: * sub-unit we want, and what target and lu we wish to  *
        !          1119: * talk to. Also tell it where to find the command      *
        !          1120: * how long int is.                                     *
        !          1121: * Also tell it where to read/write the data, and how   *
        !          1122: * long the data is supposed to be                      *
        !          1123: \*******************************************************/
        !          1124: int    sd_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags)
        !          1125: 
        !          1126: int    unit,flags;
        !          1127: struct scsi_generic *scsi_cmd;
        !          1128: int    cmdlen;
        !          1129: int    timeout;
        !          1130: u_char *data_addr;
        !          1131: int    datalen;
        !          1132: {
        !          1133:        struct  scsi_xfer *xs;
        !          1134:        int     retval;
        !          1135:        int     s;
        !          1136:        struct sd_data *sd = sd_data + unit;
        !          1137: 
        !          1138:        if(scsi_debug & PRINTROUTINES) printf("\nsd_scsi_cmd%d ",unit);
        !          1139:        if(sd->sc_sw)   /* If we have a scsi driver */
        !          1140:        {
        !          1141:                xs = sd_get_xs(unit,flags); /* should wait unless booting */
        !          1142:                if(!xs)
        !          1143:                {
        !          1144:                        printf("sd_scsi_cmd%d: controller busy"
        !          1145:                                        " (this should never happen)\n",unit); 
        !          1146:                                return(EBUSY);
        !          1147:                }
        !          1148:                xs->flags |= INUSE;
        !          1149:                /*******************************************************\
        !          1150:                * Fill out the scsi_xfer structure                      *
        !          1151:                \*******************************************************/
        !          1152:                xs->flags       |=      flags;
        !          1153:                xs->adapter     =       sd->ctlr;
        !          1154:                xs->targ        =       sd->targ;
        !          1155:                xs->lu          =       sd->lu;
        !          1156:                xs->retries     =       SD_RETRIES;
        !          1157:                xs->timeout     =       timeout;
        !          1158:                xs->cmd         =       scsi_cmd;
        !          1159:                xs->cmdlen      =       cmdlen;
        !          1160:                xs->data        =       data_addr;
        !          1161:                xs->datalen     =       datalen;
        !          1162:                xs->resid       =       datalen;
        !          1163:                xs->when_done   =       (flags & SCSI_NOMASK)
        !          1164:                                        ?(int (*)())0
        !          1165:                                        :sd_done;
        !          1166:                xs->done_arg    =       unit;
        !          1167:                xs->done_arg2   =       (int)xs;
        !          1168: retry:         xs->error       =       XS_NOERROR;
        !          1169:                xs->bp          =       0;
        !          1170:                retval = (*(sd->sc_sw->scsi_cmd))(xs);
        !          1171:                switch(retval)
        !          1172:                {
        !          1173:                case    SUCCESSFULLY_QUEUED:
        !          1174:                        s = splbio();
        !          1175:                        while(!(xs->flags & ITSDONE))
        !          1176:                                sleep(xs,PRIBIO+1);
        !          1177:                        splx(s);
        !          1178: 
        !          1179:                case    HAD_ERROR:
        !          1180:                        /*printf("err = %d ",xs->error);*/
        !          1181:                        switch(xs->error)
        !          1182:                        {
        !          1183:                        case    XS_NOERROR:
        !          1184:                                retval = ESUCCESS;
        !          1185:                                break;
        !          1186:                        case    XS_SENSE:
        !          1187:                                retval = (sd_interpret_sense(unit,xs));
        !          1188:                                break;
        !          1189:                        case    XS_DRIVER_STUFFUP:
        !          1190:                                retval = EIO;
        !          1191:                                break;
        !          1192:                        case    XS_TIMEOUT:
        !          1193:                                if(xs->retries-- )
        !          1194:                                {
        !          1195:                                        xs->flags &= ~ITSDONE;
        !          1196:                                        goto retry;
        !          1197:                                }
        !          1198:                                retval = EIO;
        !          1199:                                break;
        !          1200:                        case    XS_BUSY:
        !          1201:                                if(xs->retries-- )
        !          1202:                                {
        !          1203:                                        xs->flags &= ~ITSDONE;
        !          1204:                                        goto retry;
        !          1205:                                }
        !          1206:                                retval = EIO;
        !          1207:                                break;
        !          1208:                        default:
        !          1209:                                retval = EIO;
        !          1210:                                printf("sd%d: unknown error category from scsi driver\n"
        !          1211:                                        ,unit);
        !          1212:                        }       
        !          1213:                        break;
        !          1214:                case    COMPLETE:
        !          1215:                        retval = ESUCCESS;
        !          1216:                        break;
        !          1217:                case    TRY_AGAIN_LATER:
        !          1218:                        if(xs->retries-- )
        !          1219:                        {
        !          1220:                                xs->flags &= ~ITSDONE;
        !          1221:                                goto retry;
        !          1222:                        }
        !          1223:                        retval = EIO;
        !          1224:                        break;
        !          1225:                default:
        !          1226:                        retval = EIO;
        !          1227:                }
        !          1228:                sd_free_xs(unit,xs,flags);
        !          1229:                sdstart(unit);          /* check if anything is waiting fr the xs */
        !          1230:        }
        !          1231:        else
        !          1232:        {
        !          1233:                printf("sd%d: not set up\n",unit);
        !          1234:                return(EINVAL);
        !          1235:        }
        !          1236:        return(retval);
        !          1237: }
        !          1238: /***************************************************************\
        !          1239: * Look at the returned sense and act on the error and detirmine        *
        !          1240: * The unix error number to pass back... (0 = report no error)  *
        !          1241: \***************************************************************/
        !          1242: 
        !          1243: int    sd_interpret_sense(unit,xs)
        !          1244: int    unit;
        !          1245: struct scsi_xfer *xs;
        !          1246: {
        !          1247:        struct  scsi_sense_data *sense;
        !          1248:        int     key;
        !          1249:        int     silent;
        !          1250: 
        !          1251:        /***************************************************************\
        !          1252:        * If the flags say errs are ok, then always return ok.          *
        !          1253:        \***************************************************************/
        !          1254:        if (xs->flags & SCSI_ERR_OK) return(ESUCCESS);
        !          1255:        silent = (xs->flags & SCSI_SILENT);
        !          1256: 
        !          1257:        sense = &(xs->sense);
        !          1258:        switch(sense->error_class)
        !          1259:        {
        !          1260:        case 7:
        !          1261:                {
        !          1262:                key=sense->ext.extended.sense_key;
        !          1263:                switch(key)
        !          1264:                {
        !          1265:                case    0x0:
        !          1266:                        return(ESUCCESS);
        !          1267:                case    0x1:
        !          1268:                        if(!silent)
        !          1269:                        {
        !          1270:                                printf("sd%d: soft error(corrected) ", unit); 
        !          1271:                                if(sense->valid)
        !          1272:                                {
        !          1273:                                        printf("block no. %d (decimal)",
        !          1274:                                        (sense->ext.extended.info[0] <<24),
        !          1275:                                        (sense->ext.extended.info[1] <<16),
        !          1276:                                        (sense->ext.extended.info[2] <<8),
        !          1277:                                        (sense->ext.extended.info[3] ));
        !          1278:                                }
        !          1279:                                printf("\n");
        !          1280:                        }
        !          1281:                        return(ESUCCESS);
        !          1282:                case    0x2:
        !          1283:                        if(!silent)printf("sd%d: not ready\n ",
        !          1284:                                unit); 
        !          1285:                        return(ENODEV);
        !          1286:                case    0x3:
        !          1287:                        if(!silent)
        !          1288:                        {
        !          1289:                                printf("sd%d: medium error ", unit); 
        !          1290:                                if(sense->valid)
        !          1291:                                {
        !          1292:                                        printf("block no. %d (decimal)",
        !          1293:                                        (sense->ext.extended.info[0] <<24),
        !          1294:                                        (sense->ext.extended.info[1] <<16),
        !          1295:                                        (sense->ext.extended.info[2] <<8),
        !          1296:                                        (sense->ext.extended.info[3] ));
        !          1297:                                }
        !          1298:                                printf("\n");
        !          1299:                        }
        !          1300:                        return(EIO);
        !          1301:                case    0x4:
        !          1302:                        if(!silent)printf("sd%d: non-media hardware failure\n ",
        !          1303:                                unit); 
        !          1304:                        return(EIO);
        !          1305:                case    0x5:
        !          1306:                        if(!silent)printf("sd%d: illegal request\n ",
        !          1307:                                unit); 
        !          1308:                        return(EINVAL);
        !          1309:                case    0x6:
        !          1310:                        /***********************************************\
        !          1311:                        * If we are not open, then this is not an error *
        !          1312:                        * as we don't have state yet. Either way, make  *
        !          1313:                        * sure that we don't have any residual state    *
        !          1314:                        \***********************************************/
        !          1315:                        if(!silent)printf("sd%d: Unit attention.\n ", unit); 
        !          1316:                        sd_data[unit].flags &= ~(SDVALID | SDHAVELABEL);
        !          1317:                        if (sd_data[unit].openparts)
        !          1318:                        {
        !          1319:                                return(EIO);
        !          1320:                        }
        !          1321:                        return(ESUCCESS); /* not an error if nothing's open */
        !          1322:                case    0x7:
        !          1323:                        if(!silent)
        !          1324:                        {
        !          1325:                                printf("sd%d: attempted protection violation ",
        !          1326:                                                unit); 
        !          1327:                                if(sense->valid)
        !          1328:                                {
        !          1329:                                        printf("block no. %d (decimal)\n",
        !          1330:                                        (sense->ext.extended.info[0] <<24),
        !          1331:                                        (sense->ext.extended.info[1] <<16),
        !          1332:                                        (sense->ext.extended.info[2] <<8),
        !          1333:                                        (sense->ext.extended.info[3] ));
        !          1334:                                }
        !          1335:                                printf("\n");
        !          1336:                        }
        !          1337:                        return(EACCES);
        !          1338:                case    0x8:
        !          1339:                        if(!silent)
        !          1340:                        {
        !          1341:                                printf("sd%d: block wrong state (worm)\n ",
        !          1342:                                unit); 
        !          1343:                                if(sense->valid)
        !          1344:                                {
        !          1345:                                        printf("block no. %d (decimal)\n",
        !          1346:                                        (sense->ext.extended.info[0] <<24),
        !          1347:                                        (sense->ext.extended.info[1] <<16),
        !          1348:                                        (sense->ext.extended.info[2] <<8),
        !          1349:                                        (sense->ext.extended.info[3] ));
        !          1350:                                }
        !          1351:                                printf("\n");
        !          1352:                        }
        !          1353:                        return(EIO);
        !          1354:                case    0x9:
        !          1355:                        if(!silent)printf("sd%d: vendor unique\n",
        !          1356:                                unit); 
        !          1357:                        return(EIO);
        !          1358:                case    0xa:
        !          1359:                        if(!silent)printf("sd%d: copy aborted\n ",
        !          1360:                                unit); 
        !          1361:                        return(EIO);
        !          1362:                case    0xb:
        !          1363:                        if(!silent)printf("sd%d: command aborted\n ",
        !          1364:                                unit); 
        !          1365:                        return(EIO);
        !          1366:                case    0xc:
        !          1367:                        if(!silent)
        !          1368:                        {
        !          1369:                                printf("sd%d: search returned\n ",
        !          1370:                                        unit); 
        !          1371:                                if(sense->valid)
        !          1372:                                {
        !          1373:                                        printf("block no. %d (decimal)\n",
        !          1374:                                        (sense->ext.extended.info[0] <<24),
        !          1375:                                        (sense->ext.extended.info[1] <<16),
        !          1376:                                        (sense->ext.extended.info[2] <<8),
        !          1377:                                        (sense->ext.extended.info[3] ));
        !          1378:                                }
        !          1379:                                printf("\n");
        !          1380:                        }
        !          1381:                        return(ESUCCESS);
        !          1382:                case    0xd:
        !          1383:                        if(!silent)printf("sd%d: volume overflow\n ",
        !          1384:                                unit); 
        !          1385:                        return(ENOSPC);
        !          1386:                case    0xe:
        !          1387:                        if(!silent)
        !          1388:                        {
        !          1389:                                printf("sd%d: verify miscompare\n ",
        !          1390:                                unit); 
        !          1391:                                if(sense->valid)
        !          1392:                                {
        !          1393:                                        printf("block no. %d (decimal)\n",
        !          1394:                                        (sense->ext.extended.info[0] <<24),
        !          1395:                                        (sense->ext.extended.info[1] <<16),
        !          1396:                                        (sense->ext.extended.info[2] <<8),
        !          1397:                                        (sense->ext.extended.info[3] ));
        !          1398:                                }
        !          1399:                                printf("\n");
        !          1400:                        }
        !          1401:                        return(EIO);
        !          1402:                case    0xf:
        !          1403:                        if(!silent)printf("sd%d: unknown error key\n ",
        !          1404:                                unit); 
        !          1405:                        return(EIO);
        !          1406:                }
        !          1407:                break;
        !          1408:        }
        !          1409:        case 0:
        !          1410:        case 1:
        !          1411:        case 2:
        !          1412:        case 3:
        !          1413:        case 4:
        !          1414:        case 5:
        !          1415:        case 6:
        !          1416:                {
        !          1417:                        if(!silent)printf("sd%d: error class %d code %d\n",
        !          1418:                                unit,
        !          1419:                                sense->error_class,
        !          1420:                                sense->error_code);
        !          1421:                if(sense->valid)
        !          1422:                        if(!silent)printf("block no. %d (decimal)\n",
        !          1423:                        (sense->ext.unextended.blockhi <<16),
        !          1424:                        + (sense->ext.unextended.blockmed <<8),
        !          1425:                        + (sense->ext.unextended.blocklow ));
        !          1426:                }
        !          1427:                return(EIO);
        !          1428:        }
        !          1429: }
        !          1430: 
        !          1431: 
        !          1432: 
        !          1433: 
        !          1434: int
        !          1435: sdsize(dev_t dev)
        !          1436: {
        !          1437:        int unit = UNIT(dev), part = PARTITION(dev), val;
        !          1438:        struct sd_data *sd;
        !          1439: 
        !          1440:        if (unit >= NSD)
        !          1441:                return(-1);
        !          1442: 
        !          1443:        sd = &sd_data[unit];
        !          1444:        if((sd->flags & SDINIT) == 0) return(-1);
        !          1445:        if (sd == 0 || (sd->flags & SDHAVELABEL) == 0)
        !          1446:                val = sdopen (MAKESDDEV(major(dev), unit, RAW_PART), FREAD, S_IFBLK, 0);
        !          1447:        if ( val != 0 || sd->flags & SDWRITEPROT)
        !          1448:                return (-1);
        !          1449: 
        !          1450:        return((int)sd->disklabel.d_partitions[part].p_size);
        !          1451: }
        !          1452: 
        !          1453: sddump()
        !          1454: {
        !          1455:     printf("sddump()        -- not implemented\n");
        !          1456:     return(-1);
        !          1457: }
        !          1458: 
        !          1459: 
        !          1460: 
        !          1461: 
        !          1462: 

unix.superglobalmegacorp.com

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