Annotation of Net2/scsi/ch.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  */
                      3: /*
                      4:  * HISTORY
                      5:  * 
                      6:  *
                      7:  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
                      8:  * --------------------         -----   ----------------------
                      9:  * CURRENT PATCH LEVEL:         1       00098
                     10:  * --------------------         -----   ----------------------
                     11:  *
                     12:  * 16 Feb 93   Julian Elischer         ADDED for SCSI system
                     13:  * 
                     14:  */
                     15: 
                     16: #include       <sys/types.h>
                     17: #include       <ch.h>
                     18: 
                     19: #include <sys/param.h>
                     20: #include <sys/systm.h>
                     21: 
                     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/chio.h>
                     28: 
                     29: #if defined(OSF)
                     30: #define SECSIZE        512
                     31: #endif /* defined(OSF) */
                     32: 
                     33: #include <scsi/scsi_all.h>
                     34: #include <scsi/scsi_changer.h>
                     35: #include <scsi/scsiconf.h>
                     36: 
                     37: 
                     38: struct  scsi_xfer ch_scsi_xfer[NCH];
                     39: int     ch_xfer_block_wait[NCH];
                     40: 
                     41: 
                     42: #define PAGESIZ        4096
                     43: #define STQSIZE                4
                     44: #define        CH_RETRIES      4
                     45: 
                     46: 
                     47: #define MODE(z)                (  (minor(z) & 0x0F) )
                     48: #define UNIT(z)                (  (minor(z) >> 4) )
                     49: 
                     50: #ifndef        MACH
                     51: #define ESUCCESS 0
                     52: #endif MACH
                     53: 
                     54: int    ch_info_valid[NCH];     /* the info about the device is valid */
                     55: int    ch_initialized[NCH] ;
                     56: int    ch_debug = 1;
                     57: 
                     58: int chattach();
                     59: int ch_done();
                     60: struct ch_data
                     61: {
                     62:        int     flags;
                     63:        struct  scsi_switch *sc_sw;     /* address of scsi low level switch */
                     64:        int     ctlr;                   /* so they know which one we want */
                     65:        int     targ;                   /* our scsi target ID */
                     66:        int     lu;                     /* out scsi lu */
                     67:        short   chmo;                   /* Offset of first CHM */
                     68:        short   chms;                   /* No. of CHM */
                     69:        short   slots;                  /* No. of Storage Elements */
                     70:        short   sloto;                  /* Offset of first SE */
                     71:        short   imexs;                  /* No. of Import/Export Slots */
                     72:        short   imexo;                  /* Offset of first IM/EX */
                     73:        short   drives;                 /* No. of CTS */
                     74:        short   driveo;                 /* Offset of first CTS */
                     75:        short   rot;                    /* CHM can rotate */
                     76:        u_long  op_matrix;              /* possible opertaions */
                     77:        u_short lsterr;         /* details of lasterror */
                     78:        u_char  stor;                   /* posible Storage locations */
                     79: }ch_data[NCH];
                     80: 
                     81: #define CH_OPEN                0x01
                     82: #define CH_KNOWN       0x02
                     83: 
                     84: static int     next_ch_unit = 0;
                     85: /***********************************************************************\
                     86: * The routine called by the low level scsi routine when it discovers   *
                     87: * A device suitable for this driver                                    *
                     88: \***********************************************************************/
                     89: 
                     90: int    chattach(ctlr,targ,lu,scsi_switch)
                     91: struct scsi_switch *scsi_switch;
                     92: {
                     93:        int     unit,i,stat;
                     94:        unsigned char *tbl;
                     95: 
                     96:        if(scsi_debug & PRINTROUTINES) printf("chattach: ");
                     97:        /*******************************************************\
                     98:        * Check we have the resources for another drive         *
                     99:        \*******************************************************/
                    100:        unit = next_ch_unit++;
                    101:        if( unit >= NCH)
                    102:        {
                    103:                printf("Too many scsi changers..(%d > %d) reconfigure kernel",(unit + 1),NCH);
                    104:                return(0);
                    105:        }
                    106:        /*******************************************************\
                    107:        * Store information needed to contact our base driver   *
                    108:        \*******************************************************/
                    109:        ch_data[unit].sc_sw     =       scsi_switch;
                    110:        ch_data[unit].ctlr      =       ctlr;
                    111:        ch_data[unit].targ      =       targ;
                    112:        ch_data[unit].lu        =       lu;
                    113: 
                    114:        /*******************************************************\
                    115:        * Use the subdriver to request information regarding    *
                    116:        * the drive. We cannot use interrupts yet, so the       *
                    117:        * request must specify this.                            *
                    118:        \*******************************************************/
                    119:        if((ch_mode_sense(unit,  SCSI_NOSLEEP |  SCSI_NOMASK /*| SCSI_SILENT*/)))
                    120:        {
                    121:                printf("        ch%d: scsi changer, %d slot(s) %d drive(s) %d arm(s) %d i/e-slot(s) \n",
                    122:                        unit, ch_data[unit].slots, ch_data[unit].drives, ch_data[unit].chms, ch_data[unit].imexs);
                    123:                stat=CH_KNOWN;
                    124:        }
                    125:        else
                    126:        {
                    127:                printf("        ch%d: scsi changer :- offline\n", unit);
                    128:                stat=CH_OPEN;
                    129:        }
                    130:        ch_initialized[unit] = stat;
                    131: 
                    132:        return;
                    133: 
                    134: }
                    135: 
                    136: 
                    137: 
                    138: /*******************************************************\
                    139: *      open the device.                                *
                    140: \*******************************************************/
                    141: chopen(dev)
                    142: {
                    143:        int errcode = 0;
                    144:        int unit,mode;
                    145: 
                    146:        unit = UNIT(dev);
                    147:        mode = MODE(dev);
                    148: 
                    149:        /*******************************************************\
                    150:        * Check the unit is legal                               *
                    151:        \*******************************************************/
                    152:        if ( unit >= NCH )
                    153:        {
                    154:                printf("ch %d  > %d\n",unit,NCH);
                    155:                errcode = ENXIO;
                    156:                return(errcode);
                    157:        }
                    158:        /*******************************************************\
                    159:        * Only allow one at a time                              *
                    160:        \*******************************************************/
                    161:        if(ch_data[unit].flags & CH_OPEN)
                    162:        {
                    163:                printf("CH%d already open\n",unit);
                    164:                errcode = ENXIO;
                    165:                goto bad;
                    166:        }
                    167:        
                    168:        if(ch_debug||(scsi_debug & (PRINTROUTINES | TRACEOPENS)))
                    169:                printf("chopen: dev=0x%x (unit %d (of %d))\n"
                    170:                                ,   dev,      unit,   NCH);
                    171:        /*******************************************************\
                    172:        * Make sure the device has been initialised             *
                    173:        \*******************************************************/
                    174: 
                    175:        if (!ch_initialized[unit])
                    176:                return(ENXIO);
                    177:        if (ch_initialized[unit]!=CH_KNOWN) {
                    178:                if((ch_mode_sense(unit,  SCSI_NOSLEEP |  SCSI_NOMASK /*| SCSI_SILENT*/)))
                    179:                {
                    180:                        ch_initialized[unit]=CH_KNOWN;
                    181:                }
                    182:          else
                    183:                {
                    184:                        printf("  ch%d: scsi changer :- offline\n", unit);
                    185:                        return(ENXIO);
                    186:                }
                    187:        }
                    188:        /*******************************************************\
                    189:        * Check that it is still responding and ok.             *
                    190:        \*******************************************************/
                    191: 
                    192:        if(ch_debug || (scsi_debug & TRACEOPENS))
                    193:                printf("device is ");
                    194:        if (!(ch_req_sense(unit, 0)))
                    195:        {
                    196:                errcode = ENXIO;
                    197:                if(ch_debug || (scsi_debug & TRACEOPENS))
                    198:                        printf("not responding\n");
                    199:                goto bad;
                    200:        }
                    201:        if(ch_debug || (scsi_debug & TRACEOPENS))
                    202:                printf("ok\n");
                    203: 
                    204:        if(!(ch_test_ready(unit,0)))
                    205:        {
                    206:                printf("ch%d not ready\n",unit);
                    207:                return(EIO);
                    208:        }
                    209: 
                    210:        ch_info_valid[unit] = TRUE;
                    211: 
                    212:        /*******************************************************\
                    213:        * Load the physical device parameters                   *
                    214:        \*******************************************************/
                    215: 
                    216:        ch_data[unit].flags = CH_OPEN;
                    217:        return(errcode);
                    218: bad:
                    219:        return(errcode);
                    220: }
                    221: 
                    222: /*******************************************************\
                    223: * close the device.. only called if we are the LAST    *
                    224: * occurence of an open device                          *
                    225: \*******************************************************/
                    226: chclose(dev)
                    227: {
                    228:        unsigned char unit,mode;
                    229: 
                    230:        unit = UNIT(dev);
                    231:        mode = MODE(dev);
                    232: 
                    233:        if(scsi_debug & TRACEOPENS)
                    234:                printf("Closing device");
                    235:        ch_data[unit].flags = 0;
                    236:        return(0);
                    237: }
                    238: 
                    239: 
                    240: 
                    241: /***************************************************************\
                    242: * chstart                                                       *
                    243: * This routine is also called after other non-queued requests  *
                    244: * have been made of the scsi driver, to ensure that the queue  *
                    245: * continues to be drained.                                     *
                    246: \***************************************************************/
                    247: /* chstart() is called at splbio */
                    248: chstart(unit)
                    249: {
                    250:        int                     drivecount;
                    251:        register struct buf     *bp = 0;
                    252:        register struct buf     *dp;
                    253:        struct  scsi_xfer       *xs;
                    254:        int                     blkno, nblk;
                    255: 
                    256: 
                    257:        if(scsi_debug & PRINTROUTINES) printf("chstart%d ",unit);
                    258:        /*******************************************************\
                    259:        * See if there is a buf to do and we are not already    *
                    260:        * doing one                                             *
                    261:        \*******************************************************/
                    262:        xs=&ch_scsi_xfer[unit];
                    263:        if(xs->flags & INUSE)
                    264:        {
                    265:                return;    /* unit already underway */
                    266:        }
                    267:        if(ch_xfer_block_wait[unit]) /* a special awaits, let it proceed first */
                    268:        {
                    269:                wakeup(&ch_xfer_block_wait[unit]);
                    270:                return;
                    271:        }
                    272: 
                    273:        return;
                    274: 
                    275: }
                    276: 
                    277: 
                    278: /*******************************************************\
                    279: * This routine is called by the scsi interrupt when    *
                    280: * the transfer is complete.
                    281: \*******************************************************/
                    282: int    ch_done(unit,xs)
                    283: int    unit;
                    284: struct scsi_xfer       *xs;
                    285: {
                    286:        struct  buf             *bp;
                    287:        int     retval;
                    288: 
                    289:        if(ch_debug||(scsi_debug & PRINTROUTINES)) printf("ch_done%d ",unit);
                    290:        if (! (xs->flags & INUSE))
                    291:                panic("scsi_xfer not in use!");
                    292:        wakeup(xs);
                    293: }
                    294: /*******************************************************\
                    295: * Perform special action on behalf of the user         *
                    296: * Knows about the internals of this device             *
                    297: \*******************************************************/
                    298: chioctl(dev, cmd, arg, mode)
                    299: dev_t dev;
                    300: int cmd;
                    301: caddr_t arg;
                    302: {
                    303:        /* struct ch_cmd_buf *args;*/
                    304:        union scsi_cmd *scsi_cmd;
                    305:        register i,j;
                    306:        unsigned int opri;
                    307:        int errcode = 0;
                    308:        unsigned char unit;
                    309:        int number,flags,ret;
                    310: 
                    311:        /*******************************************************\
                    312:        * Find the device that the user is talking about        *
                    313:        \*******************************************************/
                    314:        flags = 0;      /* give error messages, act on errors etc. */
                    315:        unit = UNIT(dev);
                    316: 
                    317:        switch(cmd)
                    318:        {
                    319:                case CHIOOP: {
                    320:                        struct chop *ch=(struct chop *) arg;
                    321:                        if (ch_debug)
                    322:                                printf("[chtape_chop: %x]\n", ch->ch_op);
                    323: 
                    324:                         switch ((short)(ch->ch_op)) {
                    325:                                case CHGETPARAM:
                    326:                                        ch->u.getparam.chmo=     ch_data[unit].chmo;
                    327:                                        ch->u.getparam.chms=   ch_data[unit].chms;
                    328:                                        ch->u.getparam.sloto=  ch_data[unit].sloto;
                    329:                                        ch->u.getparam.slots=  ch_data[unit].slots;
                    330:                                        ch->u.getparam.imexo=  ch_data[unit].imexo;
                    331:                                        ch->u.getparam.imexs=  ch_data[unit].imexs;
                    332:                                        ch->u.getparam.driveo= ch_data[unit].driveo;
                    333:                                        ch->u.getparam.drives= ch_data[unit].drives;
                    334:                                        ch->u.getparam.rot=    ch_data[unit].rot;
                    335:                                        ch->result=0;
                    336:                                        return 0;
                    337:                                        break;
                    338:                                case CHPOSITION: 
                    339:                                 return ch_position(unit,&ch->result,ch->u.position.chm,
                    340:                                                ch->u.position.to,
                    341:                                                flags);
                    342:                                case CHMOVE: 
                    343:                                 return ch_move(unit,&ch->result, ch->u.position.chm,
                    344:                                        ch->u.move.from, ch->u.move.to,
                    345:                                                                flags);
                    346:                                case CHGETELEM:
                    347:                                 return ch_getelem(unit,&ch->result, ch->u.get_elem_stat.type,
                    348:                                        ch->u.get_elem_stat.from, &ch->u.get_elem_stat.elem_data,
                    349:                                                                        flags);
                    350:                                default:
                    351:                                 return EINVAL;
                    352:                }
                    353: 
                    354:         }
                    355:        default:
                    356:                return EINVAL;
                    357:        }
                    358: 
                    359:        return(ret?ESUCCESS:EIO);
                    360: }
                    361: 
                    362: ch_getelem(unit,stat,type,from,data,flags)
                    363: int unit,from,flags;
                    364: short *stat;
                    365: char *data;
                    366: {
                    367:        struct scsi_read_element_status scsi_cmd;
                    368:        char elbuf[32];
                    369:        int ret;
                    370: 
                    371:        bzero(&scsi_cmd, sizeof(scsi_cmd));
                    372:        scsi_cmd.op_code = READ_ELEMENT_STATUS;
                    373:        scsi_cmd.element_type_code=type;
                    374:        scsi_cmd.starting_element_addr[0]=(from>>8)&0xff;
                    375:        scsi_cmd.starting_element_addr[1]=from&0xff;
                    376:        scsi_cmd.number_of_elements[1]=1;
                    377:        scsi_cmd.allocation_length[2]=32;
                    378:        
                    379:        if ((ret=ch_scsi_cmd(unit,
                    380:                        &scsi_cmd,
                    381:                        sizeof(scsi_cmd),
                    382:                        elbuf,
                    383:                        32,
                    384:                        100000,
                    385:                        flags) !=ESUCCESS)) {
                    386:                        *stat=ch_data[unit].lsterr;
                    387:                        bcopy(elbuf+16,data,16);
                    388:                        return ret;
                    389:                        }
                    390:        bcopy(elbuf+16,data,16); /*Just a hack sh */
                    391:        return ret;
                    392: }
                    393: 
                    394: ch_move(unit,stat,chm,from,to,flags)
                    395: int unit,chm,from,to,flags;
                    396: short *stat;
                    397: {
                    398:        struct scsi_move_medium scsi_cmd;
                    399:        int ret;
                    400: 
                    401:        bzero(&scsi_cmd, sizeof(scsi_cmd));
                    402:        scsi_cmd.op_code = MOVE_MEDIUM;
                    403:        scsi_cmd.transport_element_address[0]=(chm>>8)&0xff;
                    404:        scsi_cmd.transport_element_address[1]=chm&0xff;
                    405:        scsi_cmd.source_address[0]=(from>>8)&0xff;
                    406:        scsi_cmd.source_address[1]=from&0xff;
                    407:        scsi_cmd.destination_address[0]=(to>>8)&0xff;
                    408:        scsi_cmd.destination_address[1]=to&0xff;
                    409:        scsi_cmd.invert=(chm&CH_INVERT)?1:0;
                    410:        if ((ret=ch_scsi_cmd(unit,
                    411:                        &scsi_cmd,
                    412:                        sizeof(scsi_cmd),
                    413:                        NULL,
                    414:                        0,
                    415:                        100000,
                    416:                        flags) !=ESUCCESS)) {
                    417:                        *stat=ch_data[unit].lsterr;
                    418:                        return ret;
                    419:                        }
                    420:        return ret;
                    421: }
                    422: 
                    423: ch_position(unit,stat,chm,to,flags)
                    424: int unit,chm,to,flags;
                    425: short *stat;
                    426: {
                    427:        struct scsi_position_to_element scsi_cmd;
                    428:        int ret;
                    429: 
                    430:        bzero(&scsi_cmd, sizeof(scsi_cmd));
                    431:        scsi_cmd.op_code = POSITION_TO_ELEMENT;
                    432:        scsi_cmd.transport_element_address[0]=(chm>>8)&0xff;
                    433:        scsi_cmd.transport_element_address[1]=chm&0xff;
                    434:        scsi_cmd.source_address[0]=(to>>8)&0xff;
                    435:        scsi_cmd.source_address[1]=to&0xff;
                    436:        scsi_cmd.invert=(chm&CH_INVERT)?1:0;
                    437:        if ((ret=ch_scsi_cmd(unit,
                    438:                        &scsi_cmd,
                    439:                        sizeof(scsi_cmd),
                    440:                        NULL,
                    441:                        0,
                    442:                        100000,
                    443:                        flags) !=ESUCCESS)) {
                    444:                        *stat=ch_data[unit].lsterr;
                    445:                        return ret;
                    446:                        }
                    447:        return ret;
                    448: }
                    449: 
                    450: /*******************************************************\
                    451: * Check with the device that it is ok, (via scsi driver)*
                    452: \*******************************************************/
                    453: ch_req_sense(unit, flags)
                    454: int    flags;
                    455: {
                    456:        struct  scsi_sense_data sense;
                    457:        struct scsi_sense scsi_cmd;
                    458: 
                    459:        bzero(&scsi_cmd, sizeof(scsi_cmd));
                    460:        scsi_cmd.op_code = REQUEST_SENSE;
                    461:        scsi_cmd.length = sizeof(sense);
                    462: 
                    463:        if (ch_scsi_cmd(unit,
                    464:                        &scsi_cmd,
                    465:                        sizeof(struct   scsi_sense),
                    466:                        &sense,
                    467:                        sizeof(sense),
                    468:                        100000,
                    469:                        flags | SCSI_DATA_IN) != 0)
                    470:        {
                    471:                return(FALSE);
                    472:        }
                    473:        else 
                    474:                return(TRUE);
                    475: }
                    476: 
                    477: /*******************************************************\
                    478: * Get scsi driver to send a "are you ready" command    *
                    479: \*******************************************************/
                    480: ch_test_ready(unit,flags)
                    481: int    unit,flags;
                    482: {
                    483:        struct scsi_test_unit_ready scsi_cmd;
                    484: 
                    485:        bzero(&scsi_cmd, sizeof(scsi_cmd));
                    486:        scsi_cmd.op_code = TEST_UNIT_READY;
                    487: 
                    488:        if (ch_scsi_cmd(unit,
                    489:                        &scsi_cmd,
                    490:                        sizeof(struct   scsi_test_unit_ready),
                    491:                        0,
                    492:                        0,
                    493:                        100000,
                    494:                        flags) != 0) {
                    495:                return(FALSE);
                    496:        } else 
                    497:                return(TRUE);
                    498: }
                    499: 
                    500: 
                    501: #ifdef __STDC__
                    502: #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
                    503: #else
                    504: #define b2tol(a)       (((unsigned)(a/**/_1) << 8) + (unsigned)a/**/_0 )
                    505: #endif
                    506: 
                    507: /*******************************************************\
                    508: * Get the scsi driver to send a full inquiry to the    *
                    509: * device and use the results to fill out the global    *
                    510: * parameter structure.                                 *
                    511: \*******************************************************/
                    512: ch_mode_sense(unit, flags)
                    513: int    unit,flags;
                    514: {
                    515:        struct scsi_mode_sense scsi_cmd;
                    516:        u_char scsi_sense[128]; /* Can't use scsi_mode_sense_data because of */
                    517:                                /* missing block descriptor                  */
                    518:        u_char *b;
                    519:        int i,l;
                    520: 
                    521:        /*******************************************************\
                    522:        * First check if we have it all loaded                  *
                    523:        \*******************************************************/
                    524:        if (ch_info_valid[unit]==CH_KNOWN) return(TRUE);
                    525:        /*******************************************************\
                    526:        * First do a mode sense                                 *
                    527:        \*******************************************************/
                    528:        ch_info_valid[unit] &= ~CH_KNOWN;
                    529:        for(l=1;l>=0;l--) {
                    530:                bzero(&scsi_cmd, sizeof(scsi_cmd));
                    531:                scsi_cmd.op_code = MODE_SENSE;
                    532:                scsi_cmd.dbd = l;
                    533:                scsi_cmd.page_code = 0x3f;      /* All Pages */
                    534:                scsi_cmd.length = sizeof(scsi_sense);
                    535:        /*******************************************************\
                    536:        * do the command, but we don't need the results         *
                    537:        * just print them for our interest's sake               *
                    538:        \*******************************************************/
                    539:                if (ch_scsi_cmd(unit,
                    540:                        &scsi_cmd,
                    541:                        sizeof(struct   scsi_mode_sense),
                    542:                        &scsi_sense,
                    543:                        sizeof(scsi_sense),
                    544:                        5000,
                    545:                        flags | SCSI_DATA_IN) == 0) {
                    546:                                ch_info_valid[unit] = CH_KNOWN;
                    547:                                break;
                    548:                        }
                    549:        }
                    550:        if (ch_info_valid[unit]!=CH_KNOWN)   {
                    551:                if(!(flags & SCSI_SILENT))
                    552:                        printf("could not mode sense for unit %d\n", unit);
                    553:                return(FALSE);
                    554:        }
                    555:        l=scsi_sense[0]-3;
                    556:        b=&scsi_sense[4];
                    557:        /*****************************\
                    558:        * To avoid alignment problems *
                    559:        \*****************************/
                    560: /*FIX THIS FOR MSB */
                    561: #define p2copy(valp)    (valp[1]+ (valp[0]<<8));valp+=2
                    562: #define p4copy(valp)    (valp[3]+ (valp[2]<<8) + (valp[1]<<16) + (valp[0]<<24));valp+=4
                    563: #if 0
                    564:        printf("\nmode_sense %d\n",l);
                    565:        for(i=0;i<l+4;i++) {
                    566:                printf("%x%c",scsi_sense[i],i%8==7?'\n':':');
                    567:        }
                    568:        printf("\n");
                    569: #endif
                    570:        for(i=0;i<l;) {
                    571:                int pc=(*b++)&0x3f;
                    572:                int pl=*b++;
                    573:                u_char *bb=b;
                    574:                switch(pc) {
                    575:                        case 0x1d:
                    576:                                ch_data[unit].chmo  =p2copy(bb);
                    577:                                ch_data[unit].chms  =p2copy(bb);
                    578:                                ch_data[unit].sloto =p2copy(bb);
                    579:                                ch_data[unit].slots =p2copy(bb);
                    580:                                ch_data[unit].imexo =p2copy(bb);
                    581:                                ch_data[unit].imexs =p2copy(bb);
                    582:                                ch_data[unit].driveo =p2copy(bb);
                    583:                                ch_data[unit].drives =p2copy(bb);
                    584:                                break;
                    585:                        case 0x1e:
                    586:                                ch_data[unit].rot = (*b)&1;
                    587:                                break;
                    588:                        case 0x1f:
                    589:                                ch_data[unit].stor = *b&0xf;
                    590:                                bb+=2;
                    591:                                ch_data[unit].stor =p4copy(bb);
                    592:                                break;
                    593:                        default:
                    594:                                break;
                    595:                }
                    596:                b+=pl;
                    597:                i+=pl+2;
                    598:        }
                    599:        if (ch_debug)
                    600:        {
                    601:                printf("unit %d: cht(%d-%d)slot(%d-%d)imex(%d-%d)cts(%d-%d) %s rotate\n",
                    602:                                unit,
                    603:                                ch_data[unit].chmo,
                    604:                                ch_data[unit].chms,
                    605:                                ch_data[unit].sloto,
                    606:                                ch_data[unit].slots,
                    607:                                ch_data[unit].imexo,
                    608:                                ch_data[unit].imexs,
                    609:                                ch_data[unit].driveo,
                    610:                                ch_data[unit].drives,
                    611:                                ch_data[unit].rot?"can":"can't");
                    612:        }
                    613:        return(TRUE);
                    614: }
                    615: 
                    616: /*******************************************************\
                    617: * ask the scsi driver to perform a command for us.     *
                    618: * Call it through the switch table, and tell it which  *
                    619: * sub-unit we want, and what target and lu we wish to  *
                    620: * talk to. Also tell it where to find the command      *
                    621: * how long int is.                                     *
                    622: * Also tell it where to read/write the data, and how   *
                    623: * long the data is supposed to be                      *
                    624: \*******************************************************/
                    625: int    ch_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags)
                    626: 
                    627: int    unit,flags;
                    628: struct scsi_generic *scsi_cmd;
                    629: int    cmdlen;
                    630: int    timeout;
                    631: u_char *data_addr;
                    632: int    datalen;
                    633: {
                    634:        struct  scsi_xfer *xs;
                    635:        int     retval;
                    636:        int     s;
                    637: 
                    638:        if(ch_debug||(scsi_debug & PRINTROUTINES)) printf("\nch_scsi_cmd%d %x",
                    639:                                unit,scsi_cmd->opcode);
                    640:        if(ch_data[unit].sc_sw) /* If we have a scsi driver */
                    641:        {
                    642: 
                    643:                xs = &(ch_scsi_xfer[unit]);
                    644:                if(!(flags & SCSI_NOMASK))
                    645:                        s = splbio();
                    646:                ch_xfer_block_wait[unit]++;     /* there is someone waiting */
                    647:                while (xs->flags & INUSE)
                    648:                {
                    649:                        sleep(&ch_xfer_block_wait[unit],PRIBIO+1);
                    650:                }
                    651:                ch_xfer_block_wait[unit]--;
                    652:                xs->flags = INUSE;
                    653:                if(!(flags & SCSI_NOMASK))
                    654:                        splx(s);
                    655: 
                    656:                /*******************************************************\
                    657:                * Fill out the scsi_xfer structure                      *
                    658:                \*******************************************************/
                    659:                xs->flags       |=      flags;
                    660:                xs->adapter     =       ch_data[unit].ctlr;
                    661:                xs->targ        =       ch_data[unit].targ;
                    662:                xs->lu          =       ch_data[unit].lu;
                    663:                xs->retries     =       CH_RETRIES;
                    664:                xs->timeout     =       timeout;
                    665:                xs->cmd         =       scsi_cmd;
                    666:                xs->cmdlen      =       cmdlen;
                    667:                xs->data        =       data_addr;
                    668:                xs->datalen     =       datalen;
                    669:                xs->resid       =       datalen;
                    670:                xs->when_done   =       (flags & SCSI_NOMASK)
                    671:                                        ?(int (*)())0
                    672:                                        :ch_done;
                    673:                xs->done_arg    =       unit;
                    674:                xs->done_arg2   =       (int)xs;
                    675: retry:         xs->error       =       XS_NOERROR;
                    676:                xs->bp          =       0;
                    677:                ch_data[unit].lsterr=0;
                    678:                retval = (*(ch_data[unit].sc_sw->scsi_cmd))(xs);
                    679:                switch(retval)
                    680:                {
                    681:                case    SUCCESSFULLY_QUEUED:
                    682:                        while(!(xs->flags & ITSDONE))
                    683:                                sleep(xs,PRIBIO+1);
                    684: 
                    685:                case    HAD_ERROR:
                    686:                case    COMPLETE:
                    687:                        switch(xs->error)
                    688:                        {
                    689:                        case    XS_NOERROR:
                    690:                                retval = ESUCCESS;
                    691:                                break;
                    692:                        case    XS_SENSE:
                    693:                                retval = (ch_interpret_sense(unit,xs));
                    694:                                break;
                    695:                        case    XS_DRIVER_STUFFUP:
                    696:                                retval = EIO;
                    697:                                break;
                    698:                        case    XS_TIMEOUT:
                    699:                                if(xs->retries-- )
                    700:                                {
                    701:                                        xs->flags &= ~ITSDONE;
                    702:                                        goto retry;
                    703:                                }
                    704:                                retval = EIO;
                    705:                                break;
                    706:                        case    XS_BUSY:
                    707:                                if(xs->retries-- )
                    708:                                {
                    709:                                        xs->flags &= ~ITSDONE;
                    710:                                        goto retry;
                    711:                                }
                    712:                                retval = EIO;
                    713:                                break;
                    714:                        default:
                    715:                                retval = EIO;
                    716:                                printf("st%d: unknown error category from scsi driver\n"
                    717:                                        ,unit);
                    718:                                break;
                    719:                        }       
                    720:                        break;
                    721:                case    TRY_AGAIN_LATER:
                    722:                        if(xs->retries-- )
                    723:                        {
                    724:                                xs->flags &= ~ITSDONE;
                    725:                                goto retry;
                    726:                        }
                    727:                        retval = EIO;
                    728:                        break;
                    729:                default:
                    730:                        retval = EIO;
                    731:                }
                    732:                xs->flags = 0;  /* it's free! */
                    733:                chstart(unit);
                    734:        }
                    735:        else
                    736:        {
                    737:                printf("chd: not set up\n",unit);
                    738:                return(EINVAL);
                    739:        }
                    740:        return(retval);
                    741: }
                    742: /***************************************************************\
                    743: * Look at the returned sense and act on the error and detirmine        *
                    744: * The unix error number to pass back... (0 = report no error)  *
                    745: \***************************************************************/
                    746: 
                    747: int    ch_interpret_sense(unit,xs)
                    748: int    unit;
                    749: struct scsi_xfer       *xs;
                    750: {
                    751:        struct  scsi_sense_data *sense;
                    752:        int     key;
                    753:        int     silent = xs->flags & SCSI_SILENT;
                    754: 
                    755:        /***************************************************************\
                    756:        * If errors are ok, report a success                            *
                    757:        \***************************************************************/
                    758:        if(xs->flags & SCSI_ERR_OK) return(ESUCCESS);
                    759: 
                    760:        /***************************************************************\
                    761:        * Get the sense fields and work out what CLASS                  *
                    762:        \***************************************************************/
                    763:        sense = &(xs->sense);
                    764:        switch(sense->error_class)
                    765:        {
                    766:        /***************************************************************\
                    767:        * If it's class 7, use the extended stuff and interpret the key *
                    768:        \***************************************************************/
                    769:        case 7:
                    770:                {
                    771:                key=sense->ext.extended.sense_key;
                    772:                if(sense->ext.extended.ili)
                    773:                        if(!silent)
                    774:                        {
                    775:                                printf("length error ");
                    776:                        }
                    777:                        if(sense->valid)
                    778:                                xs->resid = ntohl(*((long *)sense->ext.extended.info));
                    779:                                if(xs->bp)
                    780:                                {
                    781:                                        xs->bp->b_flags |= B_ERROR;
                    782:                                        return(ESUCCESS);
                    783:                                }
                    784:                if(sense->ext.extended.eom)
                    785:                        if(!silent) printf("end of medium ");
                    786:                if(sense->ext.extended.filemark)
                    787:                        if(!silent) printf("filemark ");
                    788:                if(ch_debug)
                    789:                {
                    790:                        printf("code%x class%x valid%x\n"
                    791:                                        ,sense->error_code
                    792:                                        ,sense->error_class
                    793:                                        ,sense->valid);
                    794:                        printf("seg%x key%x ili%x eom%x fmark%x\n"
                    795:                                        ,sense->ext.extended.segment
                    796:                                        ,sense->ext.extended.sense_key
                    797:                                        ,sense->ext.extended.ili
                    798:                                        ,sense->ext.extended.eom
                    799:                                        ,sense->ext.extended.filemark);
                    800:                        printf("info: %x %x %x %x followed by %d extra bytes\n"
                    801:                                        ,sense->ext.extended.info[0]
                    802:                                        ,sense->ext.extended.info[1]
                    803:                                        ,sense->ext.extended.info[2]
                    804:                                        ,sense->ext.extended.info[3]
                    805:                                        ,sense->ext.extended.extra_len);
                    806:                        printf("extra: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n"
                    807:                                        ,sense->ext.extended.extra_bytes[0]
                    808:                                        ,sense->ext.extended.extra_bytes[1]
                    809:                                        ,sense->ext.extended.extra_bytes[2]
                    810:                                        ,sense->ext.extended.extra_bytes[3]
                    811:                                        ,sense->ext.extended.extra_bytes[4]
                    812:                                        ,sense->ext.extended.extra_bytes[5]
                    813:                                        ,sense->ext.extended.extra_bytes[6]
                    814:                                        ,sense->ext.extended.extra_bytes[7]
                    815:                                        ,sense->ext.extended.extra_bytes[8]
                    816:                                        ,sense->ext.extended.extra_bytes[9]
                    817:                                        ,sense->ext.extended.extra_bytes[10]
                    818:                                        ,sense->ext.extended.extra_bytes[11]
                    819:                                        ,sense->ext.extended.extra_bytes[12]
                    820:                                        ,sense->ext.extended.extra_bytes[13]
                    821:                                        ,sense->ext.extended.extra_bytes[14]
                    822:                                        ,sense->ext.extended.extra_bytes[15]);
                    823:                                    
                    824:                }
                    825:                switch(key)
                    826:                {
                    827:                case    0x0:
                    828:                        return(ESUCCESS);
                    829:                case    0x1:
                    830:                        if(!silent)
                    831:                        {
                    832:                                printf("st%d: soft error(corrected) ", unit); 
                    833:                                if(sense->valid)
                    834:                                {
                    835:                                        printf("block no. %d (decimal)\n",
                    836:                                        (sense->ext.extended.info[0] <<24)|
                    837:                                        (sense->ext.extended.info[1] <<16)|
                    838:                                        (sense->ext.extended.info[2] <<8)|
                    839:                                        (sense->ext.extended.info[3] ));
                    840:                                }
                    841:                                else
                    842:                                {
                    843:                                        printf("\n");
                    844:                                }
                    845:                        }
                    846:                        return(ESUCCESS);
                    847:                case    0x2:
                    848:                        if(!silent) printf("st%d: not ready\n ", unit); 
                    849:                        ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
                    850:                                                                sense->ext.extended.info[13] ;
                    851:                        return(ENODEV);
                    852:                case    0x3:
                    853:                        if(!silent)
                    854:                        {
                    855:                                printf("st%d: medium error ", unit); 
                    856:                                if(sense->valid)
                    857:                                {
                    858:                                        printf("block no. %d (decimal)\n",
                    859:                                        (sense->ext.extended.info[0] <<24)|
                    860:                                        (sense->ext.extended.info[1] <<16)|
                    861:                                        (sense->ext.extended.info[2] <<8)|
                    862:                                        (sense->ext.extended.info[3] ));
                    863:                                }
                    864:                                else
                    865:                                {
                    866:                                        printf("\n");
                    867:                                }
                    868:                        }
                    869:                        return(EIO);
                    870:                case    0x4:
                    871:                        if(!silent) printf("st%d: non-media hardware failure\n ",
                    872:                                unit); 
                    873:                        ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
                    874:                                                                sense->ext.extended.info[13] ;
                    875:                        return(EIO);
                    876:                case    0x5:
                    877:                        if(!silent) printf("st%d: illegal request\n ", unit); 
                    878:                        ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
                    879:                                                                sense->ext.extended.info[13] ;
                    880:                        return(EINVAL);
                    881:                case    0x6:
                    882:                        if(!silent) printf("st%d: Unit attention.\n ", unit); 
                    883:                        ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
                    884:                                                                sense->ext.extended.info[13] ;
                    885:                        ch_info_valid[unit] = FALSE;
                    886:                        if (ch_data[unit].flags & CH_OPEN) /* TEMP!!!! */
                    887:                                return(EIO);
                    888:                        else
                    889:                                return(ESUCCESS);
                    890:                case    0x7:
                    891:                        if(!silent)
                    892:                        {
                    893:                                printf("st%d: attempted protection violation "
                    894:                                                                , unit); 
                    895:                                if(sense->valid)
                    896:                                {
                    897:                                        printf("block no. %d (decimal)\n",
                    898:                                        (sense->ext.extended.info[0] <<24)|
                    899:                                        (sense->ext.extended.info[1] <<16)|
                    900:                                        (sense->ext.extended.info[2] <<8)|
                    901:                                        (sense->ext.extended.info[3] ));
                    902:                                }
                    903:                                else
                    904:                                {
                    905:                                        printf("\n");
                    906:                                }
                    907:                        }
                    908:                        return(EACCES);
                    909:                case    0x8:
                    910:                        if(!silent)
                    911:                        {
                    912:                                printf("st%d: block wrong state (worm)\n "
                    913:                                                        , unit); 
                    914:                                if(sense->valid)
                    915:                                {
                    916:                                        printf("block no. %d (decimal)\n",
                    917:                                        (sense->ext.extended.info[0] <<24)|
                    918:                                        (sense->ext.extended.info[1] <<16)|
                    919:                                        (sense->ext.extended.info[2] <<8)|
                    920:                                        (sense->ext.extended.info[3] ));
                    921:                                }
                    922:                                else
                    923:                                {
                    924:                                        printf("\n");
                    925:                                }
                    926:                        }
                    927:                        return(EIO);
                    928:                case    0x9:
                    929:                        if(!silent) printf("st%d: vendor unique\n",
                    930:                                unit); 
                    931:                        return(EIO);
                    932:                case    0xa:
                    933:                        if(!silent) printf("st%d: copy aborted\n ",
                    934:                                unit); 
                    935:                        return(EIO);
                    936:                case    0xb:
                    937:                        if(!silent) printf("st%d: command aborted\n ",
                    938:                                unit); 
                    939:                        ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
                    940:                                                                sense->ext.extended.info[13] ;
                    941:                        return(EIO);
                    942:                case    0xc:
                    943:                        if(!silent)
                    944:                        {
                    945:                                printf("st%d: search returned\n ", unit); 
                    946:                                if(sense->valid)
                    947:                                {
                    948:                                        printf("block no. %d (decimal)\n",
                    949:                                        (sense->ext.extended.info[0] <<24)|
                    950:                                        (sense->ext.extended.info[1] <<16)|
                    951:                                        (sense->ext.extended.info[2] <<8)|
                    952:                                        (sense->ext.extended.info[3] ));
                    953:                                }
                    954:                                else
                    955:                                {
                    956:                                        printf("\n");
                    957:                                }
                    958:                        }
                    959:                        return(ESUCCESS);
                    960:                case    0xd:
                    961:                        if(!silent) printf("st%d: volume overflow\n ",
                    962:                                unit); 
                    963:                        return(ENOSPC);
                    964:                case    0xe:
                    965:                        if(!silent)
                    966:                        {
                    967:                                printf("st%d: verify miscompare\n ", unit); 
                    968:                                if(sense->valid)
                    969:                                {
                    970:                                        printf("block no. %d (decimal)\n",
                    971:                                        (sense->ext.extended.info[0] <<24)|
                    972:                                        (sense->ext.extended.info[1] <<16)|
                    973:                                        (sense->ext.extended.info[2] <<8)|
                    974:                                        (sense->ext.extended.info[3] ));
                    975:                                }
                    976:                                else
                    977:                                {
                    978:                                        printf("\n");
                    979:                                }
                    980:                        }
                    981:                        return(EIO);
                    982:                case    0xf:
                    983:                        if(!silent) printf("st%d: unknown error key\n ",
                    984:                                unit); 
                    985:                        return(EIO);
                    986:                }
                    987:                break;
                    988:        }
                    989:        /***************************************************************\
                    990:        * If it's NOT class 7, just report it.                          *
                    991:        \***************************************************************/
                    992:        case 0:
                    993:        case 1:
                    994:        case 2:
                    995:        case 3:
                    996:        case 4:
                    997:        case 5:
                    998:        case 6:
                    999:                {
                   1000:                        if(!silent) printf("st%d: error class %d code %d\n",
                   1001:                                unit,
                   1002:                                sense->error_class,
                   1003:                                sense->error_code);
                   1004:                if(sense->valid)
                   1005:                        if(!silent) printf("block no. %d (decimal)\n",
                   1006:                        (sense->ext.unextended.blockhi <<16),
                   1007:                        + (sense->ext.unextended.blockmed <<8),
                   1008:                        + (sense->ext.unextended.blocklow ));
                   1009:                }
                   1010:                return(EIO);
                   1011:        }
                   1012: }
                   1013: 
                   1014: 
                   1015: 

unix.superglobalmegacorp.com

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