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

unix.superglobalmegacorp.com

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