Annotation of Net2/scsi/scsiconf.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:  *     scsiconf.c,v 1.9 1993/05/27 10:14:02 deraadt Exp
1.1       root       17:  */
                     18: 
1.1.1.2 ! root       19: #include "sys/types.h"
        !            20: #include "sys/param.h"
        !            21: #include "sys/systm.h"
        !            22: #include "sys/errno.h"
        !            23: #include "sys/ioctl.h"
        !            24: #include "sys/buf.h"
        !            25: #include "sys/proc.h"
        !            26: #include "sys/user.h"
        !            27: #include "sys/dkbad.h"
        !            28: #include "sys/disklabel.h"
        !            29: #include "scsi/scsi_all.h"
        !            30: #include "scsi/scsiconf.h"
1.1       root       31: 
                     32: #include "st.h"
                     33: #include "sd.h"
                     34: #include "ch.h"
                     35: #include "cd.h"
                     36: #define        NBLL 0
                     37: #define        NCALS 0
                     38: #define        NKIL 0
                     39: 
                     40: #if NSD > 0
1.1.1.2 ! root       41: extern int sdattach();
1.1       root       42: #endif NSD
                     43: #if NST > 0
1.1.1.2 ! root       44: extern int stattach();
1.1       root       45: #endif NST
                     46: #if NCH > 0
1.1.1.2 ! root       47: extern int chattach();
1.1       root       48: #endif NCH
                     49: #if NCD > 0
1.1.1.2 ! root       50: extern int cdattach();
1.1       root       51: #endif NCD
                     52: #if NBLL > 0
1.1.1.2 ! root       53: extern int bllattach();
1.1       root       54: #endif NBLL
                     55: #if NCALS > 0
1.1.1.2 ! root       56: extern int calsattach();
1.1       root       57: #endif NCALS
                     58: #if NKIL > 0
1.1.1.2 ! root       59: extern int kil_attach();
1.1       root       60: #endif NKIL
                     61: 
1.1.1.2 ! root       62: struct scsidevs knowndevs[] = {
1.1       root       63: #if NSD > 0
1.1.1.2 ! root       64:        {
        !            65:                SC_TSD, T_DIRECT, T_FIXED, "standard", "any" ,"any",
        !            66:                sdattach, "sd" ,SC_ONE_LU
        !            67:        }, {
        !            68:                SC_TSD, T_DIRECT, T_FIXED, "MAXTOR  ", "XT-4170S        ", "B5A ",
        !            69:                sdattach, "mx1", SC_ONE_LU
        !            70:        },
1.1       root       71: #endif NSD
                     72: #if NST > 0
1.1.1.2 ! root       73:        {
        !            74:                SC_TST, T_SEQUENTIAL, T_REMOV, "standard", "any", "any",
        !            75:                stattach, "st" ,SC_ONE_LU
        !            76:        },
1.1       root       77: #endif NST
1.1.1.2 ! root       78: #if NCD > 0
        !            79:        {
        !            80:                SC_TCD, T_READONLY, T_REMOV, "SONY    ", "CD-ROM CDU-8012 ", "3.1a",
        !            81:                cdattach, "cd", SC_ONE_LU
        !            82:        }, {
        !            83:                SC_TCD, T_READONLY, T_REMOV, "PIONEER ", "CD-ROM DRM-600  ", "any",
        !            84:                cdattach, "cd", SC_MORE_LUS
        !            85:        },
        !            86: #endif NCD
1.1       root       87: #if NCALS > 0
1.1.1.2 ! root       88:        {
        !            89:                -1, T_PROCESSOR, T_FIXED, "standard" , "any" ,"any",
        !            90:                calsattach, "cals", SC_MORE_LUS
        !            91:        }
1.1       root       92: #endif NCALS
                     93: #if NCH > 0
1.1.1.2 ! root       94:        {
        !            95:                -1, T_CHANGER, T_REMOV, "standard", "any", "any",
        !            96:                chattach, "ch", SC_ONE_LU
        !            97:        },
1.1       root       98: #endif NCH
                     99: #if NBLL > 0
1.1.1.2 ! root      100:        {
        !           101:                -1, T_PROCESSOR, T_FIXED, "AEG     ", "READER     ", "V1.0",
        !           102:                bllattach, "bll", SC_MORE_LUS
        !           103:        },
1.1       root      104: #endif NBLL
                    105: #if NKIL > 0
1.1.1.2 ! root      106:        {
        !           107:                -1, T_SCANNER, T_FIXED, "KODAK   ", "IL Scanner 900  ", "any",
        !           108:                kil_attach, "kil", SC_ONE_LU
        !           109:        },
1.1       root      110: #endif NKIL
                    111: };
                    112: 
