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

1.1     ! root        1: /*
        !             2:  * Written by Julian Elischer ([email protected])
        !             3:  * for TRW Financial Systems for use under the MACH(2.5) operating system.
        !             4:  *
        !             5:  * TRW Financial Systems, in accordance with their agreement with Carnegie
        !             6:  * Mellon University, makes this software available to CMU to distribute
        !             7:  * or use in any manner that they see fit as long as this message is kept with
        !             8:  * the software. For this reason TFS also grants any other persons or
        !             9:  * organisations permission to use or modify this software.
        !            10:  *
        !            11:  * TFS supplies this software to be publicly redistributed
        !            12:  * on the understanding that TFS is not responsible for the correct
        !            13:  * functioning of this software in any circumstances.
        !            14:  *
        !            15:  *
        !            16:  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
        !            17:  * --------------------         -----   ----------------------
        !            18:  * CURRENT PATCH LEVEL:         1       00098
        !            19:  * --------------------         -----   ----------------------
        !            20:  *
        !            21:  * 16 Feb 93   Julian Elischer         ADDED for SCSI system
        !            22:  */
        !            23: 
        !            24: /*
        !            25:  * Ported to run under 386BSD by Julian Elischer ([email protected]) Sept 1992
        !            26:  */
        !            27: 
        !            28: /*
        !            29: $Log:
        !            30: *
        !            31: */
        !            32: #include <sys/types.h>
        !            33: #include "st.h"
        !            34: #include "sd.h"
        !            35: #include "ch.h"
        !            36: #include "cd.h"
        !            37: 
        !            38: #ifdef MACH
        !            39: #include <i386/machparam.h>
        !            40: #endif MACH
        !            41: #include <scsi/scsi_all.h>
        !            42: #include <scsi/scsiconf.h>
        !            43: 
        !            44: #if !defined(OSF) && !defined(__386BSD__)
        !            45: #include "bll.h"
        !            46: #include "cals.h"
        !            47: #include "kil.h"
        !            48: #else
        !            49: #define        NBLL 0
        !            50: #define        NCALS 0
        !            51: #define        NKIL 0
        !            52: #endif /* !defined(OSF) && !defined(__386BSD__) */
        !            53: 
        !            54: #if NSD > 0
        !            55: extern sdattach();
        !            56: #endif NSD
        !            57: #if NST > 0
        !            58: extern stattach();
        !            59: #endif NST
        !            60: #if NCH > 0
        !            61: extern chattach();
        !            62: #endif NCH
        !            63: #if NCD > 0
        !            64: extern cdattach();
        !            65: #endif NCD
        !            66: #if NBLL > 0
        !            67: extern bllattach();
        !            68: #endif NBLL
        !            69: #if NCALS > 0
        !            70: extern calsattach();
        !            71: #endif NCALS
        !            72: #if NKIL > 0
        !            73: extern kil_attach();
        !            74: #endif NKIL
        !            75: 
        !            76: /***************************************************************\
        !            77: * The structure of pre-configured devices that might be turned *
        !            78: * off and therefore may not show up                            *
        !            79: \***************************************************************/
        !            80: struct predefined
        !            81: {
        !            82:        u_char  scsibus;
        !            83:        u_char  dev;
        !            84:        u_char  lu;
        !            85:        int     (*attach_rtn)();
        !            86:        char    *devname;
        !            87:        char    flags;
        !            88: }
        !            89: pd[] = 
        !            90: {
        !            91: #ifdef EXAMPLE_PREDEFINE
        !            92: #if NSD > 0
        !            93:        {0,0,0,sdattach,"sd",0},/* define a disk at scsibus=0 dev=0 lu=0 */
        !            94: #endif NSD
        !            95: #endif EXAMPLE_PREDEFINE
        !            96:        {0,9,9}                 /*illegal dummy end entry */
        !            97: };
        !            98: 
        !            99: 
        !           100: /***************************************************************\
        !           101: * The structure of known drivers for autoconfiguration         *
        !           102: \***************************************************************/
        !           103: static struct scsidevs 
        !           104: {
        !           105:        int type;
        !           106:        int removable;
        !           107:        char    *manufacturer;
        !           108:        char    *model;
        !           109:        char    *version;
        !           110:        int     (*attach_rtn)();
        !           111:        char    *devname;
        !           112:        char    flags;          /* 1 show my comparisons during boot(debug) */
        !           113: }
        !           114: #define SC_SHOWME      0x01
        !           115: #define        SC_ONE_LU       0x00
        !           116: #define        SC_MORE_LUS     0x02
        !           117: knowndevs[] = {
        !           118: #if NSD > 0
        !           119:        { T_DIRECT,T_FIXED,"standard","any"
        !           120:                        ,"any",sdattach,"sd",SC_ONE_LU },
        !           121:        { T_DIRECT,T_FIXED,"MAXTOR  ","XT-4170S        "
        !           122:                        ,"B5A ",sdattach,"mx1",SC_ONE_LU },
        !           123: #endif NSD
        !           124: #if NST > 0
        !           125:        { T_SEQUENTIAL,T_REMOV,"standard","any"
        !           126:                        ,"any",stattach,"st",SC_ONE_LU },
        !           127: #endif NST
        !           128: #if NCALS > 0
        !           129:        { T_PROCESSOR,T_FIXED,"standard","any"
        !           130:                        ,"any",calsattach,"cals",SC_MORE_LUS },
        !           131: #endif NCALS
        !           132: #if NCH > 0
        !           133:        { T_CHANGER,T_REMOV,"standard","any"
        !           134:                        ,"any",chattach,"ch",SC_ONE_LU },
        !           135: #endif NCH
        !           136: #if NCD > 0
        !           137:        { T_READONLY,T_REMOV,"SONY    ","CD-ROM CDU-8012 "
        !           138:                        ,"3.1a",cdattach,"cd",SC_ONE_LU },
        !           139: #endif NCD
        !           140: #if NBLL > 0
        !           141:        { T_PROCESSOR,T_FIXED,"AEG     ","READER          "
        !           142:                        ,"V1.0",bllattach,"bll",SC_MORE_LUS },
        !           143: #endif NBLL
        !           144: #if NKIL > 0
        !           145:        { T_SCANNER,T_FIXED,"KODAK   ","IL Scanner 900  "
        !           146:                        ,"any",kil_attach,"kil",SC_ONE_LU },
        !           147: #endif NKIL
        !           148: 
        !           149: {0}
        !           150: };
        !           151: /***************************************************************\
        !           152: * Declarations                                                 *
        !           153: \***************************************************************/
        !           154: struct predefined      *scsi_get_predef();
        !           155: struct scsidevs        *scsi_probedev();
        !           156: struct scsidevs        *selectdev();
        !           157: 
        !           158: /* controls debug level within the scsi subsystem */
        !           159: /* see scsiconf.h for values                     */
        !           160: int    scsi_debug      =       0x0;
        !           161: int    scsibus         =       0x0; /* This is the Nth scsibus */
        !           162: 
        !           163: /***************************************************************\
        !           164: * The routine called by the adapter boards to get all their    *
        !           165: * devices configured in.                                       *
        !           166: \***************************************************************/
        !           167: scsi_attachdevs( unit, scsi_addr, scsi_switch)
        !           168: int    unit,scsi_addr;
        !           169: struct scsi_switch     *scsi_switch;
        !           170: {
        !           171:        int     targ,lun;
        !           172:        struct  scsidevs        *bestmatch = (struct scsidevs *)0;
        !           173:        struct  predefined *predef;
        !           174:        int maybe_more;
        !           175: 
        !           176: #ifdef SCSI_DELAY
        !           177: #if    SCSI_DELAY > 2
        !           178:        printf("waiting for scsi devices to settle\n");
        !           179: #else  SCSI_DELAY > 2
        !           180: #define        SCSI_DELAY 15
        !           181: #endif SCSI_DELAY > 2
        !           182: #else
        !           183: #define SCSI_DELAY 2
        !           184: #endif SCSI_DELAY
        !           185:        spinwait(1000 * SCSI_DELAY);
        !           186:        targ = 0;
        !           187:        while(targ < 8)
        !           188:        {
        !           189:                maybe_more = 0; /* by default only check 1 lun */
        !           190:                if (targ == scsi_addr) 
        !           191:                {
        !           192:                        targ++;
        !           193:                        continue;
        !           194:                }
        !           195:                lun = 0;
        !           196:                while(lun < 8)
        !           197:                {
        !           198:                        predef = scsi_get_predef(scsibus
        !           199:                                                ,targ
        !           200:                                                ,lun
        !           201:                                                ,&maybe_more);
        !           202:                        bestmatch = scsi_probedev(unit
        !           203:                                                ,targ
        !           204:                                                ,lun 
        !           205:                                                ,scsi_switch
        !           206:                                                ,&maybe_more);
        !           207:                        if((bestmatch) && (predef)) /* both exist */
        !           208:                        {
        !           209:                                if(bestmatch->attach_rtn 
        !           210:                                    != predef->attach_rtn)
        !           211:                                {
        !           212:                                    printf("Clash in found/expected devices\n");
        !           213:                                    printf("will link in FOUND\n");
        !           214:                                }
        !           215:                                (*(bestmatch->attach_rtn))(unit,
        !           216:                                                targ,
        !           217:                                                lun,
        !           218:                                                scsi_switch);
        !           219:                        }
        !           220:                        if((bestmatch) && (!predef)) /* just FOUND */
        !           221:                        {
        !           222:                                (*(bestmatch->attach_rtn))(unit,
        !           223:                                                targ,
        !           224:                                                lun,
        !           225:                                                scsi_switch);
        !           226:                        }
        !           227:                        if((!bestmatch) && (predef)) /* just predef */
        !           228:                        {
        !           229:                                (*(predef->attach_rtn))(unit,
        !           230:                                                targ,
        !           231:                                                lun,
        !           232:                                                scsi_switch);
        !           233:                        }
        !           234:                        if(!(maybe_more)) /* nothing suggests we'll find more */
        !           235:                        {
        !           236:                                break;  /* nothing here, skip to next targ */
        !           237:                        }
        !           238:                        /* otherwise something says we should look further*/
        !           239:                        lun++;
        !           240:                }
        !           241:                targ++;
        !           242:        }
        !           243: #if NGENSCSI > 0
        !           244:        /***************************************************************\
        !           245:        * If available hook up the generic scsi driver, letting it      *
        !           246:        * know which target is US. (i.e. illegal or at least special)   *
        !           247:        \***************************************************************/
        !           248:        genscsi_attach(unit,scsi_addr,0,scsi_switch);
        !           249: #endif
        !           250:        scsibus++;      /* next time we are on the NEXT scsi bus */
        !           251: }
        !           252: 
        !           253: /***********************************************\
        !           254: * given a target and lu, check if there is a   *
        !           255: * predefined device for that address           *
        !           256: \***********************************************/
        !           257: struct predefined      *scsi_get_predef(unit,target,lu,maybe_more)
        !           258: int    unit,target,lu,*maybe_more;
        !           259: {
        !           260:        int upto,numents;
        !           261: 
        !           262:        numents = (sizeof(pd)/sizeof(struct predefined)) - 1;
        !           263:        
        !           264:        for(upto = 0;upto < numents;upto++)
        !           265:        {
        !           266:                if(pd[upto].scsibus != unit)
        !           267:                        continue;
        !           268:                if(pd[upto].dev != target)
        !           269:                        continue;
        !           270:                if(pd[upto].lu != lu)
        !           271:                        continue;
        !           272:                
        !           273:                printf("  dev%d,lu%d: %s - PRECONFIGURED -\n"
        !           274:                        ,target
        !           275:                        ,lu
        !           276:                        ,pd[upto].devname);
        !           277:                *maybe_more = pd[upto].flags & SC_MORE_LUS;
        !           278:                return(&(pd[upto]));
        !           279:        }
        !           280:        return((struct predefined *)0);
        !           281: }
        !           282: 
        !           283: /***********************************************\
        !           284: * given a target and lu, ask the device what   *
        !           285: * it is, and find the correct driver table     *
        !           286: * entry.                                       *
        !           287: \***********************************************/
        !           288: struct scsidevs        *scsi_probedev(unit,target,lu,scsi_switch, maybe_more)
        !           289: 
        !           290: struct scsi_switch *scsi_switch;
        !           291: int    unit,target,lu;
        !           292: int *maybe_more;
        !           293: {
        !           294:        struct  scsidevs        *bestmatch = (struct scsidevs *)0;
        !           295:        char    *dtype=(char *)0,*desc;
        !           296:        char    *qtype;
        !           297:        static  struct scsi_inquiry_data        inqbuf; 
        !           298:        int     len,qualifier,type,remov;
        !           299:        char    manu[32];
        !           300:        char    model[32];
        !           301:        char    version[32];
        !           302: 
        !           303: 
        !           304:        bzero(&inqbuf,sizeof(inqbuf));
        !           305:        /***********************************************\
        !           306:        * Ask the device what it is                     *
        !           307:        \***********************************************/
        !           308: #ifdef DEBUG
        !           309:        if((target == 0) && (lu == 0))
        !           310:                scsi_debug = 0xfff;
        !           311:        else
        !           312:                scsi_debug = 0;
        !           313: #endif DEBUG
        !           314:        if(scsi_ready(  unit,
        !           315:                        target,
        !           316:                        lu,
        !           317:                        scsi_switch,
        !           318:                        SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
        !           319:        {
        !           320:                return(struct scsidevs *)0;
        !           321:        }
        !           322:        if(scsi_inquire(unit,
        !           323:                        target,
        !           324:                        lu,
        !           325:                        scsi_switch,
        !           326:                        &inqbuf,
        !           327:                        SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
        !           328:        {
        !           329:                return(struct scsidevs *)0;
        !           330:        }
        !           331: 
        !           332:        /***********************************************\
        !           333:        * note what BASIC type of device it is          *
        !           334:        \***********************************************/
        !           335:        if(scsi_debug & SHOWINQUIRY)
        !           336:        {
        !           337:                desc=(char *)&inqbuf;
        !           338:                printf("inq: %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
        !           339:                desc[0], desc[1], desc[2], desc[3],
        !           340:                desc[4], desc[5], desc[6], desc[7],
        !           341:                desc[8], desc[9], desc[10], desc[11],
        !           342:                desc[12]);
        !           343:        }
        !           344: 
        !           345:        type = inqbuf.device_type;
        !           346:        qualifier = inqbuf.device_qualifier;
        !           347:        remov = inqbuf.removable;
        !           348: 
        !           349:        /* Check for a non-existent unit.  If the device is returning
        !           350:         * this much, then we must set the flag that has
        !           351:         * the searcher keep looking on other luns.
        !           352:         */
        !           353:        if (qualifier == 3 && type == T_NODEVICE)
        !           354:        {
        !           355:                *maybe_more = 1;
        !           356:                return (struct scsidevs *)0;
        !           357:        }
        !           358: 
        !           359:        /* Any device qualifier that has
        !           360:         * the top bit set (qualifier&4 != 0) is vendor specific and
        !           361:         * won't match in this switch.
        !           362:         */
        !           363: 
        !           364:        switch(qualifier)
        !           365:        {
        !           366:                case 0:
        !           367:                qtype="";
        !           368:                break;
        !           369:                case 1:
        !           370:                qtype=", Unit not Connected!";
        !           371:                break;
        !           372:                case 2:
        !           373:                qtype=", Reserved Peripheral Qualifier!";
        !           374:                break;
        !           375:                case 3:
        !           376:                qtype=", The Target can't support this Unit!";
        !           377:                break;
        !           378: 
        !           379:                default:
        !           380:                dtype="vendor specific";
        !           381:                qtype="";
        !           382:                *maybe_more = 1;
        !           383:                break;
        !           384:        }
        !           385: 
        !           386:        if (dtype == 0)
        !           387:                switch(type)
        !           388:                {
        !           389:                        case T_DIRECT:
        !           390:                                dtype="direct";
        !           391:                                break;
        !           392:                        case T_SEQUENTIAL:
        !           393:                                dtype="sequential";
        !           394:                                break;
        !           395:                        case T_PRINTER:
        !           396:                                dtype="printer";
        !           397:                                break;
        !           398:                        case T_PROCESSOR:
        !           399:                                dtype="processor";
        !           400:                                break;
        !           401:                        case T_READONLY:
        !           402:                                dtype="readonly";
        !           403:                                break;
        !           404:                        case T_WORM:
        !           405:                                dtype="worm";
        !           406:                                break;
        !           407:                        case T_SCANNER:
        !           408:                                dtype="scanner";
        !           409:                                break;
        !           410:                        case T_OPTICAL:
        !           411:                                dtype="optical";
        !           412:                                break;
        !           413:                        case T_CHANGER:
        !           414:                                dtype="changer";
        !           415:                                break;
        !           416:                        case T_COMM:
        !           417:                                dtype="communication";
        !           418:                                break;
        !           419:                        default:
        !           420:                                dtype="unknown";
        !           421:                                break;
        !           422:                }
        !           423: 
        !           424:        /***********************************************\
        !           425:        * Then if it's advanced enough, more detailed   *
        !           426:        * information                                   *
        !           427:        \***********************************************/
        !           428:        if(inqbuf.ansii_version > 0) 
        !           429:        {
        !           430:                if ((len = inqbuf.additional_length 
        !           431:                                + ( (char *)inqbuf.unused
        !           432:                                  - (char *)&inqbuf))
        !           433:                        > (sizeof(struct scsi_inquiry_data) - 1))
        !           434:                        len = sizeof(struct scsi_inquiry_data) - 1;
        !           435:                desc=inqbuf.vendor;
        !           436:                desc[len-(desc - (char *)&inqbuf)] = 0;
        !           437:                strncpy(manu,inqbuf.vendor,8);manu[8]=0;
        !           438:                strncpy(model,inqbuf.product,16);model[16]=0;
        !           439:                strncpy(version,inqbuf.revision,4);version[4]=0;
        !           440:        }
        !           441:        else
        !           442:        /***********************************************\
        !           443:        * If not advanced enough, use default values    *
        !           444:        \***********************************************/
        !           445:        {
        !           446:                desc="early protocol device";
        !           447:                strncpy(manu,"unknown",8);
        !           448:                strncpy(model,"unknown",16);
        !           449:                strncpy(version,"????",4);
        !           450:        }
        !           451:        printf("  dev%d,lu%d: type %d:%d(%s%s),%s '%s%s%s' scsi%d\n"
        !           452:                ,target
        !           453:                ,lu
        !           454:                ,qualifier,type
        !           455:                ,dtype,qtype
        !           456:                ,remov?"removable":"fixed"
        !           457:                ,manu
        !           458:                ,model
        !           459:                ,version
        !           460:                ,inqbuf.ansii_version
        !           461:        );
        !           462:        /***********************************************\
        !           463:        * Try make as good a match as possible with     *
        !           464:        * available sub drivers                         *
        !           465:        \***********************************************/
        !           466:        bestmatch = (selectdev(unit,target,lu,&scsi_switch,
        !           467:                qualifier,type,remov,manu,model,version));
        !           468:        if((bestmatch) && (bestmatch->flags & SC_MORE_LUS))
        !           469:        {
        !           470:                *maybe_more = 1;
        !           471:        }
        !           472:        return(bestmatch);
        !           473: }
        !           474: 
        !           475: /***********************************************\
        !           476: * Try make as good a match as possible with    *
        !           477: * available sub drivers                                *
        !           478: \***********************************************/
        !           479: struct scsidevs        
        !           480: *selectdev(unit,target,lu,dvr_switch,qualifier,type,remov,manu,model,rev)
        !           481: int    unit,target,lu;
        !           482: struct scsi_switch *dvr_switch;
        !           483: int    qualifier,type,remov;
        !           484: char   *manu,*model,*rev;
        !           485: {
        !           486:        int     numents = (sizeof(knowndevs)/sizeof(struct scsidevs)) - 1;
        !           487:        int     count = 0;
        !           488:        int                     bestmatches = 0;
        !           489:        struct  scsidevs        *bestmatch = (struct scsidevs *)0;
        !           490:        struct  scsidevs        *thisentry = knowndevs;
        !           491: 
        !           492:        type |= (qualifier << 5);
        !           493: 
        !           494:        thisentry--;
        !           495:        while( count++ < numents)
        !           496:        {
        !           497:                thisentry++;
        !           498:                if(type != thisentry->type)
        !           499:                {
        !           500:                        continue;
        !           501:                }
        !           502:                if(bestmatches < 1)
        !           503:                {
        !           504:                        bestmatches = 1;
        !           505:                        bestmatch = thisentry;
        !           506:                }
        !           507:                if(remov != thisentry->removable)
        !           508:                {
        !           509:                        continue;
        !           510:                }
        !           511:                if(bestmatches < 2)
        !           512:                {
        !           513:                        bestmatches = 2;
        !           514:                        bestmatch = thisentry;
        !           515:                }
        !           516:                if(thisentry->flags & SC_SHOWME)
        !           517:                        printf("\n%s-\n%s-",thisentry->manufacturer, manu);
        !           518:                if(strcmp(thisentry->manufacturer, manu))
        !           519:                {
        !           520:                        continue;
        !           521:                }
        !           522:                if(bestmatches < 3)
        !           523:                {
        !           524:                        bestmatches = 3;
        !           525:                        bestmatch = thisentry;
        !           526:                }
        !           527:                if(thisentry->flags & SC_SHOWME)
        !           528:                        printf("\n%s-\n%s-",thisentry->model, model);
        !           529:                if(strcmp(thisentry->model, model))
        !           530:                {
        !           531:                        continue;
        !           532:                }
        !           533:                if(bestmatches < 4)
        !           534:                {
        !           535:                        bestmatches = 4;
        !           536:                        bestmatch = thisentry;
        !           537:                }
        !           538:                if(thisentry->flags & SC_SHOWME)
        !           539:                        printf("\n%s-\n%s-",thisentry->version, rev);
        !           540:                if(strcmp(thisentry->version, rev))
        !           541:                {
        !           542:                        continue;
        !           543:                }
        !           544:                if(bestmatches < 5)
        !           545:                {
        !           546:                        bestmatches = 5;
        !           547:                        bestmatch = thisentry;
        !           548:                        break;
        !           549:                }
        !           550:        }
        !           551: 
        !           552:        if (bestmatch == (struct scsidevs *)0)
        !           553:                printf("        No explicit device driver match for \"%s %s\".\n",
        !           554:                manu, model);
        !           555: 
        !           556:        return(bestmatch);
        !           557: }
        !           558: 
        !           559: static int recurse = 0;
        !           560: /***********************************************\
        !           561: * Do a scsi operation asking a device if it is *
        !           562: * ready. Use the scsi_cmd routine in the switch *
        !           563: * table.                                       *
        !           564: \***********************************************/
        !           565: scsi_ready(unit,target,lu,scsi_switch, flags)
        !           566: struct scsi_switch *scsi_switch;
        !           567: {
        !           568:        struct  scsi_test_unit_ready scsi_cmd;
        !           569:        struct  scsi_xfer scsi_xfer;
        !           570:        volatile int rval;
        !           571:        int     key;
        !           572: 
        !           573:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !           574:        bzero(&scsi_xfer, sizeof(scsi_xfer));
        !           575:        scsi_cmd.op_code = TEST_UNIT_READY;
        !           576: 
        !           577:        scsi_xfer.flags=flags | INUSE;
        !           578:        scsi_xfer.adapter=unit;
        !           579:        scsi_xfer.targ=target;
        !           580:        scsi_xfer.lu=lu;
        !           581:        scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd;
        !           582:        scsi_xfer.retries=8;
        !           583:        scsi_xfer.timeout=10000;
        !           584:        scsi_xfer.cmdlen=sizeof(scsi_cmd);
        !           585:        scsi_xfer.data=0;
        !           586:        scsi_xfer.datalen=0;
        !           587:        scsi_xfer.resid=0;
        !           588:        scsi_xfer.when_done=0;
        !           589:        scsi_xfer.done_arg=0;
        !           590: retry: scsi_xfer.error=0;
        !           591:        /*******************************************************\
        !           592:        * do not use interrupts                                 *
        !           593:        \*******************************************************/
        !           594:        rval = (*(scsi_switch->scsi_cmd))(&scsi_xfer);
        !           595:        if (rval != COMPLETE)
        !           596:        {
        !           597:                if(scsi_debug)
        !           598:                {
        !           599:                        printf("scsi error, rval = 0x%x\n",rval);
        !           600:                        printf("code from driver: 0x%x\n",scsi_xfer.error);
        !           601:                }
        !           602:                switch(scsi_xfer.error)
        !           603:                {
        !           604:                case    XS_SENSE:
        !           605:                /*******************************************************\
        !           606:                * Any sense value is illegal except UNIT ATTENTION      *
        !           607:                * In which case we need to check again to get the       *
        !           608:                * correct response.                                     *
        !           609:                *( especially exabytes)                                 *
        !           610:                \*******************************************************/
        !           611:                        if(scsi_xfer.sense.error_class == 7 )
        !           612:                        {
        !           613:                                key = scsi_xfer.sense.ext.extended.sense_key ;
        !           614:                                switch(key)
        !           615:                                { 
        !           616:                                case    2:      /* not ready BUT PRESENT! */
        !           617:                                                return(COMPLETE);
        !           618:                                case    6:
        !           619:                                        spinwait(1000);
        !           620:                                        if(scsi_xfer.retries--)
        !           621:                                        {
        !           622:                                                scsi_xfer.flags &= ~ITSDONE;
        !           623:                                                goto retry;
        !           624:                                        }
        !           625:                                        return(COMPLETE);
        !           626:                                default:
        !           627:                                        if(scsi_debug)
        !           628:                                                printf("%d:%d,key=%x.",
        !           629:                                                target,lu,key);
        !           630:                                }
        !           631:                        }
        !           632:                        return(HAD_ERROR);
        !           633:                case    XS_BUSY:
        !           634:                        spinwait(1000);
        !           635:                        if(scsi_xfer.retries--)
        !           636:                        {
        !           637:                                scsi_xfer.flags &= ~ITSDONE;
        !           638:                                goto retry;
        !           639:                        }
        !           640:                        return(COMPLETE);       /* it's busy so it's there */
        !           641:                case    XS_TIMEOUT:
        !           642:                default:
        !           643:                        return(HAD_ERROR);
        !           644:                }
        !           645:        }
        !           646:        return(COMPLETE);
        !           647: }
        !           648: /***********************************************\
        !           649: * Do a scsi operation asking a device what it is*
        !           650: * Use the scsi_cmd routine in the switch table.        *
        !           651: \***********************************************/
        !           652: scsi_inquire(unit,target,lu,scsi_switch,inqbuf, flags)
        !           653: struct scsi_switch *scsi_switch;
        !           654: u_char *inqbuf;
        !           655: {
        !           656:        struct  scsi_inquiry scsi_cmd;
        !           657:        struct  scsi_xfer scsi_xfer;
        !           658:        volatile int rval;
        !           659: 
        !           660:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !           661:        bzero(&scsi_xfer, sizeof(scsi_xfer));
        !           662:        scsi_cmd.op_code = INQUIRY;
        !           663:        scsi_cmd.length = sizeof(struct scsi_inquiry_data);
        !           664: 
        !           665:        scsi_xfer.flags=flags | SCSI_DATA_IN | INUSE;
        !           666:        scsi_xfer.adapter=unit;
        !           667:        scsi_xfer.targ=target;
        !           668:        scsi_xfer.lu=lu;
        !           669:        scsi_xfer.retries=8;
        !           670:        scsi_xfer.timeout=10000;
        !           671:        scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd;
        !           672:        scsi_xfer.cmdlen= sizeof(struct scsi_inquiry);
        !           673:        scsi_xfer.data=inqbuf;
        !           674:        scsi_xfer.datalen=sizeof(struct scsi_inquiry_data);
        !           675:        scsi_xfer.resid=sizeof(struct scsi_inquiry_data);
        !           676:        scsi_xfer.when_done=0;
        !           677:        scsi_xfer.done_arg=0;
        !           678: retry: scsi_xfer.error=0;
        !           679:        /*******************************************************\
        !           680:        * do not use interrupts                                 *
        !           681:        \*******************************************************/
        !           682:        if ((*(scsi_switch->scsi_cmd))(&scsi_xfer) != COMPLETE)
        !           683:        {
        !           684:                if(scsi_debug) printf("inquiry had error(0x%x) ",scsi_xfer.error);
        !           685:                switch(scsi_xfer.error)
        !           686:                {
        !           687:                case    XS_NOERROR:
        !           688:                        break;
        !           689:                case    XS_SENSE:
        !           690:                /*******************************************************\
        !           691:                * Any sense value is illegal except UNIT ATTENTION      *
        !           692:                * In which case we need to check again to get the       *
        !           693:                * correct response.                                     *
        !           694:                *( especially exabytes)                                 *
        !           695:                \*******************************************************/
        !           696:                        if((scsi_xfer.sense.error_class == 7 )
        !           697:                         && (scsi_xfer.sense.ext.extended.sense_key == 6))
        !           698:                        { /* it's changed so it's there */
        !           699:                                spinwait(1000);
        !           700:                                {
        !           701:                                        if(scsi_xfer.retries--)
        !           702:                                        {
        !           703:                                                scsi_xfer.flags &= ~ITSDONE;
        !           704:                                                goto retry;
        !           705:                                        }
        !           706:                                }
        !           707:                                return( COMPLETE);
        !           708:                        }
        !           709:                        return(HAD_ERROR);
        !           710:                case    XS_BUSY:
        !           711:                        spinwait(1000);
        !           712:                        if(scsi_xfer.retries--)
        !           713:                        {
        !           714:                                scsi_xfer.flags &= ~ITSDONE;
        !           715:                                goto retry;
        !           716:                        }
        !           717:                case    XS_TIMEOUT:
        !           718:                default:
        !           719:                        return(HAD_ERROR);
        !           720:                }
        !           721:        }
        !           722:        return(COMPLETE);
        !           723: }
        !           724: 
        !           725: 
        !           726: 
        !           727: 
        !           728: /***********************************************\
        !           729: * Utility routines often used in SCSI stuff    *
        !           730: \***********************************************/
        !           731: 
        !           732: /***********************************************\
        !           733: * convert a physical address to 3 bytes,       *
        !           734: * MSB at the lowest address,                   *
        !           735: * LSB at the highest.                          *
        !           736: \***********************************************/
        !           737: 
        !           738: lto3b(val, bytes)
        !           739: u_char *bytes;
        !           740: {
        !           741:        *bytes++ = (val&0xff0000)>>16;
        !           742:        *bytes++ = (val&0xff00)>>8;
        !           743:        *bytes = val&0xff;
        !           744: }
        !           745: 
        !           746: /***********************************************\
        !           747: * The reverse of lto3b                         *
        !           748: \***********************************************/
        !           749: _3btol(bytes)
        !           750: u_char *bytes;
        !           751: {
        !           752:        int rc;
        !           753:        rc = (*bytes++ << 16);
        !           754:        rc += (*bytes++ << 8);
        !           755:        rc += *bytes;
        !           756:        return(rc);
        !           757: }
        !           758: 

unix.superglobalmegacorp.com

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