Annotation of coherent/b/kernel/io.386/aha.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * This is the host adaptor specific portion of the
        !             3:  * Adaptec AHA154x driver.
        !             4:  *
        !             5:  * $Log:       aha.c,v $
        !             6:  * Revision 1.9  93/04/16  06:57:55  bin
        !             7:  * Hal: kernel 76 update
        !             8:  * 
        !             9:  * Revision 1.1  93/03/18  10:31:13  root
        !            10:  * r74
        !            11:  * 
        !            12:  * Revision 1.1        91/04/30  11:01:41      root
        !            13:  * Shipped with COH 3.1.0
        !            14:  * 
        !            15:  */
        !            16: #include <sys/coherent.h>
        !            17: #include <sys/buf.h>
        !            18: #include <sys/sched.h>
        !            19: 
        !            20: #include <sys/scsiwork.h>
        !            21: #include <sys/aha154x.h>
        !            22: 
        !            23: #ifdef _I386
        !            24: extern char *palloc();
        !            25: #endif /* _I386 */
        !            26: 
        !            27: #ifndef _I386
        !            28: extern saddr_t sds;            /* System Data Selector */
        !            29: static paddr_t sds_physical;   /* as physical address */
        !            30: #endif /* _I386 */
        !            31: static short   aha_i_o_base;
        !            32: static char    aha_loaded;     /* did load() find a host adaptor? */
        !            33: static char    dev_bit_map[8]; /* one byte per SCSI-ID; one bit per LUN */
        !            34: char   drive_info[MAX_SCSI_ID * MAX_LUN]; /* "per drive" info/flags */
        !            35: 
        !            36: void   aha_intr();             /* interrupt service routine */
        !            37: 
        !            38: #define        MIN_MAILBOX     1
        !            39: int    MAX_MAILBOX = { 8 };    /* tunable value */
        !            40: 
        !            41: static scsi_work_t     *scsi_work_queue;
        !            42: static mailentry       *mailbox_in, *mailbox_out;
        !            43: static char            *aha_err_msg = { "no message" };
        !            44: 
        !            45: static long    aha_timeout[] = { 
        !            46: #define        TIMEOUT_PRESENT 0
        !            47:        0x30000L,
        !            48: #define        TIMEOUT_SENDCMD 1
        !            49:        0x10000L,
        !            50: #define        TIMEOUT_POLL    2
        !            51:        0x100L
        !            52: };
        !            53: 
        !            54: /*
        !            55:  * NIGEL: The 'ccb_t' structure defined in <sys/aha154x.h> has data for the
        !            56:  * SCSI controller, at least at the base. Presumably the 'ccb_sw' member is
        !            57:  * not for the SCSI controller, so data after the 'cmd_status' member is
        !            58:  * for the driver. The 'buffer' member is not used....
        !            59:  *
        !            60:  * Below I create a wrapper structure that separates driver-private data from
        !            61:  * the Adaptec 'ccb' like the original author should have written. This allows
        !            62:  * the 'ccb' to be threaded on a work list, and would obviate the need for the
        !            63:  * stupid machinery in "i386/mem_cache.c" (although not even that would be
        !            64:  * needed had page management been done right...)
        !            65:  *
        !            66:  * The primary motivation for this is to allow ccb's to be deallocated safely.
        !            67:  * The 286 version of the driver deallocated the structures in aha_process (),
        !            68:  * which was deferred from aha_intr (). The 4.0 version can not do that because
        !            69:  * due to the large size of the buffer cache a defer-table overflow might
        !            70:  * result. We compromise by creating a deferred work list and threading the
        !            71:  * ccb's on that and only deferring the 'start work' operation. Since
        !            72:  * aha_process () does no actual work but merely calls bdone () then frees the
        !            73:  * data, we create a 'free list' of ccb's and a deferred routine to free them,
        !            74:  * and leave aha_process () to call bdone () at interrupt level to give maximum
        !            75:  * throughput.
        !            76:  *
        !            77:  * You are now passing the Hack City limits. You are now in the Interdicted
        !            78:  * Zone.
        !            79:  */
        !            80: 
        !            81: #include <stddef.h>                    /* import offsetof () */
        !            82: 
        !            83: typedef struct driver_ccb      drv_ccb_t;
        !            84: 
        !            85: struct driver_ccb {
        !            86:        ccb_t           aha_ccb;        /* the driver CCB */
        !            87:        drv_ccb_t     * next;           /* for threading on work list */
        !            88: };
        !            89:        
        !            90: static drv_ccb_t     * free_list;      /* ccb's to free */
        !            91: static int             free_active;    /* nonzero if cleanup routine active */
        !            92: 
        !            93: /*
        !            94:  * There are two low-level allocators in use, one for 3.2 and one for 4.0,
        !            95:  * and rather than #ifdef the usage we call them via a macro below.
        !            96:  */
        !            97: 
        !            98: #ifdef _I386
        !            99: #define        AHA_ALLOC(size)         palloc (size)
        !           100: #define        AHA_FREE(size)          pfree (size)
        !           101: #else
        !           102: #define        AHA_ALLOC(size)         kalloc (size)
        !           103: #define        AHA_FREE(size)          kfree (size)
        !           104: #endif
        !           105: 
        !           106: 
        !           107: /*
        !           108:  * Cleanup routine for free list, called via defer () from ccb_free ().
        !           109:  *
        !           110:  * Many fields of active ccb's are filled in with other dynamically allocated
        !           111:  * structures; this code has responsibility for freeing all of them.
        !           112:  */
        !           113: void
        !           114: ccb_cleanup ()
        !           115: {
        !           116:        drv_ccb_t     * work;
        !           117:        int             s;
        !           118: 
        !           119:        s = sphi ();
        !           120:        while ((work = free_list) != NULL) {
        !           121:                free_list = work->next;
        !           122:                spl (s);
        !           123: 
        !           124: #ifdef _I386
        !           125:                /*
        !           126:                 * The following code is insane; the DSL stuff should be part
        !           127:                 * of this ccb system. This will be fixed when a total revamp
        !           128:                 * of memory management occurs, and the "mem_cache.c" stuff
        !           129:                 * gets spaced.
        !           130:                 *
        !           131:                 * In the original code, the ccb_forget () was done after the
        !           132:                 * ccb was totally freed. I put it here to save conditionals.
        !           133:                 */
        !           134:                dsl_free (work->aha_ccb.dataptr);
        !           135:                ccb_forget (& work->aha_ccb);
        !           136: #endif
        !           137: 
        !           138:                if (work->aha_ccb.ccb_sw != NULL)
        !           139:                        AHA_FREE (work->aha_ccb.ccb_sw);
        !           140:                AHA_FREE (work);
        !           141: 
        !           142:                s = sphi ();
        !           143:        }
        !           144: 
        !           145:        free_active = 0;                /* defer () needed to reschedule */
        !           146:        spl (s);
        !           147: }
        !           148: 
        !           149: 
        !           150: /*
        !           151:  * Allocate a ccb and return a pointer to it. Call from base level only.
        !           152:  * The scsi_work_t * value passed here is remembered so that when the ccb
        !           153:  * is deallocated it will be too. In addition, code in aha_process () uses
        !           154:  * this stored value to map back from a ccb to a buffer-cache entry.
        !           155:  */
        !           156: ccb_t *
        !           157: ccb_alloc (sw)
        !           158: scsi_work_t   *        sw;
        !           159: {
        !           160:        drv_ccb_t     * drvccb;
        !           161: 
        !           162:        if ((drvccb = (drv_ccb_t *) AHA_ALLOC (sizeof (* drvccb))) == NULL)
        !           163:                return NULL;
        !           164: 
        !           165:        /*
        !           166:         * Remember the 'sw' value. Note that this really should be put in
        !           167:         * our wrapper structure, but that is to be fixed later.
        !           168:         */
        !           169: 
        !           170:        drvccb->aha_ccb.ccb_sw = sw;
        !           171: 
        !           172:        /*
        !           173:         * Return a pointer to the inner adaptec ccb.
        !           174:         */
        !           175: 
        !           176:        return & drvccb->aha_ccb;
        !           177: }
        !           178: 
        !           179: 
        !           180: /*
        !           181:  * Return a ccb to the free pool. Callable from base or interrupt level. All
        !           182:  * the dynamically allocated member data of the ccb should be freed by this
        !           183:  * routine.
        !           184:  */
        !           185: void
        !           186: ccb_free (ccb)
        !           187: ccb_t        * ccb;
        !           188: {
        !           189:        int             s;
        !           190:        drv_ccb_t     * work;
        !           191: 
        !           192:        /*
        !           193:         * Perform a portable downcast from the aha_ccb to the base structure.
        !           194:         */
        !           195: 
        !           196:        work = (drv_ccb_t *) ((char *) ccb - offsetof (drv_ccb_t, aha_ccb));
        !           197: 
        !           198:        s = sphi ();
        !           199:        work->next = free_list;
        !           200:        free_list = work;
        !           201: 
        !           202:        if (free_active == 0) {
        !           203:                defer (ccb_cleanup, 0);
        !           204:                free_active = 1;
        !           205:        }
        !           206:        spl (s);
        !           207: }
        !           208: 
        !           209: 
        !           210: /*
        !           211:  * Map from a ccb to the 'scsi_work_t' that was memoized when the ccb was
        !           212:  * allocated.
        !           213:  */
        !           214: 
        !           215: #define        ccb_to_scsiwork(ccb)    (ccb->ccb_sw)
        !           216: 
        !           217: /*
        !           218:  * NIGEL: Welcome back to Hack City. Beware of mutant code!
        !           219:  */
        !           220: 
        !           221: #if    0
        !           222: static
        !           223: OUTB(port, value)
        !           224: short port;
        !           225: {      printf("<O(%x,%x)>", port, value);
        !           226:        outb(port, value);      }
        !           227: INB(port)
        !           228: short port;
        !           229: {      register int i = inb(port);
        !           230:        printf("<I(%x)=%x>", port, i);
        !           231:        return i;       }
        !           232: #else
        !           233: #define        OUTB(port, value)       outb(port, value)
        !           234: #define        INB(port)       inb(port)
        !           235: #endif
        !           236: 
        !           237: #ifdef TRACER
        !           238: #define        SETMSG(msg)     aha_err_msg = msg
        !           239: 
        !           240: static char *
        !           241: aha_last_msg()
        !           242: {
        !           243:        T_PIGGY(0x8000, return aha_err_msg;);
        !           244: 
        !           245:        return "error messages not verbose";
        !           246: }
        !           247: 
        !           248: #else /* TRACER */
        !           249: 
        !           250: #define        SETMSG(msg)
        !           251: static char *
        !           252: aha_last_msg()
        !           253: {
        !           254:        return "error messages not verbose";
        !           255: } 
        !           256: #endif /* TRACER */
        !           257: 
        !           258: static
        !           259: int
        !           260: no_mem()
        !           261: {
        !           262:        printf("aha154x: out of kernel memory\n");
        !           263: }
        !           264: 
        !           265: int
        !           266: aha_set_base(base)
        !           267: {
        !           268:        register int i;
        !           269: 
        !           270:        i = aha_i_o_base;
        !           271:        aha_i_o_base = base;
        !           272:        return i;
        !           273: }
        !           274: 
        !           275: int
        !           276: aha_get_base()
        !           277: {
        !           278:        return aha_i_o_base;
        !           279: }
        !           280: 
        !           281: aha_process(ccb)
        !           282:        ccb_t *ccb;
        !           283: {
        !           284:        register scsi_work_t *sw;
        !           285:        register BUF *bp;
        !           286: 
        !           287:        if ((sw = ccb_to_scsiwork (ccb)) == NULL) {
        !           288:                ccb->opcode = AHA_OP_INVALID;
        !           289:                wakeup(ccb);
        !           290:                return;
        !           291:        }
        !           292: 
        !           293:        bp = sw->sw_bp;
        !           294: 
        !           295:        if((ccb->hoststatus != 0) || (ccb->targetstatus != 0)) {
        !           296:                if(--sw->sw_retry > 0
        !           297:                   || (ccb->targetstatus == CHECK_TARGET_STATUS
        !           298:                   && ccb->cmd_status[12] == SENSE_UNIT_ATTENTION)) {
        !           299:                        int s = sphi();
        !           300:                        if(scsi_work_queue->sw_actf == NULL) {
        !           301:                                scsi_work_queue->sw_actf = sw;
        !           302:                        } else {
        !           303:                                scsi_work_queue->sw_actl->sw_actf = sw;
        !           304:                        }
        !           305:                        scsi_work_queue->sw_actl = sw;
        !           306:                        spl(s);
        !           307:                        aha_start();
        !           308:                        return;
        !           309:                }
        !           310:                bp->b_flag |= BFERR;
        !           311:        } else {
        !           312:                bp->b_resid = 0;
        !           313:        }
        !           314: 
        !           315:        bdone(bp);
        !           316:        ccb_free(ccb);
        !           317: }
        !           318: 
        !           319: static
        !           320: int    aha_1out(value)
        !           321: {
        !           322:        register int i;
        !           323: 
        !           324:        while((i = INB(aha_i_o_base + AHA_STATUS) & AHA_CDOPFULL) != 0)
        !           325:                if((i & AHA_INVDCMD)
        !           326:                 || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE))
        !           327:                        return -1;
        !           328:        OUTB(aha_i_o_base + AHA_WRITE, value);
        !           329:        return 0;
        !           330: }
        !           331: 
        !           332: static
        !           333: int    aha_1in()
        !           334: {
        !           335:        register int i;
        !           336: 
        !           337:        while((i = INB(aha_i_o_base + AHA_STATUS) & AHA_DIPFULL) == 0)
        !           338:                if((i & AHA_INVDCMD)
        !           339:                 || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE))
        !           340:                        return -1;
        !           341:        return INB(aha_i_o_base + AHA_READ) & 0xFF;
        !           342: }
        !           343: 
        !           344: static
        !           345: void   aha_cmd_out(value)
        !           346: {
        !           347:        register long l;
        !           348:        register int i;
        !           349: 
        !           350:        for(l = aha_timeout[TIMEOUT_SENDCMD]; --l > 0;) {
        !           351:                if(((i=INB(aha_i_o_base + AHA_STATUS))
        !           352:                    & AHA_SCSIIDLE) != 0) {
        !           353:                        aha_1out(value);
        !           354:                        return;
        !           355:                }
        !           356:        }
        !           357:        SETMSG("timeout sending cmd byte");
        !           358:        printf("aha154x: timeout sending cmd byte\n");
        !           359: }
        !           360: 
        !           361: static
        !           362: int    aha_poll()
        !           363: {
        !           364:        register int i;
        !           365:        register int l = aha_timeout[TIMEOUT_POLL];
        !           366:        while((--l > 0)
        !           367:          &&  ((i = INB(aha_i_o_base + AHA_INTERRUPT)) & AHA_CMD_DONE) == 0)
        !           368:                ;
        !           369:        if(l == 0)
        !           370:                printf("aha154x: aha_poll timed out\n");
        !           371: 
        !           372:        i = INB(aha_i_o_base + AHA_STATUS);
        !           373:        OUTB(aha_i_o_base + AHA_CONTROL, AHA_INTRRESET);
        !           374:        return i;
        !           375: }
        !           376: 
        !           377: static
        !           378: void   aha_get_data(vec, cnt)
        !           379: char   *vec;
        !           380: int    cnt;
        !           381: {
        !           382:        while(--cnt >= 0)
        !           383:                *vec++ = aha_1in();
        !           384:        aha_poll();
        !           385: }
        !           386: 
        !           387: static
        !           388: int    aha_present()
        !           389: {
        !           390:        long    l;
        !           391: 
        !           392:        if(INB(aha_i_o_base) == 0xFF) {
        !           393:                SETMSG("no adapter found at io base");
        !           394:                return -3;
        !           395:        }
        !           396:        for(l = aha_timeout[TIMEOUT_PRESENT];
        !           397:                (--l > 0) && (INB(aha_i_o_base + AHA_STATUS) & AHA_SELFTEST);)
        !           398:                        ;
        !           399:        if(l == 0) {
        !           400:                SETMSG("selftest not completed");
        !           401:                return -1;
        !           402:        }
        !           403:        if(INB(aha_i_o_base + AHA_STATUS) & AHA_DIAGFAIL) {
        !           404:                SETMSG("diagnostics failed");
        !           405:                return -2;
        !           406:        }
        !           407:        if(INB(aha_i_o_base + AHA_STATUS) & AHA_INITMAIL) {
        !           408:                SETMSG("mailbox initialization needed");
        !           409:                return 1;
        !           410:        }
        !           411:        if(INB(aha_i_o_base + AHA_STATUS) & AHA_SCSIIDLE) {
        !           412:                SETMSG("adaptor okay, idle");
        !           413:                return 0;
        !           414:        }
        !           415:        SETMSG("unknown status at start");
        !           416:        return -4;
        !           417: }
        !           418: 
        !           419: void
        !           420: aha_l_to_p3(value, vec)
        !           421:        paddr_t value;
        !           422:        P3 vec;
        !           423: {
        !           424:        register int i;
        !           425: 
        !           426:        for(i = 3; --i >= 0;) {
        !           427:                vec[i] = value & 0xFF;
        !           428:                value >>= 8;
        !           429:        }
        !           430: }
        !           431: 
        !           432: long
        !           433: aha_p3_to_l(vec)
        !           434:        P3 vec;
        !           435: {
        !           436:        register int i;
        !           437:        register long retval;
        !           438: 
        !           439:        retval = 0;
        !           440:        for(i = 0; i < 3; ++i) {
        !           441:                retval <<= 8;
        !           442:                retval |= vec[i];
        !           443:        }
        !           444: 
        !           445:        return(retval);
        !           446: } /* aha_p3_to_l() */
        !           447: 
        !           448: #ifndef _I386 /* All of aha_p3_to_v().  */
        !           449: static char *
        !           450: aha_p3_to_v(vec)
        !           451:        P3 vec;
        !           452: {
        !           453:        paddr_t adr;
        !           454: 
        !           455:        adr = vec[0];
        !           456:        adr <<= 16;
        !           457:        adr |= (vec[1]<<8) | vec[2];
        !           458:        adr -= sds_physical;
        !           459:        return (char *)adr;
        !           460: }
        !           461: #endif /* _I386 */
        !           462: 
        !           463: aha_device_info()
        !           464: {
        !           465:        register int i;
        !           466:        static char buf[256];
        !           467: 
        !           468:        aha_cmd_out(AHA_DO_GET_DEVICES);
        !           469:        aha_get_data(&buf[0], 8);
        !           470:        for(i = 0; i < 8; ++i)
        !           471:                if(buf[i] != 0)
        !           472:                        printf("[%d] %x ", i, buf[i]);
        !           473:        printf("\n");
        !           474: }
        !           475: 
        !           476: int    aha_unload(ireq)
        !           477: {
        !           478:        /*
        !           479:         *      we should really verify that everything
        !           480:         *      out there gets flushed.
        !           481:         */
        !           482:        if (!aha_loaded)
        !           483:                return;
        !           484:        if(mailbox_out) {
        !           485:                AHA_FREE (mailbox_out);
        !           486:                mailbox_out = 0;
        !           487:        }
        !           488:        clrivec(ireq);
        !           489: }
        !           490: 
        !           491: int    aha_load(dma, ireq, base, head)
        !           492: scsi_work_t *head;
        !           493: {
        !           494:        register int    i;
        !           495:        unsigned char   adr[4];
        !           496: 
        !           497:        aha_set_base(base);
        !           498:        if(mailbox_out == 0) {
        !           499:                if ((mailbox_out = 
        !           500:                     AHA_ALLOC (2 * MAX_MAILBOX * sizeof(mailentry))) == 0) {
        !           501:                        no_mem();
        !           502:                        return -1;
        !           503:                } else {
        !           504:                        mailbox_in = &mailbox_out[MAX_MAILBOX];
        !           505:                }
        !           506:        }
        !           507: 
        !           508:        for(i = 0; i < MAX_MAILBOX; ++i)
        !           509:                mailbox_out[i].cmd = mailbox_in[i].cmd = 0;
        !           510: 
        !           511: #ifdef _I386
        !           512:        aha_l_to_p3(vtop(mailbox_out), &adr[1]);
        !           513: #else /* _I386 */
        !           514:        sds_physical = VTOP2(0, sds);
        !           515:        aha_l_to_p3(VTOP2(mailbox_out, sds), &adr[1]);
        !           516: #endif /* _I386 */
        !           517: 
        !           518:        adr[0] = MAX_MAILBOX;
        !           519: 
        !           520:        /*
        !           521:         * setup HW
        !           522:         */
        !           523:        setivec(ireq, aha_intr);
        !           524: 
        !           525:        outb(0xD6, 0xC1);               /* DMA is currently hard coded for */
        !           526:        outb(0xD4, 0x01);               /* DMA channel 5 */
        !           527: 
        !           528: 
        !           529:        OUTB(aha_i_o_base+AHA_CONTROL, AHA_HARDRESET);
        !           530:        if (aha_present() < 0) {
        !           531:                printf("aha154x: initialization error or host adaptor not ");
        !           532:                printf("found at 0x%x\n", aha_i_o_base);
        !           533:                return -1;
        !           534:        }
        !           535:        aha_cmd_out(AHA_DO_MAILBOX_INIT);
        !           536:        for(i = 0; i < 4; ++i)
        !           537:                aha_1out(adr[i]);
        !           538:        scsi_work_queue = head;
        !           539:        ++aha_loaded;
        !           540:        return MAX_MAILBOX;
        !           541: }
        !           542: 
        !           543: aha_command(sc)
        !           544: register scsi_cmd_t *sc;
        !           545: {
        !           546:        register int i;
        !           547:        /* register */ ccb_t *ccb;
        !           548: 
        !           549:        short   count = sc->blklen;
        !           550:        long    block = sc->block;
        !           551: 
        !           552:        if ((ccb = ccb_alloc (NULL)) == NULL) {
        !           553:                no_mem();
        !           554:                return -1;
        !           555:        }
        !           556: 
        !           557: #ifdef _I386
        !           558:        ccb->opcode = AHA_OP_SIC_SG;            /* SCSI_INITIATOR*/
        !           559: #else /* _I386 */
        !           560:        ccb->opcode = AHA_OP_SIC;               /* SCSI_INITIATOR*/
        !           561: #endif /* _I386 */
        !           562:        ccb->target = (sc->unit & 0x1C) << 3;   /* SCSI ID */
        !           563:        ccb->target |= sc->unit & 0x3;          /* LUN */
        !           564:        if((ccb->cmd_status[0] = sc->cmd) == ScmdWRITEXTENDED) {
        !           565:                ccb->target |= AHA_CCB_DATA_OUT;
        !           566:        } else { /* READEXT, READCAP, INQUIRY */
        !           567:                ccb->target |= AHA_CCB_DATA_IN;
        !           568:        }
        !           569:        ccb->cmd_status[1] = 0;
        !           570:        ccb->cmd_status[2] = block;
        !           571:        ccb->cmd_status[3] = block >>16;
        !           572:        ccb->cmd_status[4] = block >> 8;
        !           573:        ccb->cmd_status[5] = block;
        !           574:        ccb->cmd_status[6] = 0;
        !           575:        ccb->cmd_status[7] = count / 512;
        !           576:        ccb->cmd_status[8] = count;
        !           577:        ccb->cmd_status[9] = 0;
        !           578:        ccb->cmdlen = 10;
        !           579:        ccb->senselen = MAX_SENSEDATA;
        !           580: 
        !           581: #ifdef _I386
        !           582:        dsl_gen(ccb->dataptr, ccb->datalen, sc->buffer, (long)sc->buflen);
        !           583:        aha_l_to_p3(vtop(ccb), mailbox_out[0].adr);
        !           584:        ccb_remember(ccb, mailbox_out[0].adr);
        !           585: #else /* _I386 */
        !           586:        aha_l_to_p3((long)sc->buflen, ccb->datalen);
        !           587:        aha_l_to_p3(sc->buffer, ccb->dataptr);
        !           588:        aha_l_to_p3(VTOP2(ccb, sds), mailbox_out[0].adr);
        !           589: #endif /* _I386 */
        !           590: 
        !           591:        mailbox_out[0].cmd = MBO_TO_START;
        !           592: 
        !           593:        /* Start the AHA-154x scanning the mailboxes.  */
        !           594:        aha_1out(AHA_DO_SCSI_START);
        !           595: 
        !           596:        /* Wait for this ccb to finish.  */
        !           597:        while(ccb->opcode != AHA_OP_INVALID) {
        !           598: #ifdef _I386
        !           599:                x_sleep(ccb, pridisk, slpriNoSig, "aha:ccb");
        !           600: #else
        !           601:                v_sleep(ccb, CVBLKIO, IVBLKIO, SVBLKIO, "aha:ccb");
        !           602: #endif
        !           603:                /* The AHA-154x driver is waiting for a ccb to complete.  */
        !           604:        }
        !           605:        
        !           606:        if((ccb->targetstatus == CHECK_TARGET_STATUS)
        !           607:           && (ccb->cmd_status[12] != SENSE_UNIT_ATTENTION)) {
        !           608:                printf("aha: SCSI ID %d LUN %d. SCSI sense =",
        !           609:                (sc->unit >> 2), sc->unit & 0x3);
        !           610:                for(i = 0; i < ccb->senselen; ++i)
        !           611:                        printf(" %x", ccb->cmd_status[10+i]);
        !           612:                printf("\n");
        !           613:        }
        !           614:        i = ccb->hoststatus | ccb->targetstatus;
        !           615: 
        !           616:        /*
        !           617:         * NIGEL: If you are worried that the ccb memory is not getting freed
        !           618:         * soon enough, add a parameter to ccb_cleanup () to flag whether it
        !           619:         * should clear the active flag and call it directly here.
        !           620:         */
        !           621:        ccb_free(ccb);
        !           622: 
        !           623:        return i;
        !           624: }
        !           625: 
        !           626: ccb_t  *buildccb(sw)
        !           627: register scsi_work_t *sw;
        !           628: {
        !           629:        register ccb_t *ccb;
        !           630: 
        !           631:        if ((ccb = ccb_alloc(sw)) == NULL)
        !           632:                return NULL;
        !           633: 
        !           634: #ifdef _I386
        !           635:        ccb->opcode = AHA_OP_SIC_SG;            /* SCSI_INITIATOR*/
        !           636: #else /* _I386 */
        !           637:        ccb->opcode = AHA_OP_SIC;               /* SCSI_INITIATOR*/
        !           638: #endif /* _I386 */
        !           639: 
        !           640:        ccb->target = (sw->sw_drv & 0x1C) << 3; /* SCSI ID */
        !           641:        ccb->target |= (sw->sw_drv) & 0x3;      /* LUN */
        !           642:        if(sw->sw_bp->b_req == BREAD) {
        !           643:                ccb->target |= AHA_CCB_DATA_IN;
        !           644:                ccb->cmd_status[0] = ScmdREADEXTENDED;
        !           645:        } else {
        !           646:                ccb->target |= AHA_CCB_DATA_OUT;
        !           647:                ccb->cmd_status[0] = ScmdWRITEXTENDED;
        !           648:        }
        !           649:        ccb->cmd_status[2] = 0;
        !           650:        ccb->cmd_status[3] = sw->sw_bno >>16;
        !           651:        ccb->cmd_status[4] = sw->sw_bno >> 8;
        !           652:        ccb->cmd_status[5] = sw->sw_bno;
        !           653:        ccb->cmd_status[6] = 0;
        !           654:        ccb->cmd_status[7] = sw->sw_bp->b_count / (512*256L);
        !           655:        ccb->cmd_status[8] = sw->sw_bp->b_count / 512;
        !           656:        ccb->cmd_status[9] = 0;
        !           657:        ccb->cmdlen = 10;
        !           658:        ccb->senselen = MAX_SENSEDATA;
        !           659: 
        !           660: #ifdef _I386
        !           661:        dsl_gen(ccb->dataptr, ccb->datalen,
        !           662:                 sw->sw_bp->b_paddr, (long)sw->sw_bp->b_count);
        !           663: #else /* _I386 */
        !           664:        aha_l_to_p3((long)sw->sw_bp->b_count, ccb->datalen);
        !           665:        aha_l_to_p3(vtop(sw->sw_bp->b_faddr), ccb->dataptr);
        !           666: #endif /* _I386 */
        !           667:        /*
        !           668:         * The ccb's returned here are going to be freed by aha_process ().
        !           669:         */
        !           670:        return ccb;
        !           671: #if    0
        !           672: /* start of ioctl code */
        !           673:        if(f == SASI_CMD_IN)
        !           674:                ccb->target |= AHA_CCB_DATA_IN;
        !           675:        else if(f == SASI_CMD_OUT)
        !           676:                ccb->target |= AHA_CCB_DATA_OUT;
        !           677:        else
        !           678:                ccb->target |=   AHA_CCB_DATA_IN
        !           679:                                |AHA_CCB_DATA_OUT;
        !           680: #endif
        !           681: }
        !           682: 
        !           683: aha_start()
        !           684: {
        !           685:        register int i, s, n = 0;
        !           686:        scsi_work_t *sw;
        !           687:        static char locked;
        !           688: 
        !           689:        s = sphi();
        !           690:        if(locked) {
        !           691:                spl(s);
        !           692:                return;
        !           693:        }
        !           694:        ++locked;
        !           695:        spl(s);
        !           696: 
        !           697:        while((sw = scsi_work_queue->sw_actf) != NULL) {
        !           698:                for(i = MIN_MAILBOX; i < MAX_MAILBOX; ++i)
        !           699:                        if(mailbox_out[i].cmd == MBO_IS_FREE) {
        !           700:                                register ccb_t *ccb;
        !           701:                                int s;
        !           702: 
        !           703:                                ++n;
        !           704:                                if ((ccb = buildccb (sw)) == NULL) {
        !           705:                                        /*
        !           706:                                         * NIGEL: Earlier kernels did not
        !           707:                                         * diagnose this! 
        !           708:                                         */
        !           709:                                        goto out_of_mem;
        !           710:                                }
        !           711: #ifdef _I386
        !           712:                                aha_l_to_p3(vtop(ccb),
        !           713:                                                mailbox_out[i].adr);
        !           714:                                ccb_remember(ccb, mailbox_out[i].adr);
        !           715: #else /* _I386 */
        !           716:                                aha_l_to_p3(VTOP2(ccb, sds),
        !           717:                                                mailbox_out[i].adr);
        !           718: #endif /* _I386 */
        !           719:                                mailbox_out[i].cmd = MBO_TO_START;
        !           720: 
        !           721:                                aha_1out(AHA_DO_SCSI_START);
        !           722: 
        !           723:                                s = sphi();
        !           724:                                sw = scsi_work_queue->sw_actf = sw->sw_actf;
        !           725:                                if(sw == NULL)
        !           726:                                        scsi_work_queue->sw_actl = NULL;
        !           727:                                spl(s);
        !           728: 
        !           729:                                if(sw == NULL)
        !           730:                                        break;
        !           731:                        }
        !           732:                if(i == MAX_MAILBOX)
        !           733:                        break;
        !           734:        }
        !           735: out_of_mem:
        !           736:        --locked;
        !           737:        return n;
        !           738: }
        !           739: 
        !           740: int
        !           741: aha_completed()
        !           742: {
        !           743:        register int i, n;
        !           744: 
        !           745:        for(n = 0, i = 0; i < MAX_MAILBOX; ++i)
        !           746:                if(mailbox_in[i].cmd != MBI_IS_FREE) {
        !           747:                        /*
        !           748:                         * NIGEL: Earlier kernels deferred these, but with the
        !           749:                         * ccb_free ()/ccb_alloc () system that is no longer
        !           750:                         * necessary in either 4.x or 3.x systems.
        !           751:                         */
        !           752: #ifdef _I386
        !           753:                        aha_process(ccb_recall(mailbox_in[i].adr));
        !           754: #else /* _I386 */
        !           755:                        aha_process(aha_p3_to_v(mailbox_in[i].adr));
        !           756: #endif /* _I386 */
        !           757:                        mailbox_in[i].cmd = MBI_IS_FREE;
        !           758:                        ++n;
        !           759:                }
        !           760:        return n;
        !           761: }
        !           762: 
        !           763: void
        !           764: aha_intr()
        !           765: {
        !           766:        register int i;
        !           767: 
        !           768:        if(((i = INB(aha_i_o_base+AHA_INTERRUPT)) & AHA_ANY_INTER) == 0)
        !           769:                printf("aha: spurious interrupt %x\n", i);
        !           770: 
        !           771:        switch(i & AHA_ALL_INTERRUPTS) {
        !           772:        case AHA_RESETED:
        !           773:                break;
        !           774:        case AHA_CMD_DONE:
        !           775:                break;
        !           776:        case AHA_MBO_EMPTY:
        !           777:                defer(aha_start, (char *)0);
        !           778:                break;
        !           779:        case AHA_MBI_STORED:
        !           780:                aha_completed();
        !           781:                break;
        !           782:        default:
        !           783:                printf("aha: multiple interrupts not yet handled\n");
        !           784:        }
        !           785:        outb(aha_i_o_base+AHA_CONTROL, AHA_INTRRESET);
        !           786: }
        !           787: 
        !           788: aha_ioctl()
        !           789: {
        !           790:        printf("aha_ioctl: Not implemented\n");
        !           791: }
        !           792: 
        !           793: #ifdef TRACER
        !           794: static unsigned char vec[256];
        !           795: 
        !           796: static aha_ports_are() {
        !           797:        printf("aha_ports_are: %x %x %x\n",
        !           798:                INB(aha_i_o_base+0),
        !           799:                INB(aha_i_o_base+1),
        !           800:                INB(aha_i_o_base+2));
        !           801: }
        !           802: 
        !           803: static aha_inquiry_is() {
        !           804:        printf("aha_inquiry:");
        !           805:        printf("... aha_present = %d, ", aha_present());
        !           806:        printf("%s\n", aha_last_msg());
        !           807:        aha_cmd_out(AHA_DO_INQUIRY);
        !           808: 
        !           809:        aha_get_data(&vec[0], 4);
        !           810:        printf(" board id '%c'", vec[0]);
        !           811:        printf(", options '%c'", vec[1]);
        !           812:        printf(", HW '%c'", vec[2]);
        !           813:        printf(", FW '%c'\n", vec[3]);
        !           814: }
        !           815: 
        !           816: void   aha_setup_is() {
        !           817:        register int i;
        !           818: 
        !           819:        printf("Setup and Data:\n");
        !           820:        aha_cmd_out(AHA_DO_GET_SETUP);
        !           821:        aha_cmd_out(16);
        !           822:        aha_get_data(&vec[0], 16);
        !           823:        printf("  Data Xfer %s Sync (J1)\n", (vec[0]&1) ? "is" : "not");
        !           824:        printf("  Parity %s Enabled (J1)\n", (vec[0]&2) ? "is" : "not");
        !           825:        switch(vec[1]) {
        !           826:        case AHA_SPEED_5_0_MB:
        !           827:                printf("  5.0 Mb/sec.\n");      break;
        !           828:        case AHA_SPEED_6_7_MB:
        !           829:                printf("  6.7 Mb/sec.\n");      break;
        !           830:        case AHA_SPEED_8_0_MB:
        !           831:                printf("  8.0 Mb/sec.\n");      break;
        !           832:        case AHA_SPEED_10_MB:
        !           833:                printf("  10 Mb/sec.\n");       break;
        !           834:        case AHA_SPEED_5_7_MB:
        !           835:                printf("  5.7 Mb/sec.\n");      break;
        !           836:        default:
        !           837:                if(vec[1] & 0x80)
        !           838:                        printf("  Pulse Read %d, Write %d, Strobe off %d\n",
        !           839:                                50*(2+(vec[1]>>4)&0x7), 50*(2+(vec[1]&7)),
        !           840:                                vec[1] & 0x80 ? 150 : 100);
        !           841:        }
        !           842:        printf("  Bus Time ON %d, OFF %d\n", vec[2], vec[3]);
        !           843:        printf("  %d Mailboxes at %x|%x|%x\n", vec[4],
        !           844:                vec[5], vec[6], vec[7]);
        !           845:        for(i = 0; i < 8; ++i)
        !           846:                if(vec[i+8])
        !           847:                        printf("  Target [%d] = Sync Neg %x\n", i, vec[i+8]);
        !           848: }
        !           849: 
        !           850: static aha_mailboxes_are(n, adr)
        !           851: mailentry *adr;
        !           852: {
        !           853:        register int i;
        !           854: 
        !           855:        printf("addresses for mailbox is %x:%x\n", (long)adr);
        !           856:        for(i = 0; i < n; ++i, ++adr)
        !           857:                printf("  mbo[%x] = %x %x|%x|%x\n",
        !           858:                        i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2]);
        !           859:        for(i = 0; i < n; ++i, ++adr)
        !           860:                printf("  mbi[%x] = %x %x|%x|%x\n",
        !           861:                        i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2]);
        !           862: }
        !           863: 
        !           864: void   aha_status()
        !           865: {
        !           866:        aha_ports_are();
        !           867:        aha_inquiry_is();
        !           868: /*     aha_devices_are(); */   /* This appears to have never existed.  */
        !           869:        aha_setup_is();
        !           870:        aha_mailboxes_are(MAX_MAILBOX, mailbox_out);
        !           871: }
        !           872: 
        !           873: aha_ccb_print(ccb)
        !           874: ccb_t  *ccb;
        !           875: {
        !           876:        register int i;
        !           877:        register unsigned char *cp;
        !           878: 
        !           879:        printf("aha_ccb_print(ccb: %x)", ccb);
        !           880:        if (0 != ccb) {
        !           881:                printf(", sw: %x", ccb->ccb_sw);
        !           882:                if (0 != ccb->ccb_sw) {
        !           883:                        printf(", bp: %x", ccb->ccb_sw->sw_bp);
        !           884:                        if (0 != ccb->ccb_sw->sw_bp) {
        !           885:                                printf(", flag: %x",
        !           886:                                        ccb->ccb_sw->sw_bp->b_flag);
        !           887:                        }
        !           888:                }
        !           889:                printf(", op %d, ", ccb->opcode);
        !           890:                printf("target ID=%d, ", (ccb->target>>5) & 0x7);
        !           891:                printf("LUN=%d, ", (ccb->target & 0x7));
        !           892:                printf("dir=%s%s\n",    (ccb->target&AHA_CCB_DATA_IN)?"IN":"",
        !           893:                                        (ccb->target&AHA_CCB_DATA_OUT)?"OUT":"");
        !           894:                printf("data len %x|%x|%x, adr %x|%x|%x\n",
        !           895:                        ccb->datalen[0],ccb->datalen[1],ccb->datalen[2],
        !           896:                        ccb->dataptr[0],ccb->dataptr[1],ccb->dataptr[2]);
        !           897:                printf("status host=%x, target=%x\n",
        !           898:                        ccb->hoststatus, ccb->targetstatus);
        !           899:                printf("cmddata[%d]:", ccb->cmdlen);
        !           900:                for(i = 0, cp = ccb->cmd_status; i < ccb->cmdlen; ++i)
        !           901:                        printf(" %x", *cp++);
        !           902:                printf("\nrequest sense[%d]:", ccb->senselen);
        !           903:                for(i = 0; i < ccb->senselen; ++i)
        !           904:                        printf(" %x", *cp++);
        !           905:                if(i = cp[-1]) {
        !           906:                        printf("\n   + ");
        !           907:                        while(--i >= 0)
        !           908:                                printf(" %x", *cp++);
        !           909:                }
        !           910:                printf("\n");
        !           911:        }
        !           912: }
        !           913: 
        !           914: #endif /* TRACER */

unix.superglobalmegacorp.com

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