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

unix.superglobalmegacorp.com

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