diff options
Diffstat (limited to 'os/boot/mpc/devether.c')
| -rw-r--r-- | os/boot/mpc/devether.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/os/boot/mpc/devether.c b/os/boot/mpc/devether.c new file mode 100644 index 00000000..5c5ac792 --- /dev/null +++ b/os/boot/mpc/devether.c @@ -0,0 +1,157 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +#include "etherif.h" + +static Ctlr ether[MaxEther]; + +static struct { + char *type; + int (*reset)(Ctlr*); +} cards[] = { + { "SCC", sccethreset, }, + { "SCC2", sccethreset, }, + { 0, } +}; + +int +etherinit(void) +{ + Ctlr *ctlr; + int ctlrno, i, mask, n; + + mask = 0; + for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){ + ctlr = ðer[ctlrno]; + memset(ctlr, 0, sizeof(Ctlr)); + if(isaconfig("ether", ctlrno, &ctlr->card) == 0) + continue; + for(n = 0; cards[n].type; n++){ + if(strcmp(cards[n].type, ctlr->card.type)) + continue; + ctlr->ctlrno = ctlrno; + if((*cards[n].reset)(ctlr)) + break; + + ctlr->iq = qopen(16*1024, 1, 0, 0); + ctlr->oq = qopen(16*1024, 1, 0, 0); + + ctlr->present = 1; + mask |= 1<<ctlrno; + + print("ether%d: %s: port 0x%luX irq %d", + ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq); + if(ctlr->card.mem) + print(" addr 0x%luX", PADDR(ctlr->card.mem)); + if(ctlr->card.size) + print(" size 0x%luX", ctlr->card.size); + print(":"); + for(i = 0; i < sizeof(ctlr->card.ea); i++) + print(" %2.2uX", ctlr->card.ea[i]); + print("\n"); uartwait(); + setvec(VectorPIC + ctlr->card.irq, ctlr->card.intr, ctlr); + break; + } + } + + return mask; +} + +static Ctlr* +attach(int ctlrno) +{ + Ctlr *ctlr; + + if(ctlrno >= MaxEther || ether[ctlrno].present == 0) + return 0; + + ctlr = ðer[ctlrno]; + if(ctlr->present == 1){ + ctlr->present = 2; + (*ctlr->card.attach)(ctlr); + } + + return ctlr; +} + +uchar* +etheraddr(int ctlrno) +{ + Ctlr *ctlr; + + if((ctlr = attach(ctlrno)) == 0) + return 0; + + return ctlr->card.ea; +} + +int +etherrxpkt(int ctlrno, Etherpkt *pkt, int timo) +{ + int n; + Ctlr *ctlr; + Block *b; + ulong start; + + if((ctlr = attach(ctlrno)) == 0) + return 0; + + start = m->ticks; + while((b = qget(ctlr->iq)) == 0){ + if(TK2MS(m->ticks - start) >= timo){ + /* + print("ether%d: rx timeout\n", ctlrno); + */ + return 0; + } + } + + n = BLEN(b); + memmove(pkt, b->rp, n); + freeb(b); + + return n; +} + +int +etheriq(Ctlr *ctlr, Block *b, int freebp) +{ + if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0 && + memcmp(((Etherpkt*)b->rp)->d, broadcast, Eaddrlen) != 0){ + if(freebp) + freeb(b); + return 0; + } + qbwrite(ctlr->iq, b); + return 1; +} + +int +ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int) +{ + Ctlr *ctlr; + Block *b; + int s; + + if((ctlr = attach(ctlrno)) == 0) + return 0; + + if(qlen(ctlr->oq) > 16*1024){ + print("ether%d: tx queue full\n", ctlrno); + return 0; + } + b = iallocb(sizeof(Etherpkt)); + memmove(b->wp, pkt, len); + memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen); + b->wp += len; + qbwrite(ctlr->oq, b); + s = splhi(); + (*ctlr->card.transmit)(ctlr); + splx(s); + + return 1; +} |
