Annotation of Net2/arch/i386/isa/wd7000.c, revision 1.1.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.