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

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

unix.superglobalmegacorp.com

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