Annotation of researchv10no/cmd/worm/scsi/dslib.c, revision 1.1.1.1

1.1       root        1: /*
                      2: || dslib.c - library routines for /dev/scsi
                      3: ||
                      4: || Copyright 1988, 1989, by
                      5: ||   Gene Dronek (Vulcan Laboratory) and
                      6: ||   Rich Morin  (Canta Forda Computer Laboratory).
                      7: || All rights reserved.
                      8: */
                      9: #ident "dslib.c: $Revision: 1.4 $"
                     10: 
                     11: #include <stdio.h>
                     12: #include <sys/types.h>
                     13: 
                     14: #include "dslib.h"
                     15: #ifdef aux
                     16: #include <sys/vio.h>
                     17: #include <sys/scsireq.h>
                     18: #endif aux
                     19: 
                     20: int dsdebug=0;
                     21: long dsreqflags;       /* flag bits always set by filldsreq */
                     22: 
                     23: #define min(i,j)  ( (i) < (j) ? (i) : (j) )
                     24: 
                     25: 
                     26: /*
                     27: || Startup/shutdown -----------------------------------------------
                     28: */
                     29: 
                     30: static struct context *dsc[FDSIZ];
                     31: 
                     32: 
                     33: /*
                     34: || dsopen - open device, set up structures
                     35: */
                     36: 
                     37: struct dsreq *
                     38: dsopen(opath, oflags)
                     39:   char *opath;
                     40:   int   oflags;
                     41: {
                     42:     
                     43:   struct dsreq *dsp;
                     44:   struct context *cp;
                     45:   int fd;
                     46:   DSDBG(fprintf(stderr,"dsopen(%s,%x) ", opath, oflags));
                     47: 
                     48:   fd = open(opath, oflags);
                     49:   if (fd < 0)                                          
                     50:     return NULL;                       /* can't open   */
                     51:   if (dsc[fd] != NULL)                 /* already in use */
                     52:     ds_zot("dsopen: fd already in use");
                     53: 
                     54:   cp = (struct context *) calloc(1, sizeof(struct context));
                     55:   if (cp == NULL)                                    /* can't allocate */
                     56:     ds_zot("dsopen: can't allocate space");
                     57:   dsc[fd] = cp;
                     58:   cp->dsc_fd = fd;
                     59:   dsp = &(cp->dsc_dsreq);
                     60: 
                     61:   dsp->ds_flags =      0;
                     62:   dsp->ds_time =       10 * 1000;      /* 10 second default timeout */
                     63:   dsp->ds_private =    (ulong) cp;     /* pointer back to context */
                     64:   dsp->ds_cmdbuf =     cp->dsc_cmd;
                     65:   dsp->ds_cmdlen =     sizeof cp->dsc_cmd;
                     66:   dsp->ds_databuf =    0;
                     67:   dsp->ds_datalen =    0;
                     68:   dsp->ds_sensebuf =   cp->dsc_sense;
                     69:   dsp->ds_senselen =   sizeof cp->dsc_sense;
                     70:   DSDBG(fprintf(stderr,"=>cp %x, dsp %x\n", cp, dsp));
                     71:   return dsp;
                     72: }
                     73: 
                     74: 
                     75: /*
                     76: || dsclose - close device, release context struct.
                     77: */
                     78: 
                     79: dsclose(dsp)
                     80:   struct dsreq *dsp;
                     81: {
                     82:   int fd;
                     83:   struct context *cp;
                     84: 
                     85:   if (dsp == NULL)
                     86:     ds_zot("dsclose: dsp is NULL");
                     87: 
                     88:   cp = (struct context *)dsp->ds_private;
                     89:   fd = getfd(dsp);
                     90:   if ( cp == NULL )
                     91:     ds_zot("dsclose: private is NULL");
                     92: 
                     93:   cfree(cp);
                     94:   dsc[fd] = (struct context *)NULL;
                     95:   return;
                     96: }
                     97: 
                     98: 
                     99: /*
                    100: || Generic SCSI CCS Command functions ------------------------------------
                    101: ||
                    102: || dsp         dsreq pointer
                    103: || data                data buffer pointer
                    104: || datalen     data buffer length
                    105: || lba         logical block address
                    106: || vu          vendor unique bits
                    107: */
                    108: 
                    109: /*
                    110: || testunitready00 - issue group 0 "Test Unit Ready" command (0x00)
                    111: */
                    112: 
                    113: testunitready00(dsp)
                    114:   struct dsreq *dsp;
                    115: {
                    116:   fillg0cmd(dsp, CMDBUF(dsp), G0_TEST, 0, 0, 0, 0, 0);
                    117:   filldsreq(dsp, 0, 0, DSRQ_READ|DSRQ_SENSE);
                    118:   return(doscsireq(getfd(dsp), dsp));
                    119: }
                    120: 
                    121: 
                    122: /*
                    123: || requestsense03 - issue group 0 "Request Sense" command (0x03)
                    124: */
                    125: 
                    126: requestsense03(dsp, data, datalen, vu)
                    127:   struct dsreq *dsp;
                    128:   caddr_t data;
                    129:   long datalen;
                    130:   char vu;
                    131: {
                    132:   fillg0cmd(dsp, CMDBUF(dsp), G0_REQU, 0, 0, 0, B1(datalen), B1(vu<<6));
                    133:   filldsreq(dsp, data, datalen, DSRQ_READ);
                    134:   return(doscsireq(getfd(dsp), dsp));
                    135: }
                    136: 
                    137: 
                    138: /*
                    139: || write0a - issue group 0 "Write" command (0x0a)
                    140: */
                    141: 
                    142: write0a(dsp, data, datalen, lba, vu)
                    143:   struct dsreq *dsp;
                    144:   caddr_t data;
                    145:   long datalen, lba;
                    146:   char vu;
                    147: {
                    148:   fillg0cmd(dsp, CMDBUF(dsp), G0_WRIT, B3(lba), B1(datalen), B1(vu<<6));
                    149:   filldsreq(dsp, data, datalen, DSRQ_READ);
                    150:   return(doscsireq(getfd(dsp), dsp));
                    151: }
                    152: 
                    153: 
                    154: /*
                    155: || inquiry12 - issue group 0 "Inquiry" command (0x12)
                    156: */
                    157: 
                    158: inquiry12(dsp, data, datalen, vu)
                    159:   struct dsreq *dsp;
                    160:   caddr_t data;
                    161:   long datalen;
                    162:   char vu;
                    163: {
                    164:   fillg0cmd(dsp, CMDBUF(dsp), G0_INQU, 0, 0, 0, B1(datalen), B1(vu<<6));
                    165:   filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE);
                    166:   return(doscsireq(getfd(dsp), dsp));
                    167: }
                    168: 
                    169: 
                    170: /*
                    171: || modeselect15 - issue group 0 "Mode Select" command (0x15)
                    172: ||
                    173: || save                0 - don't save saveable pages
                    174: ||             1 - save saveable pages
                    175: */
                    176: 
                    177: modeselect15(dsp, data, datalen, save, vu)
                    178:   struct dsreq *dsp;
                    179:   caddr_t data;
                    180:   long datalen;
                    181:   char save, vu;
                    182: {
                    183:   fillg0cmd(dsp, CMDBUF(dsp), G0_MSEL, save&1, 0, 0, B1(datalen), B1(vu<<6));
                    184:   filldsreq(dsp, data, datalen, DSRQ_WRITE|DSRQ_SENSE);
                    185:   return(doscsireq(getfd(dsp), dsp));
                    186: }
                    187: 
                    188: 
                    189: /*
                    190: || modesense1a - issue group 0 "Mode Sense" command (0x1a)
                    191: ||
                    192: || pagectrl    0 - current values
                    193: ||             1 - changeable values
                    194: ||             2 - default values
                    195: ||             3 - saved values
                    196: ||
                    197: || pagecode    0   - vendor unique
                    198: ||             1   - error recovery
                    199: ||             2   - disconnect/reconnect
                    200: ||             3   - direct access dev. fmt.
                    201: ||             4   - rigid disk geometry
                    202: ||             5   - flexible disk
                    203: ||             6-9 - see specific dev. types
                    204: ||             0a  - implemented options
                    205: ||             0b  - medium types supported
                    206: ||             3f  - return all pages
                    207: */
                    208: 
                    209: modesense1a(dsp, data, datalen, pagectrl, pagecode, vu)
                    210:   struct dsreq *dsp;
                    211:   caddr_t data;
                    212:   long datalen;
                    213:   char pagectrl, pagecode, vu;
                    214: {
                    215:   fillg0cmd(dsp, CMDBUF(dsp), G0_MSEN, 0x10,
                    216:     ((pagectrl&3)<<6) | (pagecode&0x3F),
                    217:     0, B1(datalen), B1(vu<<6));
                    218:   filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE);
                    219:   return(doscsireq(getfd(dsp), dsp));
                    220: }
                    221: 
                    222: 
                    223: /*
                    224: || senddiagnostic1d - issue group 0 "Send Diagnostic" command (0x1d)
                    225: ||
                    226: || self                0 - run test, hold results
                    227: ||             1 - run test, return status
                    228: ||
                    229: || dofl                0 - device online
                    230: ||             1 - device offline
                    231: ||
                    232: || uofl                0 - unit online
                    233: ||             1 - unit offline
                    234: */
                    235: 
                    236: senddiagnostic1d(dsp, data, datalen, self, dofl, uofl, vu)
                    237:   struct dsreq *dsp;
                    238:   caddr_t data;
                    239:   long datalen;
                    240:   char self, dofl, uofl, vu;
                    241: {
                    242:   fillg0cmd(dsp, CMDBUF(dsp), G0_MSEN,
                    243:     (self&1)<<2 | (dofl&1)<<1 | (uofl&1),
                    244:     0, B2(datalen), B1(vu<<6));
                    245:   filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE);
                    246:   return(doscsireq(getfd(dsp), dsp));
                    247: }
                    248: 
                    249: 
                    250: /*
                    251: || readcapacity25 - issue group 1 "Read Capacity" command (0x25)
                    252: ||
                    253: || pmi         0 - return last logical block, entire unit
                    254: ||             1 - return last logical block, current track
                    255: */
                    256: 
                    257: readcapacity25(dsp, data, datalen, lba, pmi, vu)
                    258:   struct dsreq *dsp;
                    259:   caddr_t data;
                    260:   long datalen, lba;
                    261:   char pmi, vu;
                    262: {
                    263:   fillg1cmd(dsp, CMDBUF(dsp), G1_RCAP, 0, B4(lba), 0, 0, pmi&1, B1(vu<<6));
                    264:   filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE
                    265:     /* |DSRQ_CTRL2 */ );
                    266:   /* dsp->ds_time = 100;       /* often takes a while */
                    267:   return(doscsireq(getfd(dsp), dsp));
                    268: }
                    269: 
                    270: 
                    271: /*
                    272: || readextended28 - issue group 1 "Read Extended" command (0x28)
                    273: */
                    274: 
                    275: readextended28(dsp, data, datalen, lba, vu)
                    276:   struct dsreq *dsp;
                    277:   caddr_t data;
                    278:   long datalen, lba;
                    279:   char vu;
                    280: {
                    281:   fillg1cmd(dsp, CMDBUF(dsp), G1_READ, 0, B4(lba), 0, B2(datalen), B1(vu<<6));
                    282:   filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE
                    283:     /* |DSRQ_CTRL2 */ );
                    284:   /* dsp->ds_time = 100;       /* often takes a while */
                    285:   return(doscsireq(getfd(dsp), dsp));
                    286: }
                    287: 
                    288: 
                    289: /*
                    290: || writeextended2a - issue group 1 "Write Extended" command (0x2a)
                    291: */
                    292: 
                    293: writeextended2a(dsp, data, datalen, lba, vu)
                    294:   struct dsreq *dsp;
                    295:   caddr_t data;
                    296:   long datalen, lba;
                    297:   char vu;
                    298: {
                    299:   fillg1cmd(dsp, CMDBUF(dsp), G1_WRIT, 0, B4(lba), 0, B2(datalen), B1(vu<<6));
                    300:   filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE
                    301:     /* |DSRQ_CTRL2 */ );
                    302:   /* dsp->ds_time = 100;       /* often takes a while */
                    303:   return(doscsireq(getfd(dsp), dsp));
                    304: }
                    305: 
                    306: 
                    307: /*
                    308: || Support functions ----------------------------------------------------
                    309: */
                    310: 
                    311: /*
                    312: || fillg0cmd - Fill a Group 0 command buffer
                    313: */
                    314: 
                    315: fillg0cmd(dsp, cmd, b0,b1,b2,b3,b4,b5)
                    316:   struct dsreq *dsp;
                    317:   uchar_t *cmd, b0,b1,b2,b3,b4,b5;
                    318: {
                    319:   uchar_t *c = cmd;
                    320:   DSDBG(fprintf(stderr,"fillg0cmd(%x,%x, %02x %02x %02x %02x %02x %02x)\n",
                    321:                dsp, cmd, b0,b1,b2,b3,b4,b5));
                    322:   *c++ = b0, *c++ = b1, *c++ = b2, *c++ = b3, *c++ = b4, *c++ = b5;
                    323:        
                    324:   CMDBUF(dsp) = (caddr_t) cmd;
                    325:   CMDLEN(dsp) = 6;
                    326: }
                    327: 
                    328: 
                    329: /*
                    330: || fillg1cmd - Fill a Group 1 command buffer
                    331: */
                    332: 
                    333: fillg1cmd(dsp, cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9)
                    334:   struct dsreq *dsp;
                    335:   uchar_t *cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9;
                    336: {
                    337:   uchar_t *c = cmd;
                    338:   DSDBG(fprintf(stderr,
                    339:     "fillg1cmd(%x,%x, %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x)\n",
                    340:                dsp, cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9));
                    341: 
                    342:   *c++ = b0, *c++ = b1, *c++ = b2, *c++ = b3, *c++ = b4, *c++ = b5;
                    343:   *c++ = b6, *c++ = b7, *c++ = b8, *c++ = b9;
                    344:        
                    345:   CMDBUF(dsp) = (caddr_t) cmd;
                    346:   CMDLEN(dsp) = 10;
                    347: }
                    348: 
                    349: 
                    350: /*
                    351: || filldsreq - Fill a dsreq structure
                    352: */
                    353: 
                    354: filldsreq(dsp,data,datalen,flags)
                    355:   struct dsreq         *dsp;
                    356:   uchar_t              *data;
                    357: {
                    358:   DSDBG(fprintf(stderr,"filldsreq(%x,%x,%d,%x) cmdlen %d\n",
                    359:                dsp,data,datalen,flags,CMDLEN(dsp)));
                    360:   dsp->ds_flags        = flags | dsreqflags |
                    361:          (((dsdebug&1) ? DSRQ_TRACE : 0) |
                    362:          ((dsdebug&2) ? DSRQ_PRINT : 0));
                    363:   dsp->ds_time = 10 * 1000;    /* default to 10 seconds */
                    364:   dsp->ds_link = 0;
                    365:   dsp->ds_synch        = 0;
                    366:   dsp->ds_ret          = 0;
                    367: 
                    368:   DATABUF(dsp)         = (caddr_t) data;
                    369:   DATALEN(dsp) = datalen;
                    370: }
                    371: 
                    372: 
                    373: /*
                    374: || bprint - print array of bytes, in hex.
                    375: */
                    376: 
                    377: #define hex(x) "0123456789ABCDEF" [ (x) & 0xF ]
                    378: 
                    379: bprint(s,n,nperline,space)
                    380:        char *s;
                    381: {
                    382:        int   i, x;
                    383:        char  *sp = (space) ? " ": "";
                    384: 
                    385:        for(i=0;i<n;i++)  {
                    386:                x = s[i];
                    387:                fprintf(stderr,((i%4==3)?"%c%c%s%s":"%c%c%s"),
                    388:                        hex(x>>4), hex(x), sp, sp);
                    389:                if ( i%nperline == (nperline - 1) )
                    390:                        fprintf(stderr,"\n");
                    391:        }
                    392:        if ( space )
                    393:                fprintf(stderr,"\n");
                    394: }
                    395: 
                    396: 
                    397: /*
                    398: || doscsireq - issue scsi command, return status or -1 error.
                    399: */
                    400: 
                    401: doscsireq( fd, dsp)
                    402:   int  fd;             /* ioctl file descriptor */
                    403:   struct dsreq *dsp;   /* devscsi request packet */
                    404: {
                    405:   int  cc;
                    406:   int  retries = 4;
                    407:   uchar_t      sbyte;
                    408: 
                    409:   DSDBG(fprintf(stderr,"doscsireq(%d,%x) %x ---- %s\n",fd,dsp,
                    410:     (CMDBUF(dsp))[0],
                    411:     ds_vtostr( (CMDBUF(dsp))[0], cmdnametab)));
                    412: 
                    413:   /*
                    414:    *  loop, issuing command
                    415:    *    until done, or further retry pointless
                    416:    */
                    417: 
                    418:   while ( --retries > 0 )  {
                    419: 
                    420:    caddr_t sp;
                    421: 
                    422:     sp =  SENSEBUF(dsp);
                    423:     DSDBG(fprintf(stderr,"cmdbuf   =  ");
                    424:                bprint(CMDBUF(dsp),CMDLEN(dsp),16,1));
                    425:     if ( (dsp->ds_flags & DSRQ_WRITE) )
                    426:       DSDBG(bprint( DATABUF(dsp), min(50,DATALEN(dsp)),16,1 ));
                    427:        
                    428: DSDBG(fprintf(stderr,"databuf datalen %x %d\n",DATABUF(dsp), DATALEN(dsp)));
                    429:     cc = ioctl( fd, DS_ENTER, dsp);
                    430:     if ( cc < 0)  {
                    431:       ds_panic(dsp, "cannot ioctl fd %d\n",fd);
                    432:     }
                    433:        
                    434:        DSDBG(fprintf(stderr,"cmdlen after ioctl=%d\n",CMDLEN(dsp)));
                    435:     DSDBG(fprintf(stderr,"ioctl=%d ret=%x %s",
                    436:       cc, RET(dsp), 
                    437:       RET(dsp) ? ds_vtostr(RET(dsp),dsrtnametab) : ""));
                    438:     DSDBG(if (SENSESENT(dsp)) fprintf(stderr," sensesent=%d",
                    439:       SENSESENT(dsp)));
                    440: 
                    441:     DSDBG(fprintf(stderr,
                    442:       " cmdsent=%d datasent=%d sbyte=%x %s\n",
                    443:       CMDSENT(dsp), DATASENT(dsp), STATUS(dsp),
                    444:       ds_vtostr(STATUS(dsp), cmdstatustab)));
                    445:     DSDBG(if ( FLAGS(dsp) & DSRQ_READ )
                    446:       bprint( DATABUF(dsp), min(16*16,DATASENT(dsp)), 16,1));
                    447: 
                    448: #ifdef aux
                    449:   /*
                    450:    *  check for AUX bus-error 
                    451:    *  we retry with poll-dma
                    452:    */
                    453:     if ( RET(dsp) == DSRT_AGAIN )  {
                    454:       int n = SDC_RDPOLL|SDC_WRPOLL;
                    455:       DSDBG(fprintf(stderr,"setting rd/wr-poll"));
                    456:       cc = ioctl( fd, DS_SET, n);      /* set bits */
                    457:       if ( cc != 0 )
                    458:         return -1;
                    459:     }
                    460: #endif aux
                    461: 
                    462:     if ( RET(dsp) == DSRT_NOSEL )
                    463:       continue;                /* retry noselect 3X */
                    464: 
                    465:     /* decode sense data returned */
                    466:     if ( SENSESENT(dsp) )  {
                    467:       DSDBG(
                    468:         fprintf(stderr, "sense key %x - %s\n",
                    469:           SENSEKEY(sp),
                    470:           ds_vtostr( SENSEKEY(sp), sensekeytab));
                    471:         bprint( SENSEBUF(dsp),
                    472:           min(100, SENSESENT(dsp)),
                    473:           16,1);
                    474:       );
                    475:     }
                    476:     DSDBG(fprintf(stderr, "sbyte %x\n", STATUS(dsp)));
                    477: 
                    478:     /* decode scsi command status byte */
                    479:     sbyte = STATUS(dsp);
                    480:     switch (sbyte)  {
                    481:       case 0x08:               /*  BUSY */
                    482:       case 0x18:               /*  RESERV CONFLICT */
                    483:        sleep(2);
                    484:        continue;
                    485:       case 0x00:               /*  GOOD */
                    486:       case 0x02:               /*  CHECK CONDITION */
                    487:       case 0x10:               /*  INTERM/GOOD */
                    488:       default:
                    489:        return sbyte;
                    490:     }
                    491:   }
                    492:   return -1;   /* fail retry limit */
                    493: }
                    494: 
                    495: 
                    496: /*
                    497: || opttovar - lookup option in table, return var addr (NULL if fail)
                    498: */
                    499: 
                    500: int *
                    501: opttovar( ostr, table)
                    502:   char *ostr;
                    503:   struct opttab{
                    504:     char *opt;
                    505:     int  *var;
                    506:   } *table;
                    507: {
                    508:   register struct opttab *tp;
                    509: 
                    510:   for (tp=table; (tp->var); tp++)
                    511:     if ( strncmp( ostr, tp->opt, 3) == 0 )
                    512:       break;
                    513: 
                    514:   if ( !tp->var )
                    515:     fprintf(stderr,"unknown option %s", ostr);
                    516:        
                    517:   return (tp->var);
                    518: }
                    519: 
                    520: 
                    521: /*
                    522: || ds_vtostr - lookup value in table to return string pointer
                    523: */
                    524: 
                    525: char *
                    526: ds_vtostr( v, table)
                    527:   long v;
                    528:   struct vtab *table;
                    529: {
                    530:   register struct vtab *tp;
                    531: 
                    532:   for (tp=table; (tp->string); tp++)
                    533:     if ( v == tp->val )
                    534:       break;
                    535:        
                    536:   return (tp->string) ? tp->string : "";
                    537: }
                    538: 
                    539: 
                    540: /*
                    541: || ds_panic - yelp, leave...
                    542: */
                    543: 
                    544: ds_panic( fmt, v)
                    545:   char *fmt;
                    546:   int v;
                    547: {
                    548:   extern errno;
                    549: 
                    550:   fprintf(stderr,fmt,v);
                    551:   fprintf(stderr,"\nerrno = %d\n",errno);
                    552:   exit(1);
                    553: }
                    554: 
                    555: 
                    556: /*
                    557: || ds_zot - go away, with a message.
                    558: */
                    559: 
                    560: ds_zot(message)
                    561:   char *message;
                    562: {
                    563:   fprintf(stderr, "%s\n", message);
                    564:   exit(1);
                    565: }

unix.superglobalmegacorp.com

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