|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.