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

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

unix.superglobalmegacorp.com

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