Annotation of Net2/arch/i386/isa/wd7000.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * UNFINISHED! UNFINISHED! UNFINISHED! UNFINISHED! UNFINISHED! UNFINISHED!
        !             3:  * 
        !             4:  * [email protected] 93/04/02
        !             5:  * 
        !             6:  * I was writing this driver for a wd7000-ASC. Yeah, the "-ASC" not the
        !             7:  * "-FASST2". The difference is that the "-ASC" is missing scatter gather
        !             8:  * support.
        !             9:  * 
        !            10:  * In any case, the real reason why I never finished it is because the
        !            11:  * motherboard I have has broken DMA. This card wants 8MHz 1 wait state
        !            12:  * operation, and my board munges about 30% of the words transferred.
        !            13:  * 
        !            14:  * Hopefully someone can finish this for the wd7000-FASST2. It should be
        !            15:  * quite easy to do. Look at the Linux wd7000 device driver to see how
        !            16:  * scatter gather is done by the board, then look at one of the Adaptec
        !            17:  * drivers to finish off the job..
        !            18:  */
        !            19: #include "wds.h"
        !            20: #if NWDS > 0
        !            21: 
        !            22: #include <sys/types.h>
        !            23: #include <sys/param.h>
        !            24: #include <sys/systm.h>
        !            25: #include <sys/errno.h>
        !            26: #include <sys/ioctl.h>
        !            27: #include <sys/buf.h>
        !            28: #include <sys/proc.h>
        !            29: #include <sys/user.h>
        !            30: 
        !            31: #include <i386/isa/isa_device.h>
        !            32: #include <scsi/scsi_all.h>
        !            33: #include <scsi/scsiconf.h>
        !            34: 
        !            35: extern int delaycount;  /* from clock setup code */
        !            36: 
        !            37: #define PHYSTOKV(x)    ( (u_long)(x) | 0xFE000000)
        !            38: #define KVTOPHYS(x)    vtophys(x)
        !            39: #define PAGESIZ        4096
        !            40: #define INVALIDATE_CACHE {asm volatile( ".byte 0x0F ;.byte 0x08" ); }
        !            41: 
        !            42: 
        !            43: /* WD7000 registers */
        !            44: #define WDS_STAT               0       /* read */
        !            45: #define WDS_IRQSTAT            1       /* read */
        !            46: 
        !            47: #define WDS_CMD                        0       /* write */
        !            48: #define WDS_IRQACK             1       /* write */
        !            49: #define WDS_HCR                        2       /* write */
        !            50: 
        !            51: /* WDS_STAT (read) defs */
        !            52: #define WDS_IRQ                        0x80
        !            53: #define WDS_RDY                        0x40
        !            54: #define WDS_REJ                        0x20
        !            55: #define WDS_INIT               0x10
        !            56: 
        !            57: /* WDS_IRQSTAT (read) defs */
        !            58: #define WDSI_MASK              0xc0
        !            59: #define WDSI_ERR               0x00
        !            60: #define WDSI_MFREE             0x80
        !            61: #define WDSI_MSVC              0xc0
        !            62: 
        !            63: /* WDS_CMD (write) defs */
        !            64: #define WDSC_NOOP              0x00
        !            65: #define WDSC_INIT              0x01
        !            66: #define WDSC_DISUNSOL          0x02
        !            67: #define WDSC_ENAUNSOL          0x03
        !            68: #define WDSC_IRQMFREE          0x04
        !            69: #define WDSC_SCSIRESETSOFT     0x05
        !            70: #define WDSC_SCSIRESETHARD     0x06
        !            71: #define WDSC_MSTART(m)         (0x80 + (m))
        !            72: #define WDSC_MMSTART(m)                (0xc0 + (m))
        !            73: 
        !            74: /* WDS_HCR (write) defs */
        !            75: #define WDSH_IRQEN             0x08
        !            76: #define WDSH_DRQEN             0x04
        !            77: #define WDSH_SCSIRESET         0x02
        !            78: #define WDSH_ASCRESET          0x01
        !            79: 
        !            80: struct wds_cmd {
        !            81:        u_char cmd;
        !            82:        u_char targ;
        !            83:        struct scsi_generic scb;                /*u_char scb[12];*/
        !            84:        u_char stat;
        !            85:        u_char venderr;
        !            86:        u_char len[3];
        !            87:        u_char data[3];
        !            88:        u_char next[3];
        !            89:        u_char write;
        !            90:        u_char xx[6];
        !            91: };
        !            92: 
        !            93: struct wds_req {
        !            94:        struct wds_cmd cmd;
        !            95:        struct wds_cmd sense;
        !            96:        struct scsi_xfer *sxp;
        !            97:        int busy, polled;
        !            98:        int done, ret, ombn;
        !            99: };
        !           100: 
        !           101: #define WDSX_SCSICMD           0x00
        !           102: #define WDSX_OPEN_RCVBUF       0x80
        !           103: #define WDSX_RCV_CMD           0x81
        !           104: #define WDSX_RCV_DATA          0x82
        !           105: #define WDSX_RCV_DATASTAT      0x83
        !           106: #define WDSX_SND_DATA          0x84
        !           107: #define WDSX_SND_DATASTAT      0x85
        !           108: #define WDSX_SND_CMDSTAT       0x86
        !           109: #define WDSX_READINIT          0x88
        !           110: #define WDSX_READSCSIID                0x89
        !           111: #define WDSX_SETUNSOLIRQMASK   0x8a
        !           112: #define WDSX_GETUNSOLIRQMASK   0x8b
        !           113: #define WDSX_GETFIRMREV                0x8c
        !           114: #define WDSX_EXECDIAG          0x8d
        !           115: #define WDSX_SETEXECPARM       0x8e
        !           116: #define WDSX_SETEXECPARM       0x8e
        !           117: #define WDSX_GETEXECPARM       0x8f
        !           118: 
        !           119: struct wds_mb {
        !           120:        u_char stat;
        !           121:        u_char addr[3];
        !           122: };
        !           123: /* ICMB status value */
        !           124: #define ICMB_OK                        0x01
        !           125: #define ICMB_OKERR             0x02
        !           126: #define ICMB_ETIME             0x04
        !           127: #define ICMB_ERESET            0x05
        !           128: #define ICMB_ETARCMD           0x06
        !           129: #define ICMB_ERESEL            0x80
        !           130: #define ICMB_ESEL              0x81
        !           131: #define ICMB_EABORT            0x82
        !           132: #define ICMB_ESRESET           0x83
        !           133: #define ICMB_EHRESET           0x84
        !           134: 
        !           135: struct wds_setup {
        !           136:        u_char cmd;
        !           137:        u_char scsi_id;
        !           138:        u_char buson_t;
        !           139:        u_char busoff_t;
        !           140:        u_char xx;
        !           141:        u_char mbaddr[3];
        !           142:        u_char nomb;
        !           143:        u_char nimb;
        !           144: };
        !           145: 
        !           146: #define WDS_NOMB       16
        !           147: #define WDS_NIMB       8
        !           148: #define MAXSIMUL       8
        !           149: struct wds {
        !           150:        u_short addr;
        !           151:        struct wds_req wdsr[MAXSIMUL];
        !           152:        struct wds_mb ombs[WDS_NOMB], imbs[WDS_NIMB];
        !           153:        int devs;
        !           154: } wds[NWDS];
        !           155: 
        !           156: static int wdsunit = 0;
        !           157: int wds_debug = 0;
        !           158: 
        !           159: int wdsprobe(), wdsattach(), wdsintr();
        !           160: 
        !           161: struct isa_driver wdsdriver = {
        !           162:        wdsprobe,
        !           163:        wdsattach,
        !           164:        "wds",
        !           165: };
        !           166: 
        !           167: int wds_scsi_cmd();
        !           168: void wds_minphys();
        !           169: long wds_adapter_info();
        !           170: 
        !           171: struct scsi_switch wds_switch = {
        !           172:        wds_scsi_cmd,
        !           173:        wds_minphys,
        !           174:        0, 0,
        !           175:        wds_adapter_info,
        !           176:        0, 0, 0,
        !           177: };
        !           178: 
        !           179: p2x(p, x)
        !           180: u_char *p;
        !           181: u_long x;
        !           182: {
        !           183:        p[0] = (x & 0x00ff0000) >> 16;
        !           184:        p[1] = (x & 0x0000ff00) >> 8;
        !           185:        p[2] = (x & 0x000000ff);
        !           186: }
        !           187: 
        !           188: u_char *
        !           189: x2p(x)
        !           190: u_char *x;
        !           191: {
        !           192:        u_long q;
        !           193: 
        !           194:        q = ((x[0]<<16) & 0x00ff0000) + ((x[1]<<8) & 0x0000ff00) + (x[2] & 0x000000ff);
        !           195:        return (u_char *)q;
        !           196: }
        !           197: 
        !           198: wdsprobe(dev)
        !           199: struct isa_device *dev;
        !           200: {
        !           201:        scsi_debug = PRINTROUTINES | TRACEOPENS | TRACEINTERRUPTS |
        !           202:                SHOWREQUESTS | SHOWSCATGATH | SHOWINQUIRY | SHOWCOMMANDS;
        !           203: 
        !           204:        if(wdsunit > NWDS)
        !           205:                return 0;
        !           206: 
        !           207:        dev->id_unit = wdsunit;
        !           208:        wds[wdsunit].addr = dev->id_iobase;
        !           209: 
        !           210:        if(wds_init(dev) != 0)
        !           211:                return 0;
        !           212:        wdsunit++;
        !           213:        return 1;
        !           214: }
        !           215: 
        !           216: void
        !           217: wds_minphys(bp)
        !           218: struct buf *bp;
        !           219: {
        !           220:        int base = (int)bp->b_un.b_addr & (PAGESIZ-1);
        !           221: 
        !           222:        if(base + bp->b_bcount > PAGESIZ)
        !           223:                bp->b_bcount = PAGESIZ - base;
        !           224: }
        !           225: 
        !           226: struct wds_req *
        !           227: wdsr_alloc(unit)
        !           228: int unit;
        !           229: {
        !           230:        struct wds_req *r;
        !           231:        int x;
        !           232:        int i;
        !           233: 
        !           234:        r = NULL;
        !           235:        x = splbio();
        !           236:        for(i=0; i<MAXSIMUL; i++)
        !           237:                if(wds[unit].wdsr[i].busy == 0) {
        !           238:                        r = &wds[unit].wdsr[i];
        !           239:                        r->busy = 1;
        !           240:                        break;
        !           241:                }
        !           242:        if(r == NULL) {
        !           243:                splx(x);
        !           244:                return NULL;
        !           245:        }
        !           246: 
        !           247:        r->ombn = -1;
        !           248:        for(i=0; i<WDS_NOMB; i++)
        !           249:                if(wds[unit].ombs[i].stat==0) {
        !           250:                        wds[unit].ombs[i].stat = 1;
        !           251:                        r->ombn = i;
        !           252:                        break;
        !           253:                }
        !           254:        if(r->ombn == -1 ) {
        !           255:                r->busy = 0;
        !           256:                splx(x);
        !           257:                return NULL;
        !           258:        }
        !           259:        splx(x);
        !           260:        return r;
        !           261: }
        !           262: 
        !           263: int
        !           264: wds_scsi_cmd(sxp)
        !           265: struct scsi_xfer *sxp;
        !           266: {
        !           267:        struct wds_req *r;
        !           268:        int unit = sxp->adapter;
        !           269:        u_short base;
        !           270:        u_char c, *p;
        !           271:        int i;
        !           272: 
        !           273:        base = wds[unit].addr;
        !           274: 
        !           275:        /*printf("scsi_cmd\n");*/
        !           276: 
        !           277:        if( sxp->flags & SCSI_RESET) {
        !           278:                printf("reset!\n");
        !           279:                return COMPLETE;
        !           280:        }
        !           281: 
        !           282:        /* XXX DEBUG */
        !           283:        if( sxp->targ != 1) {
        !           284:                printf("ignoring target %d/%d\n", sxp->targ, sxp->lu);
        !           285:                sxp->error = XS_TIMEOUT;
        !           286:                return HAD_ERROR;
        !           287:        }
        !           288: 
        !           289:        r = wdsr_alloc(unit);
        !           290:        if(r==NULL) {
        !           291:                printf("no request slot available!\n");
        !           292:                sxp->error = XS_DRIVER_STUFFUP;
        !           293:                return TRY_AGAIN_LATER;
        !           294:        }
        !           295:        r->done = 0;
        !           296:        r->sxp = sxp;
        !           297: 
        !           298:        printf("wds%d: target %d/%d req %8x flags %08x len %d: ", unit,
        !           299:                sxp->targ, sxp->lu, r, sxp->flags, sxp->cmdlen);
        !           300:        for(i=0, p=(u_char *)sxp->cmd; i<sxp->cmdlen; i++)
        !           301:                printf("%02x ", p[i]);
        !           302:        printf("\n");
        !           303:        printf("       data %08x datalen %08x\n", sxp->data, sxp->datalen);
        !           304: 
        !           305:        if(sxp->flags & SCSI_DATA_UIO) {
        !           306:                printf("UIO!\n");
        !           307:                sxp->error = XS_DRIVER_STUFFUP;
        !           308:                return TRY_AGAIN_LATER;
        !           309:        }
        !           310: 
        !           311:        p2x(&wds[unit].ombs[r->ombn].addr[0], KVTOPHYS(&r->cmd));
        !           312:        printf("%08x/%08x mbox@%08x: %02x %02x %02x %02x\n",
        !           313:                &r->cmd, KVTOPHYS(&r->cmd), &wds[unit].ombs[0], 
        !           314:                wds[unit].ombs[r->ombn].stat, wds[unit].ombs[r->ombn].addr[0],
        !           315:                wds[unit].ombs[r->ombn].addr[1], wds[unit].ombs[r->ombn].addr[2]);
        !           316: 
        !           317:        bzero(&r->cmd, sizeof r->cmd);
        !           318:        r->cmd.cmd = WDSX_SCSICMD;
        !           319:        r->cmd.targ = (sxp->targ << 5) | sxp->lu;
        !           320:        bcopy(sxp->cmd, &r->cmd.scb, sxp->cmdlen<12 ? sxp->cmdlen : 12);
        !           321:        p2x(&r->cmd.len[0], sxp->datalen);
        !           322:        p2x(&r->cmd.data[0], sxp->datalen ? KVTOPHYS(sxp->data) : 0);
        !           323:        r->cmd.write = (sxp->flags&SCSI_DATA_IN)? 0x80 : 0x00;
        !           324:        p2x(&r->cmd.next[0], KVTOPHYS(&r->sense));
        !           325: 
        !           326:        bzero(&r->sense, sizeof r->sense);
        !           327:        r->sense.cmd = r->cmd.cmd;
        !           328:        r->sense.targ = r->cmd.targ;
        !           329:        r->sense.scb.opcode = REQUEST_SENSE;
        !           330:        p2x(&r->sense.data[0], KVTOPHYS(&sxp->sense));
        !           331:        p2x(&r->sense.len[0], sizeof sxp->sense);
        !           332:        r->sense.write = 0x80;
        !           333: 
        !           334:        /*printf("wdscmd: ");
        !           335:        for(i=0, p=(u_char *)&r->cmd; i<sizeof r->cmd; i++)
        !           336:                printf("%02x ", p[i]);
        !           337:        printf("\n");*/
        !           338: 
        !           339:        if(sxp->flags & SCSI_NOMASK) {
        !           340:                outb(base+WDS_HCR, WDSH_DRQEN);
        !           341:                r->polled = 1;
        !           342:        } else
        !           343:                r->polled = 0;
        !           344: 
        !           345:        c = WDSC_MSTART(r->ombn);
        !           346:        if( wds_cmd(base, &c, sizeof c) != 0) {
        !           347:                printf("wds%d: unable to start outgoing mbox\n", unit);
        !           348:                r->busy = 0;
        !           349:                /* XXX need to free mailbox */
        !           350:                return TRY_AGAIN_LATER;
        !           351:        }
        !           352: 
        !           353:        DELAY(10000);
        !           354:        /*printf("%08x/%08x mbox: %02x %02x %02x %02x\n", &r->cmd, KVTOPHYS(&r->cmd),
        !           355:                wds[unit].ombs[r->ombn].stat, wds[unit].ombs[r->ombn].addr[0],
        !           356:                wds[unit].ombs[r->ombn].addr[1], wds[unit].ombs[r->ombn].addr[2]);*/
        !           357: 
        !           358:        if(sxp->flags & SCSI_NOMASK) {
        !           359: repoll:                printf("wds%d: polling.", unit);
        !           360:                i = 0;
        !           361:                while( (inb(base+WDS_STAT) & WDS_IRQ) == 0) {
        !           362:                        printf(".");
        !           363:                        DELAY(10000);
        !           364:                        if(++i == 10) {
        !           365:                                printf("failed %02x\n", inb(base+WDS_IRQSTAT));
        !           366:                                /*r->busy = 0;*/
        !           367:                                sxp->error = XS_TIMEOUT;
        !           368:                                return HAD_ERROR;
        !           369:                        }
        !           370:                }
        !           371:                printf("got one!\n");
        !           372:                wdsintr(unit);
        !           373:                if(r->done) {
        !           374:                        r->sxp->flags |= ITSDONE;
        !           375:                        if(r->sxp->when_done)
        !           376:                                (*r->sxp->when_done)(r->sxp->done_arg,
        !           377:                                        r->sxp->done_arg2);
        !           378:                        r->busy = 0;
        !           379:                        return r->ret;
        !           380:                }
        !           381:                goto repoll;
        !           382:        }
        !           383: 
        !           384:        outb(base+WDS_HCR, WDSH_IRQEN|WDSH_DRQEN);
        !           385:        printf("wds%d: successfully queued\n", unit);
        !           386:        return SUCCESSFULLY_QUEUED;
        !           387: }
        !           388: 
        !           389: long
        !           390: wds_adapter_info(unit)
        !           391: int unit;
        !           392: {
        !           393:        return 1;
        !           394: }
        !           395: 
        !           396: int
        !           397: wdsintr(unit)
        !           398: {
        !           399:        struct wds_cmd *pc, *vc;
        !           400:        struct wds_mb *in;
        !           401:        u_char stat;
        !           402:        u_char c;
        !           403: 
        !           404:        /*printf("stat=%02x\n", inb(wds[unit].addr + WDS_STAT));*/
        !           405:        DELAY(1000);
        !           406:        c = inb(wds[unit].addr + WDS_IRQSTAT);
        !           407:        printf("wdsintr: %02x\n", c);
        !           408:        if( (c&WDSI_MASK) == WDSI_MSVC) {
        !           409:                DELAY(1000);
        !           410:                c = c & ~WDSI_MASK;
        !           411:                in = &wds[unit].imbs[c];
        !           412: 
        !           413:                printf("incoming mailbox %02x@%08x: ", c, in);
        !           414:                printf("%02x %02x %02x %02x\n",
        !           415:                        in->stat, in->addr[0], in->addr[1], in->addr[2]);
        !           416:                pc = (struct wds_cmd *)x2p(&in->addr[0]);
        !           417:                vc = (struct wds_cmd *)PHYSTOKV(pc);
        !           418:                stat = in->stat;
        !           419:                printf("p=%08x v=%08x stat %02xx\n", pc, vc, stat);
        !           420:                wds_done(unit, vc, stat);
        !           421:                in->stat = 0;
        !           422: 
        !           423:                outb(wds[unit].addr + WDS_IRQACK, 0xff);
        !           424:        }
        !           425: }
        !           426: 
        !           427: wds_done(unit, c, stat)
        !           428: int unit;
        !           429: struct wds_cmd *c;
        !           430: u_char stat;
        !           431: {
        !           432:        struct wds_req *r;
        !           433:        int i;
        !           434: 
        !           435:        r = (struct wds_req *)NULL;
        !           436:        for(i=0; i<MAXSIMUL; i++)
        !           437:                if( c == &wds[unit].wdsr[i].cmd ) {
        !           438:                        /*printf("found at req slot %d\n", i);*/
        !           439:                        r = &wds[unit].wdsr[i];
        !           440:                        break;
        !           441:                }
        !           442:        if(r == (struct wds_req *)NULL) {
        !           443:                printf("failed to find request!\n");
        !           444:                return;
        !           445:        }
        !           446: 
        !           447:        printf("wds%d: cmd %8x stat %2x/%2x %2x/%2x\n", unit, c,
        !           448:                r->cmd.stat, r->cmd.venderr, r->sense.stat, r->sense.venderr);
        !           449: 
        !           450:        r->done = 1;
        !           451:        /* XXX need to free mailbox */
        !           452:        r->ret = HAD_ERROR;
        !           453:        switch(r->cmd.stat) {
        !           454:        case ICMB_OK:
        !           455:                /*XXX r->sxp->sense.valid = 0;
        !           456:                r->sxp->error = 0;*/
        !           457:                r->ret = COMPLETE;
        !           458:                break;
        !           459:        case ICMB_OKERR:
        !           460:                printf("scsi err %02x\n", c->venderr);
        !           461:                /*XXX r->sxp->sense.error_code = c->venderr;
        !           462:                r->sxp->sense.valid = 1;*/
        !           463:                r->ret = COMPLETE;
        !           464:                break;
        !           465:        case ICMB_ETIME:
        !           466:                r->sxp->error = XS_TIMEOUT;
        !           467:                r->ret = HAD_ERROR;
        !           468:                break;
        !           469:        case ICMB_ERESET:
        !           470:        case ICMB_ETARCMD:
        !           471:        case ICMB_ERESEL:
        !           472:        case ICMB_ESEL:
        !           473:        case ICMB_EABORT:
        !           474:        case ICMB_ESRESET:
        !           475:        case ICMB_EHRESET:
        !           476:                r->sxp->error = XS_DRIVER_STUFFUP;
        !           477:                r->ret = HAD_ERROR;
        !           478:                break;
        !           479:        }
        !           480:        if(r->polled==0) {
        !           481:                r->sxp->flags |= ITSDONE;
        !           482:                if(r->sxp->when_done)
        !           483:                        (*r->sxp->when_done)(r->sxp->done_arg, r->sxp->done_arg2);
        !           484:                r->busy = 0;
        !           485:        }
        !           486:        return;
        !           487: }
        !           488: 
        !           489: int
        !           490: wdsattach(dev)
        !           491: struct isa_device *dev;
        !           492: {
        !           493:        int unit = dev->id_unit;
        !           494: 
        !           495:        /*printf("start attach...\n");*/
        !           496:        scsi_attachdevs(unit, wds[unit].devs, &wds_switch);
        !           497:        /*printf("done attach...\n");*/
        !           498:        return;
        !           499: }
        !           500: 
        !           501: wds_init(dev)
        !           502: struct isa_device *dev;
        !           503: {
        !           504:        struct wds_setup init;
        !           505:        u_short base;
        !           506:        u_char *p, c;
        !           507:        int unit, i;
        !           508: 
        !           509:        unit = dev->id_unit;
        !           510:        base = wds[unit].addr;
        !           511: 
        !           512:        /*
        !           513:         * Sending a command causes the CMDRDY bit to clear.
        !           514:         */
        !           515:        c = inb(base+WDS_STAT);
        !           516:        for(i=0; i<4; i++)
        !           517:                if( (inb(base+WDS_STAT) & WDS_RDY) != 0) {
        !           518:                        goto ready;
        !           519:                DELAY(10);
        !           520:        }
        !           521:        return 1;
        !           522: 
        !           523: ready:
        !           524:        outb(base+WDS_CMD, WDSC_NOOP);
        !           525:        if( inb(base+WDS_STAT) & WDS_RDY)
        !           526:                return 1;
        !           527: 
        !           528:        /*
        !           529:         * the controller exists. reset and init.
        !           530:         */
        !           531:        outb(base+WDS_HCR, WDSH_SCSIRESET|WDSH_ASCRESET);
        !           532:        DELAY(3);
        !           533:        outb(base+WDS_HCR, WDSH_DRQEN);
        !           534:        DELAY(20000);
        !           535: 
        !           536:        isa_dmacascade(dev->id_drq);
        !           537: 
        !           538:        if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY) {
        !           539:                printf("wds%d: waiting for controller to become ready", unit);
        !           540:                for(i=0; i<6; i++) {
        !           541:                        if( (inb(base+WDS_STAT) & (WDS_RDY)) == WDS_RDY)
        !           542:                                break;
        !           543:                        printf(".");
        !           544:                        DELAY(10000);
        !           545:                }
        !           546:                if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY) {
        !           547:                        printf("failed\n");
        !           548:                        return 1;
        !           549:                }
        !           550:        }
        !           551: 
        !           552:        bzero(&init, sizeof init);
        !           553:        init.cmd = WDSC_INIT;
        !           554:        init.scsi_id = 0;
        !           555:        init.buson_t = 24;
        !           556:        init.busoff_t = 48;
        !           557:        p2x(&init.mbaddr[0], KVTOPHYS(&wds[unit].ombs[0]));
        !           558:        init.xx = 0;
        !           559:        init.nomb = WDS_NOMB;
        !           560:        init.nimb = WDS_NIMB;
        !           561: 
        !           562:        /*p = (u_char *)&init;
        !           563:        printf("wds%d: %08x %08x init: ", unit,
        !           564:                &wds[unit].ombs[0], KVTOPHYS(&wds[unit].ombs[0]));
        !           565:        for(i=0; i<sizeof init; i++)
        !           566:                printf("%02x ", p[i]);
        !           567:        printf("\n");*/
        !           568: 
        !           569:        wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY);
        !           570:        if( wds_cmd(base, &init, sizeof init) != 0) {
        !           571:                printf("wds%d: wds_cmd failed\n", unit);
        !           572:                return 1;
        !           573:        }
        !           574:        wds_wait(base+WDS_STAT, WDS_INIT, WDS_INIT);
        !           575: 
        !           576:        wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY);
        !           577:        c = WDSC_DISUNSOL;
        !           578:        if( wds_cmd(base, &c, sizeof c) != 0) {
        !           579:                printf("wds%d: wds_cmd failed\n", unit);
        !           580:                return 1;
        !           581:        }
        !           582: 
        !           583:        return 0;
        !           584: }
        !           585: 
        !           586: wds_cmd(base, p, l)
        !           587: u_short base;
        !           588: u_char *p;
        !           589: int l;
        !           590: {
        !           591:        int i;
        !           592:        u_char c;
        !           593: 
        !           594:        i = 0;
        !           595:        while(i < l) {
        !           596:                while( ((c=inb(base+WDS_STAT)) & WDS_RDY) == 0)
        !           597:                        ;
        !           598: 
        !           599:                outb(base+WDS_CMD, *p);
        !           600: 
        !           601:                while( ((c=inb(base+WDS_STAT)) & WDS_RDY) == 0)
        !           602:                        ;
        !           603: 
        !           604:                if(c & WDS_REJ)
        !           605:                        return 1;
        !           606:                p++;
        !           607:                i++;
        !           608:        }
        !           609:        while( ((c=inb(base+WDS_STAT)) & WDS_RDY) == 0)
        !           610:                ;
        !           611:        if(c & WDS_REJ)
        !           612:                return 1;
        !           613:        /*printf("wds_cmd: %02x\n", inb(base+WDS_STAT));*/
        !           614:        return 0;
        !           615: }
        !           616: 
        !           617: wds_wait(reg, mask, val)
        !           618: {
        !           619:        while( (inb(reg) & mask) != val)
        !           620:                ;
        !           621: }
        !           622: 
        !           623: #endif

unix.superglobalmegacorp.com

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