From bedca0009aa4bb013ea29410ab644c2dd5d865a0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 16 Oct 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-10-16 --- pc/audio.h | 6 +- pc/devusb.c | 48 +++-- pc/ether82557.c | 1 + pc/etherwavelan.c | 484 ++++++++++++++++++++++++++++++++-------------- port/devaudio.c | 4 +- 5 files changed, 366 insertions(+), 177 deletions(-) diff --git a/pc/audio.h b/pc/audio.h index fb11b11158579377fa7ae1f69af9776e426482c0..37cd27cd0b99731ef47ee1985da8a47e2564135a 100644 --- a/pc/audio.h +++ b/pc/audio.h @@ -1,10 +1,10 @@ enum { - Bufsize = 16*1024, /* 92 ms each */ - Nbuf = 16, /* 1.5 seconds total */ + Bufsize = 4*1024, /* 23.22 ms each */ + Nbuf = 32, /* .74 seconds total */ Dma = 6, IrqAUDIO = 7, - SBswab = 0, + SBswab = 0, }; #define seteisadma(a, b) dmainit(a, Bufsize); diff --git a/pc/devusb.c b/pc/devusb.c index 4522e21ab95f78031d4c7f78f1a27971eaca6ef4..ca7913376a6be2d71bd4bd1847f42db60206d39f 100644 --- a/pc/devusb.c +++ b/pc/devusb.c @@ -206,7 +206,7 @@ struct Endpt { int data01; /* 0=DATA0, 1=DATA1 */ uchar eof; ulong csp; - uchar isopen; /* ep operations forbidden on open endpoints */ +/* uchar isopen; ep operations forbidden on open endpoints */ uchar mode; /* OREAD, OWRITE, ORDWR */ uchar nbuf; /* number of buffers allowed */ uchar iso; @@ -645,6 +645,7 @@ eptactivate(Endpt *e) { ilock(&activends); if(e->active == 0){ + XPRINT("activate 0x%p\n", e); e->active = 1; e->activef = activends.f; activends.f = e; @@ -661,6 +662,7 @@ eptdeactivate(Endpt *e) ilock(&activends); if(e->active){ e->active = 0; + XPRINT("deactivate 0x%p\n", e); for(l = &activends.f; *l != e; l = &(*l)->activef) if(*l == nil){ iunlock(&activends); @@ -808,7 +810,7 @@ schedendpt(Endpt *e) return 0; ub = &ubus; - if (e->isopen){ + if (e->active){ return -1; } e->off = 0; @@ -1445,7 +1447,7 @@ usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp) /* * Top level directory contains the name of the device. */ - if(c->qid.path == Qtopdir){ + if(QID(c->qid) == Qtopdir){ if(s == DEVDOTDOT){ mkqid(&q, Qtopdir, 0, QTDIR); devdir(c, q, "#U", 0, eve, 0555, dp); @@ -1544,6 +1546,7 @@ usbopen(Chan *c, int omode) f = 0; if(QID(c->qid) == Qnew){ d = usbnewdevice(); + XPRINT("usbopen, new dev 0x%p\n", d); if(d == nil) { XPRINT("usbopen failed (usbnewdevice)\n"); error(Enodev); @@ -1553,8 +1556,10 @@ usbopen(Chan *c, int omode) f = 1; } - if(c->qid.path < Q3rd) + if(QID(c->qid) < Q3rd){ + XPRINT("usbopen, devopen < Q3rd\n"); return devopen(c, omode, nil, 0, usbgen); + } qlock(&usbstate); if(waserror()){ @@ -1570,24 +1575,26 @@ usbopen(Chan *c, int omode) d->busy = 1; if(!f) incref(d); + XPRINT("usbopen, Qctl 0x%p\n", d); break; default: d = usbdevice(c); s = QID(c->qid) - Qep0; + XPRINT("usbopen, default 0x%p, %d\n", d, s); if(s >= 0 && s < nelem(d->ep)){ Endpt *e; if((e = d->ep[s]) == nil) { XPRINT("usbopen failed (endpoint)\n"); error(Enodev); } + XPRINT("usbopen: dev 0x%p, ept 0x%p\n", d, e); if(schedendpt(e) < 0){ - if (e->isopen) - error("can't schedule USB endpoint, isopen"); + if (e->active) + error("can't schedule USB endpoint, active"); else error("can't schedule USB endpoint"); } - e->isopen++; eptactivate(e); } incref(d); @@ -1625,27 +1632,17 @@ void usbclose(Chan *c) { Udev *d; - int s; - if(c->qid.type == QTDIR || c->qid.path < Q3rd) + if(c->qid.type == QTDIR || QID(c->qid) < Q3rd) return; qlock(&usbstate); d = usbdevice(c); - s = QID(c->qid) - Qep0; - if(s >= 0 && s < nelem(d->ep)){ - Endpt *e; - if(e = d->ep[s]) { - if (e->isopen == 1){ - e->isopen = 0; - eptdeactivate(e); - unschedendpt(e); - } - } - } if(QID(c->qid) == Qctl) d->busy = 0; - if(c->flag & COPEN) + if(c->flag & COPEN){ + XPRINT("usbclose: freedev 0x%p\n", d); freedev(d); + } qunlock(&usbstate); } @@ -1858,13 +1855,12 @@ epstatus(char *s, int n, Endpt *e, int i) int l; l = 0; - l += snprint(s+l, n-l, "%2d %#6.6lux %10lud bytes %10lud blocks", + l += snprint(s+l, n-l, "%2d %#6.6lux %10lud bytes %10lud blocks\n", i, e->csp, e->nbytes, e->nblocks); if (e->iso && e->toffset){ - l += snprint(s+l, n-l, " %6d buffered %10lud offset %19lld time", - e->buffered, e->toffset, e->time); + l += snprint(s+l, n-l, "bufsize %6d buffered %6d offset %10lud time %19lld\n", + e->maxpkt, e->buffered, e->toffset, e->time); } - l += snprint(s+l, n-l, "\n"); return l; } @@ -2103,7 +2099,7 @@ usbwrite(Chan *c, void *a, long n, vlong offset) qunlock(&usbstate); nexterror(); } - if (e->isopen) + if (e->active) error(Eperm); if(strcmp(fields[2], "bulk") == 0){ Ctlr *ub; diff --git a/pc/ether82557.c b/pc/ether82557.c index f5bba26dc5d8d8c190729e624900ddb0cc6775f0..aa31b3b486f7e3ab692caa879e1f7eab50392a25 100644 --- a/pc/ether82557.c +++ b/pc/ether82557.c @@ -904,6 +904,7 @@ i82557pci(void) continue; case 0x1229: /* Intel 8255[789] */ case 0x1031: /* Intel 82562EM */ + case 0x2449: /* Intel ????? */ break; } diff --git a/pc/etherwavelan.c b/pc/etherwavelan.c index 6dda6d1ce4710cd93607ec4ce67e95a427749364..1a462eaf11c6aa4786ce7af7e29f6a850c8fe215 100644 --- a/pc/etherwavelan.c +++ b/pc/etherwavelan.c @@ -27,67 +27,10 @@ #include "../port/netif.h" #include "etherif.h" -#define DEBUG if(1)print +#define DEBUG if(0){}else print #define SEEKEYS 0 -typedef struct Ctlr Ctlr; -typedef struct Wltv Wltv; -typedef struct WFrame WFrame; -typedef struct Stats Stats; -typedef struct WStats WStats; -typedef struct WKey WKey; - -struct WStats -{ - ulong ntxuframes; // unicast frames - ulong ntxmframes; // multicast frames - ulong ntxfrags; // fragments - ulong ntxubytes; // unicast bytes - ulong ntxmbytes; // multicast bytes - ulong ntxdeferred; // deferred transmits - ulong ntxsretries; // single retries - ulong ntxmultiretries; // multiple retries - ulong ntxretrylimit; - ulong ntxdiscards; - ulong nrxuframes; // unicast frames - ulong nrxmframes; // multicast frames - ulong nrxfrags; // fragments - ulong nrxubytes; // unicast bytes - ulong nrxmbytes; // multicast bytes - ulong nrxfcserr; - ulong nrxdropnobuf; - ulong nrxdropnosa; - ulong nrxcantdecrypt; - ulong nrxmsgfrag; - ulong nrxmsgbadfrag; - ulong end; -}; - -struct WFrame -{ - ushort sts; - ushort rsvd0; - ushort rsvd1; - ushort qinfo; - ushort rsvd2; - ushort rsvd3; - ushort txctl; - ushort framectl; - ushort id; - uchar addr1[Eaddrlen]; - uchar addr2[Eaddrlen]; - uchar addr3[Eaddrlen]; - ushort seqctl; - uchar addr4[Eaddrlen]; - ushort dlen; - uchar dstaddr[Eaddrlen]; - uchar srcaddr[Eaddrlen]; - ushort len; - ushort dat[3]; - ushort type; -}; - // Lucent's Length-Type-Value records to talk to the wavelan. // most operational parameters are read/set using this. enum @@ -191,6 +134,9 @@ enum WR_Data0 = 0x36, WR_Data1 = 0x38, + WR_PciCor = 0x26, + WR_PciHcr = 0x2E, + // Frame stuff WF_Err = 0x0003, @@ -212,9 +158,62 @@ enum }; -#define csr_outs(ctlr,r,arg) outs((ctlr)->iob+(r),(arg)) -#define csr_ins(ctlr,r) ins((ctlr)->iob+(r)) -#define csr_ack(ctlr,ev) outs((ctlr)->iob+WR_EvAck,(ev)) +typedef struct Ctlr Ctlr; +typedef struct Wltv Wltv; +typedef struct WFrame WFrame; +typedef struct Stats Stats; +typedef struct WStats WStats; +typedef struct WKey WKey; + +struct WStats +{ + ulong ntxuframes; // unicast frames + ulong ntxmframes; // multicast frames + ulong ntxfrags; // fragments + ulong ntxubytes; // unicast bytes + ulong ntxmbytes; // multicast bytes + ulong ntxdeferred; // deferred transmits + ulong ntxsretries; // single retries + ulong ntxmultiretries; // multiple retries + ulong ntxretrylimit; + ulong ntxdiscards; + ulong nrxuframes; // unicast frames + ulong nrxmframes; // multicast frames + ulong nrxfrags; // fragments + ulong nrxubytes; // unicast bytes + ulong nrxmbytes; // multicast bytes + ulong nrxfcserr; + ulong nrxdropnobuf; + ulong nrxdropnosa; + ulong nrxcantdecrypt; + ulong nrxmsgfrag; + ulong nrxmsgbadfrag; + ulong end; +}; + +struct WFrame +{ + ushort sts; + ushort rsvd0; + ushort rsvd1; + ushort qinfo; + ushort rsvd2; + ushort rsvd3; + ushort txctl; + ushort framectl; + ushort id; + uchar addr1[Eaddrlen]; + uchar addr2[Eaddrlen]; + uchar addr3[Eaddrlen]; + ushort seqctl; + uchar addr4[Eaddrlen]; + ushort dlen; + uchar dstaddr[Eaddrlen]; + uchar srcaddr[Eaddrlen]; + ushort len; + ushort dat[3]; + ushort type; +}; struct WKey { @@ -252,6 +251,7 @@ struct Wltv struct Stats { ulong nints; + ulong ndoubleint; ulong nrx; ulong ntx; ulong ntxrq; @@ -303,10 +303,75 @@ struct Ctlr int ctlrno; + /* for PCI-based devices */ + Ctlr *next; + ushort *mmb; + int active; + Pcidev *pcidev; + Stats; WStats; }; +/* + * When we're using a PCI device and memory-mapped I/O, + * the registers are spaced out as though each takes 32 bits, + * even though they are only 16-bit registers. Thus, + * ctlr->mmb[reg] is the right way to access register reg, + * even though a priori you'd expect to use ctlr->mmb[reg/2]. + */ +static void +csr_outs(Ctlr *ctlr, int reg, ushort arg) +{ + if(ctlr->mmb) + ctlr->mmb[reg] = arg; + else + outs(ctlr->iob+reg, arg); +} + +static ushort +csr_ins(Ctlr *ctlr, int reg) +{ + if(ctlr->mmb) + return ctlr->mmb[reg]; + else + return ins(ctlr->iob+reg); +} + +static void +csr_ack(Ctlr *ctlr, int ev) +{ + csr_outs(ctlr, WR_EvAck, ev); +} + +static void +csr_inss(Ctlr *ctlr, int reg, void *dat, int ndat) +{ + ushort *rp, *wp; + + if(ctlr->mmb){ + rp = &ctlr->mmb[reg]; + wp = dat; + while(ndat-- > 0) + *wp++ = *rp; + }else + inss(ctlr->iob+reg, dat, ndat); +} + +static void +csr_outss(Ctlr *ctlr, int reg, void *dat, int ndat) +{ + ushort *rp, *wp; + + if(ctlr->mmb){ + rp = dat; + wp = &ctlr->mmb[reg]; + while(ndat-- > 0) + *wp = *rp++; + }else + outss(ctlr->iob+reg, dat, ndat); +} + // w_... routines do not ilock the Ctlr and should // be called locked. @@ -343,16 +408,36 @@ w_cmd(Ctlr *ctlr, ushort cmd, ushort arg) if(csr_ins(ctlr, WR_EvSts)&WCmdEv) break; if(i==WTmOut){ - print("#l%d: execing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_EvSts)); - return -1; + /* + * WCmdIni can take a really long time. + */ + enum { IniTmOut = 2000 }; + for(i=0; ictlrno, cmd, i); + if(i == IniTmOut){ + print("#l%d: execing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_EvSts)); + return -1; + } } rc = csr_ins(ctlr, WR_Sts); csr_ack(ctlr, WCmdEv); - if((rc&WCmdMsk) != (cmd&WCmdMsk) || (rc&WResSts)){ + if((rc&WCmdMsk) != (cmd&WCmdMsk)){ print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc); return -1; } + if(rc&WResSts){ + /* + * Don't print; this happens on every WCmdAccWr for some reason. + */ + if(0) print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc); + return -1; + } return 0; } @@ -398,7 +483,7 @@ w_inltv(Ctlr* ctlr, Wltv* ltv) return -1; } if(ltv->len > 0) - inss((ctlr)->iob+(WR_Data1), <v->val, ltv->len-1); + csr_inss(ctlr, WR_Data1, <v->val, ltv->len-1); return 0; } @@ -408,7 +493,7 @@ w_outltv(Ctlr* ctlr, Wltv* ltv) { if(w_seek(ctlr,ltv->type, 0, 1)) return; - outss((ctlr)->iob+(WR_Data1), ltv, ltv->len+1); + csr_outss(ctlr, WR_Data1, ltv, ltv->len+1); w_cmd(ctlr, WCmdAccWr, ltv->type); } @@ -486,7 +571,7 @@ w_read(Ctlr* ctlr, int type, int off, void* buf, ulong len) DEBUG("wavelan: w_read: seek failed"); return 0; } - inss((ctlr)->iob+(WR_Data1), buf, len/2); + csr_inss(ctlr, WR_Data1, buf, len/2); return len; } @@ -502,7 +587,7 @@ w_write(Ctlr* ctlr, int type, int off, void* buf, ulong len) return 0; } - outss((ctlr)->iob+(WR_Data0), buf, len/2); + csr_outss(ctlr, WR_Data0, buf, len/2); csr_outs(ctlr, WR_Data0, 0xdead); csr_outs(ctlr, WR_Data0, 0xbeef); @@ -763,10 +848,8 @@ w_intr(Ether *ether) return; } - csr_outs(ctlr, WR_IntEna, 0); rc = csr_ins(ctlr, WR_EvSts); - csr_ack(ctlr, ~WEvs); // Not interested on them - + csr_ack(ctlr, ~WEvs); // Not interested in them if (rc & WRXEv){ w_rxdone(ether); csr_ack(ctlr, WRXEv); @@ -797,8 +880,6 @@ w_intr(Ether *ether) ctlr->nidrop++; csr_ack(ctlr, WIDropEv); } - - w_intena(ctlr); w_txstart(ether); } @@ -821,7 +902,7 @@ w_timer(void* arg) continue; ctlr->ticks++; - ilock(&ctlr->Lock); + ilock(ctlr); // Seems that the card gets frames BUT does // not send the interrupt; this is a problem because @@ -838,10 +919,10 @@ w_timer(void* arg) // the card frames in the wrong way; due to the // lack of documentation I cannot know. -// if (csr_ins(ctlr, WR_EvSts)&WEvs){ -// ctlr->tickintr++; -// w_intr(ether); -// } + if (csr_ins(ctlr, WR_EvSts)&WEvs){ + ctlr->tickintr++; + w_intr(ether); + } if ((ctlr->ticks % 10) == 0) { if (ctlr->txtmout && --ctlr->txtmout == 0){ @@ -856,7 +937,7 @@ w_timer(void* arg) if (ctlr->txbusy == 0) w_cmd(ctlr, WCmdAskStats, WTyp_Stats); } - iunlock(&ctlr->Lock); + iunlock(ctlr); } pexit("terminated",0); } @@ -880,9 +961,9 @@ attach(Ether* ether) snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno); ctlr = (Ctlr*) ether->ctlr; if (ctlr->attached == 0){ - ilock(&ctlr->Lock); + ilock(ctlr); rc = w_enable(ether); - iunlock(&ctlr->Lock); + iunlock(ctlr); if(rc == 0){ ctlr->attached = 1; kproc(name, w_timer, ether); @@ -921,6 +1002,7 @@ ifstat(Ether* ether, void* a, long n, ulong offset) PRINTSTAT("Noise: %d\n", ctlr->noise-149); PRINTSTAT("SNR: %ud\n", ctlr->signal-ctlr->noise); PRINTSTAT("Interrupts: %lud\n", ctlr->nints); + PRINTSTAT("Double Interrupts: %lud\n", ctlr->ndoubleint); PRINTSTAT("TxPackets: %lud\n", ctlr->ntx); PRINTSTAT("RxPackets: %lud\n", ctlr->nrx); PRINTSTAT("TxErrors: %lud\n", ctlr->ntxerr); @@ -951,7 +1033,7 @@ ifstat(Ether* ether, void* a, long n, ulong offset) } // real card stats - ilock(&ctlr->Lock); + ilock(ctlr); PRINTSTR("\nCard stats: \n"); PRINTSTAT("Status: %ux\n", csr_ins(ctlr, WR_Sts)); PRINTSTAT("Event status: %ux\n", csr_ins(ctlr, WR_EvSts)); @@ -990,7 +1072,7 @@ ifstat(Ether* ether, void* a, long n, ulong offset) PRINTSTAT("Transmit key id: %d\n", txid); } } - iunlock(&ctlr->Lock); + iunlock(ctlr); PRINTSTAT("ntxuframes: %lud\n", ctlr->ntxuframes); PRINTSTAT("ntxmframes: %lud\n", ctlr->ntxmframes); @@ -1142,16 +1224,16 @@ ctl(Ether* ether, void* buf, long n) if(ctlr->attached == 0) error(Eshutdown); - ilock(&ctlr->Lock); + ilock(ctlr); if(option(ctlr, buf, n)){ - iunlock(&ctlr->Lock); + iunlock(ctlr); error(Ebadctl); } if(ctlr->txbusy) w_txdone(ctlr, WTxErrEv); w_enable(ether); w_txstart(ether); - iunlock(&ctlr->Lock); + iunlock(ctlr); return n; } @@ -1164,10 +1246,10 @@ transmit(Ether* ether) if (ctlr == 0) return; - ilock(&ctlr->Lock); + ilock(ctlr); ctlr->ntxrq++; w_txstart(ether); - iunlock(&ctlr->Lock); + iunlock(ctlr); } static void @@ -1180,9 +1262,9 @@ promiscuous(void* arg, int on) error("card not found"); if (ctlr->attached == 0) error("card not attached"); - ilock(&ctlr->Lock); + ilock(ctlr); ltv_outs(ctlr, WTyp_Prom, (on?1:0)); - iunlock(&ctlr->Lock); + iunlock(ctlr); } static void @@ -1193,10 +1275,10 @@ interrupt(Ureg* ,void* arg) if (ctlr == 0) return; - ilock(&ctlr->Lock); + ilock(ctlr); ctlr->nints++; w_intr(ether); - iunlock(&ctlr->Lock); + iunlock(ctlr); } static char* wavenames[] = { @@ -1207,57 +1289,16 @@ static char* wavenames[] = { }; static int -reset(Ether* ether) +genreset(Ether* ether, Ctlr *ctlr) { int i; + char *p; Wltv ltv; - Ctlr* ctlr; - char *name, *p; - - if((ctlr = malloc(sizeof(Ctlr))) == nil) - return -1; - - ilock(&ctlr->Lock); - ctlr->ctlrno = ether->ctlrno; - - if (ether->port==0) - ether->port=WDfltIOB; - ctlr->iob = ether->port; - if (ether->irq==0) - ether->irq=WDfltIRQ; - - if (ioalloc(ether->port,WIOLen,0,"wavelan")<0){ - print("#l%d: port 0x%lx in use\n", - ether->ctlrno, ether->port); - goto abort1; - } - - for (i=0; wavenames[i]; i++) - if ((ctlr->slot = pcmspecial(wavenames[i], ether))>=0) - break; - name = wavenames[i]; - - if (name == nil){ - for (i=0; inopt; i++){ - if (cistrncmp(ether->opt[i], "id=", 3) == 0){ - name = ðer->opt[i][3]; - if ((ctlr->slot = pcmspecial(name, ether)) < 0) - name = nil; - } - } - if (name == nil){ - DEBUG("no wavelan found\n"); - goto abort; - } - } - - // DEBUG("#l%d: port=0x%lx irq=%ld\n", - // ether->ctlrno, ether->port, ether->irq); w_intdis(ctlr); if (w_cmd(ctlr,WCmdIni,0)){ print("#l%d: init failed\n", ether->ctlrno); - goto abort; + return -1; } w_intdis(ctlr); ltv_outs(ctlr, WTyp_Tick, 8); @@ -1288,7 +1329,7 @@ reset(Ether* ether) if (w_inltv(ctlr, <v)){ print("#l%d: unable to read mac addr\n", ether->ctlrno); - goto abort; + return -1; } memmove(ether->ea, ltv.addr, Eaddrlen); @@ -1321,20 +1362,171 @@ reset(Ether* ether) // ether->ea[0], ether->ea[1], ether->ea[2], // ether->ea[3], ether->ea[4], ether->ea[5]); - iunlock(&ctlr->Lock); return 0; +} -abort: - iofree(ether->port); -abort1: - iunlock(&ctlr->Lock); - free(ctlr); - ether->ctlr = nil; - return -1; +static int +wavelanpcmciareset(Ether *ether) +{ + int i; + Ctlr *ctlr; + + if((ctlr = malloc(sizeof(Ctlr))) == nil) + return -1; + + ilock(ctlr); + ctlr->ctlrno = ether->ctlrno; + + if (ether->port==0) + ether->port=WDfltIOB; + ctlr->iob = ether->port; + if (ether->irq==0) + ether->irq=WDfltIRQ; + + if (ioalloc(ether->port,WIOLen,0,"wavelan")<0){ + print("#l%d: port 0x%lx in use\n", + ether->ctlrno, ether->port); + goto abort1; + } + + /* + * If id= is specified, card must match. Otherwise try generic. + */ + ctlr->slot = -1; + for(i=0; inopt; i++){ + if(cistrncmp(ether->opt[i], "id=", 3) == 0){ + if((ctlr->slot = pcmspecial(ðer->opt[i][3], ether)) < 0) + return -1; + break; + } + } + if(ctlr->slot == -1){ + for (i=0; wavenames[i]; i++) + if((ctlr->slot = pcmspecial(wavenames[i], ether))>=0) + break; + if(!wavenames[i]){ + DEBUG("no wavelan found\n"); + goto abort; + } + } + + // DEBUG("#l%d: port=0x%lx irq=%ld\n", + // ether->ctlrno, ether->port, ether->irq); + + if(genreset(ether, ctlr) < 0){ + abort: + iofree(ether->port); + abort1: + iunlock(ctlr); + free(ctlr); + ether->ctlr = nil; + return -1; + } + iunlock(ctlr); + return 0; } +static struct { + int vid; + int did; +} wavelanpci[] = { + 0x1260, 0x3873, /* Intersil Prism2.5 */ +}; + +static Ctlr *ctlrhead, *ctlrtail; + +static void +wavelanpciscan(void) +{ + int i; + ulong pa; + Pcidev *p; + Ctlr *ctlr; + + p = nil; + while(p = pcimatch(p, 0, 0)){ + for(i=0; ivid == wavelanpci[i].vid && p->did == wavelanpci[i].did) + break; + if(i==nelem(wavelanpci)) + continue; + + /* + * On the Prism, bar[0] is the memory-mapped register address (4KB), + */ + if(p->mem[0].size != 4096){ + print("wavelanpci: %.4ux %.4ux: unlikely mmio size\n", p->vid, p->did); + continue; + } + + ctlr = malloc(sizeof(Ctlr)); + ctlr->pcidev = p; + pa = upamalloc(p->mem[0].bar&~0xF, p->mem[0].size, 0); + if(pa == 0){ + print("wavelanpci: %.4ux %.4ux: upamalloc 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size); + free(ctlr); + continue; + } + ctlr->mmb = (ushort*)KADDR(pa); + if(ctlrhead != nil) + ctlrtail->next = ctlr; + else + ctlrhead = ctlr; + ctlrtail = ctlr; + pcisetbme(p); + } +} + +static int +wavelanpcireset(Ether *ether) +{ + int i; + Ctlr *ctlr; + + if(ctlrhead == nil) + wavelanpciscan(); + + /* + * Allow plan9.ini to set vid, did? + */ + for(ctlr=ctlrhead; ctlr!=nil; ctlr=ctlr->next) + if(ctlr->active == 0) + break; + if(ctlr == nil) + return -1; + + ilock(ctlr); + ether->irq = ctlr->pcidev->intl; + ether->tbdf = ctlr->pcidev->tbdf; + + /* + * Really hard reset. + */ + csr_outs(ctlr, WR_PciCor, 0x0080); + delay(250); + csr_outs(ctlr, WR_PciCor, 0x0000); + delay(500); + for(i=0; i<2*10; i++){ + if(!(csr_ins(ctlr, WR_Cmd)&WCmdBusy)) + break; + delay(100); + } + if(i >= 2*10) + print("wavelan pci %.4ux %.4ux: reset timeout %.4ux\n", + ctlr->pcidev->vid, ctlr->pcidev->did, csr_ins(ctlr, WR_Cmd)); + + if(genreset(ether, ctlr) < 0){ + iunlock(ctlr); + ether->ctlr = nil; + return -1; + } + iunlock(ctlr); + return 0; +} + void etherwavelanlink(void) { - addethercard("wavelan", reset); + addethercard("wavelan", wavelanpcmciareset); + addethercard("wavelanpci", wavelanpcireset); } diff --git a/port/devaudio.c b/port/devaudio.c index c6b63f28300c0dd92f9495fe8d206648af347e32..80b48ec2b66d6b782d7e20874f3df3d6b419a061 100644 --- a/port/devaudio.c +++ b/port/devaudio.c @@ -1016,8 +1016,8 @@ audioread(Chan *c, void *v, long n, vlong off) case Qstatus: buf[0] = 0; - snprint(buf, sizeof(buf), "bytes %lud\ntime %lld\n", - audio.totcount, audio.tottime); + snprint(buf, sizeof(buf), "bufsize %6d buffered %6d offset %10lud time %19lld\n", + Bufsize, audio.buffered, audio.totcount, audio.tottime); return readstr(offset, a, n, buf); case Qvolume: