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

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

unix.superglobalmegacorp.com

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