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