1.1.1.2 ! root      113: /* controls debug level within the scsi subsystem: see scsiconf.h */
        !           114: int scsi_debug = 0;
1.1       root      115: 
1.1.1.2 ! root      116: struct scsidevs *
        !           117: scsi_probe(int masunit, struct scsi_switch *sw, int physid, int type, int want)
1.1       root      118: {
1.1.1.2 ! root      119:        static struct scsi_inquiry_data inqbuf;
        !           120:        struct scsidevs *ret = (struct scsidevs *)0;
        !           121:        int targ = physid >> 3;
        !           122:        int lun = physid & 7;
        !           123:        char *qtype=NULL, *dtype=NULL, *desc;
        !           124:        char manu[9], model[17], revision[5];
        !           125:        int len;
        !           126: 
        !           127:        bzero(&inqbuf, sizeof inqbuf);
        !           128: 
        !           129:        /*printf("probe: %s%d targ %d lun %d\n",
        !           130:                sw->name, masunit, targ, lun);*/
        !           131: 
        !           132:        if( scsi_ready(masunit, targ, lun, sw,
        !           133:            SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
        !           134:                return (struct scsidevs *)-1;
1.1       root      135: 
1.1.1.2 ! root      136:        if( scsi_inquire(masunit, targ, lun, sw, (u_char *)&inqbuf,
        !           137:            SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
1.1       root      138:                return (struct scsidevs *)0;
                    139: 
1.1.1.2 ! root      140:        if( inqbuf.device_qualifier==3 && inqbuf.device_type==T_NODEVICE)
        !           141:                return (struct scsidevs *)0;
1.1       root      142: 
1.1.1.2 ! root      143:        switch(inqbuf.device_qualifier) {
        !           144:        case 0:
        !           145:                qtype = "";
1.1       root      146:                break;
1.1.1.2 ! root      147:        case 1:
        !           148:                qtype = "Unit not Connected!";
1.1       root      149:                break;
1.1.1.2 ! root      150:        case 2:
        !           151:                qtype =", Reserved Peripheral Qualifier!";
1.1       root      152:                break;
1.1.1.2 ! root      153:        case 3:
        !           154:                qtype = ", The Target can't support this Unit!";
1.1       root      155:                break;
1.1.1.2 ! root      156:        default:
        !           157:                dtype = "vendor specific";
        !           158:                qtype = "";
1.1       root      159:                break;
                    160:        }
                    161: 
1.1.1.2 ! root      162:        if (dtype == NULL) {
        !           163:                switch(inqbuf.device_type) {
        !           164:                case T_DIRECT:
        !           165:                        dtype = "direct";
        !           166:                        break;
        !           167:                case T_SEQUENTIAL:
        !           168:                        dtype = "seq";
        !           169:                        break;
        !           170:                case T_PRINTER:
        !           171:                        dtype = "pr";
        !           172:                        break;
        !           173:                case T_PROCESSOR:
        !           174:                        dtype = "cpu";
        !           175:                        break;
        !           176:                case T_READONLY:
        !           177:                        dtype = "ro";
        !           178:                        break;
        !           179:                case T_WORM:
        !           180:                        dtype = "worm";
        !           181:                        break;
        !           182:                case T_SCANNER:
        !           183:                        dtype = "scan";
        !           184:                        break;
        !           185:                case T_OPTICAL:
        !           186:                        dtype = "optic";
        !           187:                        break;
        !           188:                case T_CHANGER:
        !           189:                        dtype = "changer";
        !           190:                        break;
        !           191:                case T_COMM:
        !           192:                        dtype = "comm";
        !           193:                        break;
        !           194:                default:
        !           195:                        dtype = "???";
        !           196:                        break;
1.1       root      197:                }
1.1.1.2 ! root      198:        }
1.1       root      199: 
1.1.1.2 ! root      200:        if(inqbuf.ansii_version > 0) {
        !           201:                len = inqbuf.additional_length +
        !           202:                        ((char *)inqbuf.unused - (char *)&inqbuf);
        !           203:                if( len > sizeof(struct scsi_inquiry_data) - 1)
1.1       root      204:                        len = sizeof(struct scsi_inquiry_data) - 1;
1.1.1.2 ! root      205:                desc = inqbuf.vendor;
        !           206:                desc[len-(desc-(char *)&inqbuf)] = 0;
        !           207:                strncpy(manu, inqbuf.vendor, sizeof inqbuf.vendor);
        !           208:                manu[sizeof inqbuf.vendor] = '\0';
        !           209:                strncpy(model, inqbuf.product, sizeof inqbuf.product);
        !           210:                model[sizeof inqbuf.product] = '\0';
        !           211:                strncpy(revision, inqbuf.revision, sizeof inqbuf.revision);
        !           212:                revision[sizeof inqbuf.revision] = '\0';
        !           213:        } else {
        !           214:                desc = "early protocol device";
        !           215:                strcpy(manu, "????");
        !           216:                strcpy(model, "");
        !           217:                strcpy(revision, "");
        !           218:        }
        !           219: 
        !           220:        if(want)
        !           221:                goto print;
        !           222: 
        !           223:        ret = selectdev(masunit, targ, lun, sw, inqbuf.device_qualifier,
        !           224:                inqbuf.device_type, inqbuf.removable, manu, model, revision, type);
        !           225:        if(sw->printed[targ] & (1<<lun))
        !           226:                return ret;
        !           227: 
        !           228: print:
        !           229:        printf("%s%d targ %d lun %d: type %d(%s) %s <%s%s%s> SCSI%d\n",
        !           230:                sw->name, masunit, targ, lun,
        !           231:                inqbuf.device_type, dtype,
        !           232:                inqbuf.removable ? "removable" : "fixed",
        !           233:                manu, model, revision, inqbuf.ansii_version);
        !           234:        if(qtype[0])
        !           235:                printf("%s%d targ %d lun %d: qualifier %d(%s)\n",
        !           236:                        sw->name, masunit, targ, lun,
        !           237:                        inqbuf.device_qualifier, qtype);
        !           238:        sw->printed[targ] |= (1<<lun);
        !           239:        return ret;
1.1       root      240: }
                    241: 
1.1.1.2 ! root      242: void
        !           243: scsi_warn(int masunit, int mytarg, struct scsi_switch *sw)
1.1       root      244: {
1.1.1.2 ! root      245:        struct scsidevs *match = (struct scsidevs *)0;
        !           246:        int physid;
        !           247:        int targ, lun;
1.1       root      248: 
1.1.1.2 ! root      249:        for(targ=0; targ<8; targ++) {
        !           250:                if(targ==mytarg)
1.1       root      251:                        continue;
1.1.1.2 ! root      252:                for(lun=0; lun<8; lun++) {
        !           253:                        /* check if device already used, or empty */
        !           254:                        if( sw->empty[targ] & (1<<lun) )
        !           255:                                continue;
        !           256:                        if( sw->used[targ] & (1<<lun) )
        !           257:                                continue;
        !           258: 
        !           259:                        physid = targ*8 + lun;
        !           260:                        match = scsi_probe(masunit, sw, physid, 0, 0);
        !           261: 
        !           262:                        if(match == (struct scsidevs *)-1) {
        !           263:                                if(lun==0)
        !           264:                                        sw->empty[targ] = 0xff;
        !           265:                                else
        !           266:                                        sw->empty[targ] = 0xff;
        !           267:                                continue;
        !           268:                        }
        !           269:                        if(match) {
        !           270:                                targ = physid >> 3;
        !           271:                                lun = physid & 7;
        !           272:                                if(match->flags & SC_MORE_LUS)
        !           273:                                        sw->empty[targ] |= (1<<lun);
        !           274:                                else
        !           275:                                        sw->empty[targ] = 0xff;
        !           276:                        }
1.1       root      277:                }
1.1.1.2 ! root      278:        }
        !           279: }
        !           280: 
        !           281: /*
        !           282:  * not quite perfect. If we have two "drive ?" entries, this will
        !           283:  * probe through all the devices twice. It should have realized that
        !           284:  * any device that is not found the first time won't exist later on.
        !           285:  */
        !           286: int
        !           287: scsi_attach(int masunit, int mytarg, struct scsi_switch *sw,
        !           288:        int *physid, int *unit, int type)
        !           289: {
        !           290:        struct scsidevs *match = (struct scsidevs *)0;
        !           291:        int targ, lun;
        !           292:        int ret=0;
        !           293: 
        !           294:        /*printf("%s%d probing at targ %d lun %d..\n",
        !           295:                sw->name, masunit, *physid >> 3, *physid & 7);*/
        !           296: 
        !           297:        if( *physid!=-1 ) {
        !           298:                targ = *physid >> 3;
        !           299:                lun = *physid & 7;
        !           300: 
        !           301:                if( (sw->empty[targ] & (1<<lun)) || (sw->used[targ] & (1<<lun)) )
        !           302:                        return 0;
        !           303: 
        !           304:                match = scsi_probe(masunit, sw, *physid, type, 0);
        !           305:                if(match == (struct scsidevs *)-1) {
        !           306:                        match = (struct scsidevs *)0;
        !           307:                        if(lun==0)
        !           308:                                sw->empty[targ] = 0xff;
        !           309:                        else
        !           310:                                sw->empty[targ] |= (1<<lun);
        !           311:                        return 0;
1.1       root      312:                }
1.1.1.2 ! root      313: 
        !           314:                if(!match)
        !           315:                        return 0;
        !           316: 
        !           317:                ret = (*(match->attach_rtn))(masunit, sw, *physid, unit);
        !           318:                goto success;
        !           319:        }
        !           320: 
        !           321:        for(targ=0; targ<8; targ++) {
        !           322:                if(targ==mytarg)
1.1       root      323:                        continue;
1.1.1.2 ! root      324:                for(lun=0; lun<8; lun++) {
        !           325:                        if( (sw->empty[targ] & (1<<lun)) || (sw->used[targ] & (1<<lun)) )
        !           326:                                continue;
        !           327: 
        !           328:                        *physid = targ*8 + lun;
        !           329:                        match = scsi_probe(masunit, sw, *physid, type, 0);
        !           330:                        if( match==(struct scsidevs *)-1) {
        !           331:                                if(lun==0)
        !           332:                                        sw->empty[targ] = 0xff;
        !           333:                                else
        !           334:                                        sw->empty[targ] |= (1<<lun);
        !           335:                                match = (struct scsidevs *)0;
        !           336:                                continue;
        !           337:                        }
        !           338:                        if(!match)
        !           339:                                break;
        !           340:                        ret = (*(match->attach_rtn))(masunit, sw, *physid, unit);
        !           341:                        if(ret)
        !           342:                                goto success;
        !           343:                        return 0;
        !           344:                }
        !           345:        }
        !           346:        *physid = -1;   /* failed... */
        !           347:        return 0;
        !           348: 
        !           349: success:
        !           350:        targ = *physid >> 3;
        !           351:        lun = *physid & 7;
        !           352:        if(match->flags & SC_MORE_LUS)
        !           353:                sw->used[targ] |= (1<<lun);
        !           354:        else
        !           355:                sw->used[targ] = 0xff;
        !           356:        return ret;
        !           357: }
        !           358: 
        !           359: /*
        !           360:  * Try make as good a match as possible with
        !           361:  * available sub drivers
        !           362:  */
        !           363: struct scsidevs *
        !           364: selectdev(int unit, int target, int lu, struct scsi_switch *sw, int qual,
        !           365:        int dtype, int remov, char *manu, char *model, char *rev, int type)
        !           366: {
        !           367:        struct scsidevs *sdbest = (struct scsidevs *)0;
        !           368:        struct scsidevs *sdent = knowndevs;
        !           369:        int numents = sizeof(knowndevs)/sizeof(struct scsidevs);
        !           370:        int count = 0, sdbestes = 0;
        !           371: 
        !           372:        dtype |= (qual << 5);
        !           373: 
        !           374:        sdent--;
        !           375:        while( count++ < numents) {
        !           376:                sdent++;
        !           377:                if(dtype != sdent->dtype)
1.1       root      378:                        continue;
1.1.1.2 ! root      379:                if(type != sdent->type)
1.1       root      380:                        continue;
1.1.1.2 ! root      381:                if(sdbestes < 1) {
        !           382:                        sdbestes = 1;
        !           383:                        sdbest = sdent;
1.1       root      384:                }
1.1.1.2 ! root      385:                if(remov != sdent->removable)
1.1       root      386:                        continue;
1.1.1.2 ! root      387:                if(sdbestes < 2) {
        !           388:                        sdbestes = 2;
        !           389:                        sdbest = sdent;
        !           390:                }
        !           391:                if(sdent->flags & SC_SHOWME)
        !           392:                        printf("\n%s-\n%s-", sdent->manufacturer, manu);
        !           393:                if(strcmp(sdent->manufacturer, manu))
        !           394:                        continue;
        !           395:                if(sdbestes < 3) {
        !           396:                        sdbestes = 3;
        !           397:                        sdbest = sdent;
        !           398:                }
        !           399:                if(sdent->flags & SC_SHOWME)
        !           400:                        printf("\n%s-\n%s-",sdent->model, model);
        !           401:                if(strcmp(sdent->model, model))
        !           402:                        continue;
        !           403:                if(sdbestes < 4) {
        !           404:                        sdbestes = 4;
        !           405:                        sdbest = sdent;
        !           406:                }
        !           407:                if(sdent->flags & SC_SHOWME)
        !           408:                        printf("\n%s-\n%s-",sdent->version, rev);
        !           409:                if(strcmp(sdent->version, rev))
        !           410:                        continue;
        !           411:                if(sdbestes < 5) {
        !           412:                        sdbestes = 5;
        !           413:                        sdbest = sdent;
1.1       root      414:                        break;
                    415:                }
                    416:        }
1.1.1.2 ! root      417:        return sdbest;
1.1       root      418: }
                    419: 
1.1.1.2 ! root      420: /*
        !           421:  * Do a scsi operation asking a device if it is
        !           422:  * ready. Use the scsi_cmd routine in the switch
        !           423:  * table.
        !           424:  */
        !           425: int
        !           426: scsi_ready(int unit, int target, int lu,
        !           427:        struct scsi_switch *sw, int flags)
1.1       root      428: {
1.1.1.2 ! root      429:        struct scsi_test_unit_ready scsi_cmd;
        !           430:        struct scsi_xfer scsi_xfer;
1.1       root      431:        volatile int rval;
1.1.1.2 ! root      432:        int key;
1.1       root      433: 
                    434:        bzero(&scsi_cmd, sizeof(scsi_cmd));
                    435:        bzero(&scsi_xfer, sizeof(scsi_xfer));
                    436:        scsi_cmd.op_code = TEST_UNIT_READY;
                    437: 
1.1.1.2 ! root      438:        scsi_xfer.flags = flags | INUSE;
        !           439:        scsi_xfer.adapter = unit;
        !           440:        scsi_xfer.targ = target;
        !           441:        scsi_xfer.lu = lu;
        !           442:        scsi_xfer.cmd = (struct scsi_generic *)&scsi_cmd;
        !           443:        scsi_xfer.retries = 8;
        !           444:        scsi_xfer.timeout = 10000;
        !           445:        scsi_xfer.cmdlen = sizeof(scsi_cmd);
        !           446:        scsi_xfer.data = 0;
        !           447:        scsi_xfer.datalen = 0;
        !           448:        scsi_xfer.resid = 0;
        !           449:        scsi_xfer.when_done = 0;
        !           450:        scsi_xfer.done_arg = 0;
        !           451: retry: scsi_xfer.error = 0;
        !           452: 
        !           453:        /* don't use interrupts! */
        !           454: 
        !           455:        rval = (*(sw->scsi_cmd))(&scsi_xfer);
        !           456:        if (rval != COMPLETE) {
        !           457:                if(scsi_debug) {
        !           458:                        printf("scsi error, rval = 0x%x\n", rval);
        !           459:                        printf("code from driver: 0x%x\n", scsi_xfer.error);
        !           460:                }
        !           461:                switch(scsi_xfer.error) {
        !           462:                case XS_SENSE:
        !           463:                        /*
        !           464:                         * Any sense value is illegal except UNIT ATTENTION
        !           465:                         * In which case we need to check again to get the
        !           466:                         * correct response. (especially exabytes)
        !           467:                         */
        !           468:                        if(scsi_xfer.sense.error_class == 7 ) {
1.1       root      469:                                key = scsi_xfer.sense.ext.extended.sense_key ;
1.1.1.2 ! root      470:                                switch(key) { 
        !           471:                                case 2: /* not ready BUT PRESENT! */
        !           472:                                        return(COMPLETE);
        !           473:                                case 6:
1.1       root      474:                                        spinwait(1000);
1.1.1.2 ! root      475:                                        if(scsi_xfer.retries--) {
1.1       root      476:                                                scsi_xfer.flags &= ~ITSDONE;
                    477:                                                goto retry;
                    478:                                        }
                    479:                                        return(COMPLETE);
                    480:                                default:
                    481:                                        if(scsi_debug)
1.1.1.2 ! root      482:                                                printf("%d:%d,key=%x.", target,
        !           483:                                                        lu, key);
1.1       root      484:                                }
                    485:                        }
                    486:                        return(HAD_ERROR);
1.1.1.2 ! root      487:                case XS_BUSY:
1.1       root      488:                        spinwait(1000);
1.1.1.2 ! root      489:                        if(scsi_xfer.retries--) {
1.1       root      490:                                scsi_xfer.flags &= ~ITSDONE;
                    491:                                goto retry;
                    492:                        }
1.1.1.2 ! root      493:                        return COMPLETE;        /* it's busy so it's there */
        !           494:                case XS_TIMEOUT:
1.1       root      495:                default:
1.1.1.2 ! root      496:                        return HAD_ERROR;
1.1       root      497:                }
                    498:        }
1.1.1.2 ! root      499:        return COMPLETE;
1.1       root      500: }
1.1.1.2 ! root      501: 
        !           502: /*
        !           503:  * Do a scsi operation asking a device what it is
        !           504:  * Use the scsi_cmd routine in the switch table.
        !           505:  */
        !           506: int
        !           507: scsi_inquire(int unit, int target, int lu, struct scsi_switch *sw,
        !           508:        u_char *inqbuf, int flags)
1.1       root      509: {
1.1.1.2 ! root      510:        struct scsi_inquiry scsi_cmd;
        !           511:        struct scsi_xfer scsi_xfer;
1.1       root      512: 
                    513:        bzero(&scsi_cmd, sizeof(scsi_cmd));
                    514:        bzero(&scsi_xfer, sizeof(scsi_xfer));
                    515:        scsi_cmd.op_code = INQUIRY;
                    516:        scsi_cmd.length = sizeof(struct scsi_inquiry_data);
                    517: 
1.1.1.2 ! root      518:        scsi_xfer.flags = flags | SCSI_DATA_IN | INUSE;
        !           519:        scsi_xfer.adapter = unit;
        !           520:        scsi_xfer.targ = target;
        !           521:        scsi_xfer.lu = lu;
        !           522:        scsi_xfer.retries = 8;
        !           523:        scsi_xfer.timeout = 10000;
        !           524:        scsi_xfer.cmd = (struct scsi_generic *)&scsi_cmd;
        !           525:        scsi_xfer.cmdlen =  sizeof(struct scsi_inquiry);
        !           526:        scsi_xfer.data = inqbuf;
        !           527:        scsi_xfer.datalen = sizeof(struct scsi_inquiry_data);
        !           528:        scsi_xfer.resid = sizeof(struct scsi_inquiry_data);
        !           529:        scsi_xfer.when_done = 0;
        !           530:        scsi_xfer.done_arg = 0;
        !           531: 
        !           532: retry:
        !           533:        scsi_xfer.error=0;
        !           534:        /* don't use interrupts! */
        !           535: 
        !           536:        if ((*(sw->scsi_cmd))(&scsi_xfer) != COMPLETE) {
        !           537:                if(scsi_debug)
        !           538:                        printf("inquiry had error(0x%x) ",scsi_xfer.error);
        !           539:                switch(scsi_xfer.error) {
        !           540:                case XS_NOERROR:
        !           541:                        break;
        !           542:                case XS_SENSE:
        !           543:                        /*
        !           544:                         * Any sense value is illegal except UNIT ATTENTION
        !           545:                         * In which case we need to check again to get the
        !           546:                         * correct response. (especially exabytes)
        !           547:                         */
        !           548:                        if( scsi_xfer.sense.error_class==7 &&
        !           549:                            scsi_xfer.sense.ext.extended.sense_key==6) {
        !           550:                                /* it's changed so it's there */
1.1       root      551:                                spinwait(1000);
1.1.1.2 ! root      552:                                if(scsi_xfer.retries--) {
        !           553:                                        scsi_xfer.flags &= ~ITSDONE;
        !           554:                                        goto retry;
1.1       root      555:                                }
1.1.1.2 ! root      556:                                return COMPLETE;
1.1       root      557:                        }
1.1.1.2 ! root      558:                        return HAD_ERROR;
        !           559:                case XS_BUSY:
1.1       root      560:                        spinwait(1000);
1.1.1.2 ! root      561:                        if(scsi_xfer.retries--) {
1.1       root      562:                                scsi_xfer.flags &= ~ITSDONE;
                    563:                                goto retry;
                    564:                        }
1.1.1.2 ! root      565:                case XS_TIMEOUT:
1.1       root      566:                default:
                    567:                        return(HAD_ERROR);
                    568:                }
                    569:        }
1.1.1.2 ! root      570:        return COMPLETE;
1.1       root      571: }
                    572: 
1.1.1.2 ! root      573: /*
        !           574:  * convert a physical address to 3 bytes,
        !           575:  * MSB at the lowest address,
        !           576:  * LSB at the highest.
        !           577:  */
        !           578: void
        !           579: lto3b(u_long val, u_char *bytes)
1.1       root      580: {
                    581:        *bytes++ = (val&0xff0000)>>16;
                    582:        *bytes++ = (val&0xff00)>>8;
                    583:        *bytes = val&0xff;
                    584: }
                    585: 
1.1.1.2 ! root      586: /*
        !           587:  * The reverse of lto3b
        !           588:  */
        !           589: u_long
        !           590: _3btol(u_char *bytes)
1.1       root      591: {
1.1.1.2 ! root      592:        u_long rc;
        !           593: 
1.1       root      594:        rc = (*bytes++ << 16);
                    595:        rc += (*bytes++ << 8);
                    596:        rc += *bytes;
1.1.1.2 ! root      597:        return rc;
1.1       root      598: }
                    599: 

unix.superglobalmegacorp.com

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