Annotation of coherent/b/STREAMS/io.386/haiscsi.c, revision 1.1.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.