Annotation of coherent/b/STREAMS/io.386/haiscsi.c, revision 1.1

1.1     ! root        1: /***********************************************************************
        !             2:  *  Module: haiscsi.c
        !             3:  *
        !             4:  *  This is the interface between the Coherent kernel, the host
        !             5:  *  adapter module and the SCSI device modules. It's just a simple
        !             6:  *  dispatcher that determines which routine to call based upon the
        !             7:  *  calling device's Target ID.  The target ID should be set in bits
        !             8:  *  4-6 of the device's minor number.  
        !             9:  *
        !            10:  *  Copyright (c) 1993, Christopher Sean Hilton, All Rights Reserved.
        !            11:  *
        !            12:  *  Last Modified: Sat Jul 24 08:08:28 1993 by [chris]
        !            13:  */
        !            14: 
        !            15: #include <stddef.h>
        !            16: #include <sys/coherent.h>
        !            17: #include <sys/con.h>
        !            18: #include <sys/buf.h>
        !            19: #include <sys/io.h>
        !            20: #include <sys/sched.h>
        !            21: #include <sys/stat.h>
        !            22: 
        !            23: #include <sys/uproc.h>
        !            24: #include <errno.h>
        !            25: 
        !            26: #include <sys/haiscsi.h>
        !            27: #include <sys/haiioctl.h>
        !            28: 
        !            29: /*
        !            30:  *  Constants.
        !            31:  */
        !            32: #define GROUPMASK   0xe0
        !            33: #define GROUP0   0x00          /* SCSI-1/2 */
        !            34: #define GROUP1   0x20          /* SCSI-1/2 */
        !            35: #define GROUP2   0x40          /* SCSI-2 */
        !            36: #define GROUP5   0xa0          /* SCSI-1/2 */
        !            37: 
        !            38: /* Configurable variables - see /etc/conf/hai/Space.c. */
        !            39: extern int HAI_DISK;
        !            40: extern int HAI_TAPE;
        !            41: 
        !            42: extern int nonedev();     /* Set error and exit. */
        !            43: extern int nulldev();     /* Do nothing and exit. */
        !            44: 
        !            45: /*
        !            46:  * Device type entry points.
        !            47:  */
        !            48: extern dca_t    sddca;         /* Fixed disk control routines */
        !            49: extern dca_t    ctdca;         /* Cartridge tape control routines */
        !            50: extern dca_t   haict3600;      /* Cartridge tape (Tandberg TDC3600) */
        !            51: 
        !            52: dca_t  mdca[MAXDEVS];          /* Initialized by setup_mdca(). */
        !            53: 
        !            54: static void scsi_open();       /* Open dispatcher */
        !            55: static void scsi_close();      /* Close dispatcher */
        !            56: static void scsi_block();      /* Block dispatcher */
        !            57: static void scsi_read();       /* Read dispatcher */
        !            58: static void scsi_write();      /* Write dispatcher */
        !            59: static void scsi_ioctl();      /* I/O Control dispatcher */
        !            60: static int scsi_load();                /* Load driver */
        !            61: static int scsi_unload();      /* Unload driver */
        !            62: 
        !            63: static void setup_mdca();      /* Put device handlers into SCSI id table. */
        !            64: 
        !            65: CON scsicon = {
        !            66:        DFBLK | DFCHR,
        !            67:        SCSIMAJOR,
        !            68:        scsi_open,              /* Open entry point */
        !            69:        scsi_close,             /* Close entry point */
        !            70:        scsi_block,             /* Block entry point. */
        !            71:        scsi_read,              /* Read Entry point */
        !            72:        scsi_write,             /* write entry point */
        !            73:        scsi_ioctl,             /* IO control entry point */
        !            74:        nulldev,                /* No powerfail entry (yet?) */
        !            75:        hatimer,                /* timeout entry point */
        !            76:        scsi_load,              /* Load entry point */
        !            77:        scsi_unload,            /* Unload entry point */
        !            78:        nulldev                 /* No poll entry yet either. */
        !            79: };
        !            80: 
        !            81: static char *errstr[] = {
        !            82:        "No sense",
        !            83:        "Recovered error",
        !            84:        "Not ready",
        !            85:        "Medium error",
        !            86:        "Hardware error",
        !            87:        "Illegal request",
        !            88:        "Unit attention",
        !            89:        "Data protect",
        !            90:        "Blank check",
        !            91:        "Vendor unique error",
        !            92:        "Copy Aborted",
        !            93:        "Aborted command",
        !            94:        "Equal",
        !            95:        "Volume overflow",
        !            96:        "Miscompare",
        !            97:        "Reserved"
        !            98: };
        !            99: 
        !           100: char iofailmsg[] = "%s: status(0x%x)";
        !           101: int  HAI_HAID  = 7;
        !           102: 
        !           103: extern int hapresent;          /* Provided/Controled by host adapter module */
        !           104: extern dca_p mdca[MAXDEVS];    /* See haicfg.c */
        !           105: 
        !           106: /***********************************************************************
        !           107:  *  int scsi_open(dev_t dev, int mode)
        !           108:  *
        !           109:  *  Open a device on the SCSI bus at target ID: tid(dev). This is
        !           110:  *  Accomplished by calling the open routine at mdca[tid(dev)]->d_open
        !           111:  */
        !           112: 
        !           113: static void scsi_open(dev, mode)
        !           114: register dev_t   dev;
        !           115: int mode;
        !           116: {
        !           117:        register dca_p d = mdca[tid(dev)];
        !           118: 
        !           119:        if (!hapresent || !d)
        !           120:                u. u_error = EINVAL;
        !           121:        else
        !           122:                (*(d->d_open))(dev, mode);
        !           123: }   /* scsi_open() */
        !           124: 
        !           125: /***********************************************************************
        !           126:  *  void scsi_close()
        !           127:  *
        !           128:  *  Close entry point for all devices at major index SCSIMAJOR.
        !           129:  */
        !           130: 
        !           131: static void scsi_close(dev)
        !           132: register dev_t dev;
        !           133: {
        !           134:        register dca_p d = mdca[tid(dev)];
        !           135: 
        !           136:        if (!hapresent || !d)
        !           137:                u. u_error = EINVAL;
        !           138:        else
        !           139:                (*(d->d_close))(dev);
        !           140: }   /* scsi_close() */
        !           141: 
        !           142: /***********************************************************************
        !           143:  *  void scsi_block()
        !           144:  *
        !           145:  *  Block Entry point.
        !           146:  */
        !           147: 
        !           148: static void scsi_block(bp)
        !           149: register BUF *bp;
        !           150: {
        !           151:        register dca_p d = mdca[tid(bp->b_dev)];
        !           152: 
        !           153:        if (!hapresent || !d) {
        !           154:                bp->b_resid = bp->b_count;
        !           155:                bp->b_flag |= BFERR;
        !           156:                bdone(bp);
        !           157:        }
        !           158:        else
        !           159:                (*(d->d_block))(bp);
        !           160: }   /* scsi_block() */
        !           161: 
        !           162: /***********************************************************************
        !           163:  *  void scsi_read()
        !           164:  *
        !           165:  *  Read entry point.
        !           166:  */
        !           167: 
        !           168: void scsi_read(dev, iop)
        !           169: register dev_t  dev;
        !           170: register IO  *iop;
        !           171: {
        !           172:        register dca_p d = mdca[tid(dev)];
        !           173:        if (!hapresent || !d)
        !           174:                u. u_error = EINVAL;
        !           175:        else
        !           176:                (*(d->d_read))(dev, iop);
        !           177: }   /* scsi_read() */
        !           178: 
        !           179: /***********************************************************************
        !           180:  *  int scsi_write()
        !           181:  *
        !           182:  *  Write entry point.
        !           183:  */
        !           184: 
        !           185: void scsi_write(dev, iop)
        !           186: register dev_t  dev;
        !           187: IO  *iop;
        !           188: {
        !           189:        register dca_p d = mdca[tid(dev)];
        !           190:        if (!hapresent || !d)
        !           191:                u. u_error = EINVAL;
        !           192:        else
        !           193:                (*(d->d_write))(dev, iop);
        !           194: }   /* scsi_write() */
        !           195: 
        !           196: /***********************************************************************
        !           197:  *  scsi_ioctl()
        !           198:  *
        !           199:  *  IO Control entry point.
        !           200:  */
        !           201: 
        !           202: static void scsi_ioctl(dev, cmd, vec)
        !           203: register dev_t  dev;
        !           204: int                     cmd;
        !           205: char                   *vec;
        !           206: {
        !           207:        register dca_p d = mdca[tid(dev)];
        !           208: 
        !           209:        if (!hapresent || !d)
        !           210:                u. u_error = EINVAL;
        !           211:        else
        !           212:                (*(d->d_ioctl))(dev, cmd, vec);
        !           213: }   /* scsi_ioctl() */
        !           214: 
        !           215: /***********************************************************************
        !           216:  *  scsi_load()
        !           217:  *
        !           218:  *  Load Entry point.
        !           219:  */
        !           220: 
        !           221: static int scsi_load()
        !           222: 
        !           223: {
        !           224:        register int    id;
        !           225:        register dca_p  d;
        !           226: 
        !           227:        printf("Host Adapter Independent SCSI Driver v1.1\n");
        !           228:        hainit();
        !           229:        if (!hapresent)
        !           230:                printf("Host Adapter Initialization failed.\n");
        !           231: 
        !           232:        setup_mdca();
        !           233: 
        !           234:        for (id = 0; id < MAXDEVS; ++id) {
        !           235:                if ((d = mdca[id]) && d->d_load) {
        !           236:                        printf("ID %d: ", id);
        !           237:                        if (!(*(d->d_load))(id))
        !           238:                                printf("\tLoad() failed.\n");
        !           239:                }
        !           240:        }
        !           241:        return;
        !           242: }   /* scsi_load() */
        !           243: 
        !           244: /***********************************************************************
        !           245:  *  scsi_unload()
        !           246:  *
        !           247:  *  SCSI unload routine.
        !           248:  */
        !           249: 
        !           250: int scsi_unload()
        !           251: 
        !           252: {
        !           253:        register int    id;
        !           254:        register dca_p  d;
        !           255: 
        !           256:        for (id = 0; id < MAXDEVS; ++id)
        !           257:                if ((d = mdca[id]) && d->d_unload)
        !           258:                        (*(d->d_unload))(id);
        !           259: }   /* scsi_unload() */
        !           260: 
        !           261: /***********************************************************************
        !           262:  *  Utility Routines
        !           263:  */
        !           264: 
        !           265: /***********************************************************************
        !           266:  *  char *swapbytes()
        !           267:  *
        !           268:  *  Swap bytes in an object from big to little endian or vice versa.
        !           269:  */
        !           270: 
        !           271: char *swapbytes(mem, size)
        !           272: char   *mem;
        !           273: size_t  size;
        !           274: 
        !           275: {
        !           276:        register char *p = mem;
        !           277:        register char *q = p + size - 1;
        !           278: 
        !           279:        while (q > p) {
        !           280:                *p ^= *q;
        !           281:                *q ^= *p;
        !           282:                *p ^= *q;
        !           283:                p++;
        !           284:                q--;
        !           285:        }
        !           286:        return mem;
        !           287: }   /* swapbytes() */
        !           288: 
        !           289: /***********************************************************************
        !           290:  *  cpycdb()
        !           291:  *
        !           292:  *  Copy a SCSI Command/Data Block. Return the number of bytes copied.
        !           293:  */
        !           294: 
        !           295: int cpycdb(dst, src)
        !           296: register cdb_p dst;
        !           297: register cdb_p src;
        !           298: {
        !           299:                switch (src->g0. opcode & GROUPMASK) {
        !           300:                case GROUP0:
        !           301:                        memcpy(dst, src, sizeof(g0cmd_t));
        !           302:                        return sizeof(g0cmd_t);
        !           303:                case GROUP1:
        !           304:                case GROUP2:
        !           305:                        memcpy(dst, src, sizeof(g1cmd_t));
        !           306:                        return sizeof(g1cmd_t);
        !           307:                case GROUP5:
        !           308:                        memcpy(dst, src, sizeof(g5cmd_t));
        !           309:                        return sizeof(g5cmd_t);
        !           310:                default:
        !           311:                        return 0;
        !           312:        }
        !           313: }   /* cpycdb() */
        !           314: 
        !           315: /***********************************************************************
        !           316:  *  dumpmem()
        !           317:  *
        !           318:  *  Dump memory from (p) for (s) bytes.
        !           319:  */
        !           320: 
        !           321: static char hexchars[] = "0123456789abcdef",
        !           322:                        linebuf[] = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................\n";
        !           323: 
        !           324: void dumpmem(m, p, s)
        !           325: char m[];
        !           326: register unsigned char *p;
        !           327: register size_t s;
        !           328: {
        !           329:        register int i;
        !           330:        char *l;
        !           331: 
        !           332:        if (m)
        !           333:                printf(m);
        !           334:        printf(" (0x%x)\n", (unsigned) p);
        !           335:        memset(linebuf, ' ', sizeof(linebuf) - 2);
        !           336:        linebuf[48] = '|';
        !           337:        l = linebuf;
        !           338:        for (i = 0; i < s; ++i, ++p) {
        !           339:                *l++ = hexchars[(*p >> 4) & 0x0f];
        !           340:                *l++ = hexchars[*p & 0x0f];
        !           341:                *l++ = ' ';
        !           342:                linebuf[50 + (i & 15)] = (*p >= ' ' && *p <= '~') ? *p : '.';
        !           343:                if ((i & 15) == 15) {
        !           344:                        printf(linebuf);
        !           345:                        memset(linebuf, ' ', sizeof(linebuf) - 2);
        !           346:                        linebuf[48] = '|';
        !           347:                        l = linebuf;
        !           348:                }
        !           349:        }
        !           350:        if ((s & 15) != 0)
        !           351:                printf(linebuf);
        !           352: }   /* dumpmem() */
        !           353: 
        !           354: /***********************************************************************
        !           355:  *  scsidone()
        !           356:  *
        !           357:  *  Wake up processes sleeping on SRB (r).
        !           358:  */
        !           359: 
        !           360: static int scsidone(r)
        !           361: register srb_p r;
        !           362: {
        !           363:        wakeup(&(r->status));
        !           364: }
        !           365: 
        !           366: /***********************************************************************
        !           367:  *  reqsense()
        !           368:  *
        !           369:  *  Issue a request sense command device loaded into the target/lun
        !           370:  *  fields of the given srb r.  Uses v_sleep().
        !           371:  */
        !           372: 
        !           373: void reqsense(r)
        !           374: register srb_p r;
        !           375: {
        !           376:        int                      s;
        !           377:        unsigned short  status;
        !           378:        unsigned short  tries;
        !           379:        unsigned short  timeout;
        !           380:        bufaddr_t          buf;
        !           381:        unsigned short  xferdir;
        !           382:        int                      (*cleanup)();
        !           383:        cdb_t              cdb;
        !           384: 
        !           385:        if (r->status == ST_CHKCOND) {
        !           386:                status = ST_CHKCOND;
        !           387:                tries = r->tries;
        !           388:                timeout = r->timeout;
        !           389:                memcpy(&buf, &(r->buf), sizeof(bufaddr_t));
        !           390:                xferdir = r->xferdir;
        !           391:                cleanup = r->cleanup;
        !           392:                memcpy(&cdb, &(r->cdb), sizeof(cdb_t));
        !           393: 
        !           394:                r->timeout = 4;
        !           395:                r->buf. space = KRNL_ADDR;
        !           396:                r->buf. addr. caddr = (caddr_t) r->sensebuf;
        !           397:                r->buf. size = sizeof(r->sensebuf);
        !           398:                r->xferdir = DMAREAD;
        !           399:                r->cleanup = &scsidone;
        !           400:                memset(&(r->cdb), 0, sizeof(cdb_t));
        !           401:                r->cdb. g0. opcode = 0x03;
        !           402:                r->cdb. g0. lun_lba = (r->lun << 5);
        !           403:                r->cdb. g0. xfr_len = r->buf. size;
        !           404:                s = sphi();
        !           405:                startscsi(r);
        !           406:                while (r->status == ST_PENDING) {
        !           407:                        if (x_sleep(&(r->status), pritape, slpriSigCatch, "reqsense")) {
        !           408:                                u. u_error = EINTR;
        !           409:                                status = ST_USRABRT;
        !           410:                                break;
        !           411:                        }
        !           412:                }
        !           413:                spl(s);
        !           414: 
        !           415:                r->tries = tries;
        !           416:                r->timeout = timeout;
        !           417:                memcpy(&(r->buf), &buf, sizeof(bufaddr_t));
        !           418:                r->xferdir = xferdir;
        !           419:                r->cleanup = cleanup;
        !           420:                memcpy(&(r->cdb), &(cdb), sizeof(cdb_t));
        !           421:                r->status = status;
        !           422:        }
        !           423: }   /* reqsense() */
        !           424: 
        !           425: /***********************************************************************
        !           426:  *  doscsi()
        !           427:  *
        !           428:  *  An alternative to startscsi() which handles everything including
        !           429:  *  any request sense commands necessary if the command failed.  All
        !           430:  *  information is returned in given srb.  Note:  you can only use
        !           431:  *  this routine when the u structure for a process is available (from
        !           432:  *  an open, close, read, write, or ioctl routine).  Since this calls
        !           433:  *  sleep it will screw things up something fierce if you call it from
        !           434:  *  a load, unload, block, timer or interrupt routine.  Also note
        !           435:  *  that some host adapters do the sense part this automatically.
        !           436:  */
        !           437: 
        !           438: void doscsi(r, retrylimit, schedPri, sleepPri, reason)
        !           439: register srb_p  r;
        !           440: int                     retrylimit;
        !           441: int                     schedPri;
        !           442: int                     sleepPri;
        !           443: char                   reason[];
        !           444: {
        !           445:        int      s;
        !           446: 
        !           447:        r->cleanup = &scsidone;
        !           448:        for (r->tries = 0; r->tries < retrylimit; ) {
        !           449:                if (startscsi(r)) {
        !           450:                        s = sphi();
        !           451:                        while (r->status == ST_PENDING) {
        !           452:                                if (x_sleep(&(r->status), schedPri, sleepPri, reason)) {
        !           453:                                        abortscsi(r);
        !           454:                                        r->status = ST_USRABRT;
        !           455:                                        u. u_error = EINTR;
        !           456:                                }
        !           457:                        }
        !           458:                        spl(s);
        !           459:                        if (r->status == ST_GOOD)
        !           460:                                return;
        !           461: 
        !           462:                        if (r->status == ST_CHKCOND)
        !           463:                                reqsense(r);
        !           464:                }
        !           465:                else
        !           466:                        r->status = ST_TIMEOUT;
        !           467:        }
        !           468: }   /* doscsi() */
        !           469: 
        !           470: /***********************************************************************
        !           471:  *  printsense()
        !           472:  *
        !           473:  *  Print out the results in the given sense buffer.  This is done
        !           474:  *  in English, almost.
        !           475:  */
        !           476: 
        !           477: void printsense(dev, msg, e)
        !           478: register dev_t   dev;
        !           479: register char     *msg;
        !           480: register extsense_p e;
        !           481: {
        !           482:        long info;
        !           483:        if ((e->errorcode & 0x70) != 0x70)
        !           484:                devmsg(dev, "%s: Bad sensekey", msg);
        !           485:        else {
        !           486:                if ((e->errorcode & 0x80) != 0x80)
        !           487:                        devmsg(dev,
        !           488:                                   "%s: %s - key: (0x%x)",
        !           489:                                   msg,
        !           490:                                   errstr[e->sensekey & 0x0f],
        !           491:                                   (e->sensekey & 0xe0));
        !           492:                else {
        !           493:                        info = (long) e->info;
        !           494:                        flip(info);
        !           495:                        devmsg(dev,
        !           496:                                   "%s: %s - addr: %d key: (0x%x)",
        !           497:                                   msg,
        !           498:                                   errstr[e->sensekey & 0x0f],
        !           499:                                   info,
        !           500:                                   (e->sensekey & 0xe0));
        !           501:                }
        !           502:        }
        !           503: }   /* printsense() */
        !           504: 
        !           505: /***********************************************************************
        !           506:  *  printerror()
        !           507:  *  
        !           508:  *  Print an error after command completion.  Be silent if the command
        !           509:  *  was aborted by the user.
        !           510:  */
        !           511: 
        !           512: int printerror(r, msg)
        !           513: register srb_p r;
        !           514: register char *msg;
        !           515: {
        !           516:        if (r->status == ST_USRABRT)
        !           517:                return 0;
        !           518:        else {
        !           519:                if (r->status != ST_CHKCOND)
        !           520:                        devmsg(r->dev, iofailmsg, msg, r->status);
        !           521:                else
        !           522:                        printsense(r->dev, msg, r->sensebuf);
        !           523:                return 1;
        !           524:        }
        !           525: }   /* printerror() */
        !           526: 
        !           527: /***********************************************************************
        !           528:  *  haiioctl()  --       I/O Controls common to all devices.
        !           529:  *  
        !           530:  *  This function provides I/O Control functions common to all SCSI
        !           531:  *  devices.  The chain of operation should be as follows:
        !           532:  *  
        !           533:  *  You:
        !           534:  *       1)  Make sure that the device is in an appropriate state to
        !           535:  *               perform the I/O Control.  (It might not be a good idea to
        !           536:  *               format the disk drive with the root partition).
        !           537:  *  
        !           538:  *       2)  Call haiioctl() with your srb and cmd from I/O Control.
        !           539:  */
        !           540: 
        !           541: void haiioctl(r, cmd, vec)
        !           542: register srb_p  r;                       /* Device's srb */
        !           543: register int   cmd;                    /* Command to do */
        !           544: register char   *vec;             /* Additional information (if needed) */
        !           545: {
        !           546:        haiusercdb_t h;
        !           547:        
        !           548:        switch (cmd) {
        !           549:        case HAIINQUIRY:
        !           550:        case HAIMDSNS0:
        !           551:        case HAIMDSLCT0:
        !           552:        case HAIMDSNS2:
        !           553:        case HAIMDSLCT2:
        !           554:                u. u_error = ENXIO;
        !           555:                return;
        !           556:        case HAIUSERCDB:
        !           557:                if (super()) {
        !           558:                        if (!ukcopy(vec, &h, sizeof(haiusercdb_t)))
        !           559:                                return;
        !           560:                        r->buf. space = USER_ADDR;
        !           561:                        r->buf. addr. caddr = vec + sizeof(haiusercdb_t);
        !           562:                        r->buf. size = h. buflen;
        !           563:                        r->xferdir = h. xferdir;
        !           564:                        r->timeout = h. timeout;
        !           565:                        memcpy(&(r->cdb), &(h. cdb), sizeof(cdb_t));
        !           566:                        doscsi(r, 1, pritty, slpriSigCatch, "haiioctl");
        !           567:                        if (!kucopy(r->sensebuf, ((haiusercdb_p) vec)->sensebuf, SENSELEN))
        !           568:                                return;
        !           569:                }
        !           570:                return;
        !           571:        default:
        !           572:                u. u_error = ENXIO;
        !           573:                return;
        !           574:        }
        !           575:        return;
        !           576: }   /* haiioctl() */
        !           577: 
        !           578: /***********************************************************************
        !           579:  *  hainonblk()         --  Block entry point for devices that shouldn't
        !           580:  *                                       have block entry points.
        !           581:  *  
        !           582:  *  Since this is a multiplexing driver and some devices behind it
        !           583:  *  will have block entry points and some shouldn't.  ALL do.
        !           584:  */
        !           585: 
        !           586: void hainonblk(bp)
        !           587: register BUF   *bp;
        !           588: {
        !           589:        bp->b_flag |= BFERR;
        !           590:        bdone(bp);
        !           591: }   /* hainonblk() */
        !           592: 
        !           593: /*
        !           594:  * setup_mdca
        !           595:  *
        !           596:  * Load mdca table based on globals HAI_DISK and HAI_TAPE.
        !           597:  */
        !           598: void
        !           599: setup_mdca()
        !           600: {
        !           601:        int id, mask;
        !           602:        extern dca_t sddca;
        !           603:        extern dca_t ctdca;
        !           604: 
        !           605:        for (id = 0; id < 8; id ++) {
        !           606:                mask = 1 << id;
        !           607:                if (HAI_DISK & mask)
        !           608:                        mdca[id] = & sddca;
        !           609:                if (HAI_TAPE & mask)
        !           610:                        mdca[id] = & ctdca;
        !           611:        }
        !           612: }
        !           613: 
        !           614: /* End of file */

unix.superglobalmegacorp.com

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