| plan 9 kernel history: overview | file list | diff list |
1994/0629/pc/devether.c (diff list | history)
| pc/devether.c on 1992/0403 | ||
| 1992/0403 | #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" | |
| 1993/1113 | #include "ureg.h" #include "../port/error.h" #include "../port/netif.h" | |
| 1992/0403 | ||
| 1993/1113 | #include "etherif.h" | |
| 1992/1222 | ||
| 1993/1113 | static Ether *ether[MaxEther]; | |
| 1992/0403 | ||
| 1993/1113 | void etherinit(void) { } | |
| 1992/1222 | ||
| 1993/1113 | Chan* etherattach(char *spec) { ulong ctlrno; char *p; Chan *c; | |
| 1992/0404 | ||
| 1993/1113 | ctlrno = 0; if(spec && *spec){ ctlrno = strtoul(spec, &p, 0); if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther)) error(Ebadarg); } if(ether[ctlrno] == 0) error(Enodev); | |
| 1992/0403 | ||
| 1993/1113 | c = devattach('l', spec); c->dev = ctlrno; if(ether[ctlrno]->attach) (*ether[ctlrno]->attach)(ether[ctlrno]); return c; } | |
| 1992/0922 | ||
| 1992/0425 | Chan* | |
| 1992/0424 | etherclone(Chan *c, Chan *nc) | |
| 1992/0411 | { | |
| 1992/0424 | return devclone(c, nc); } | |
| 1992/0411 | ||
| 1992/0424 | int etherwalk(Chan *c, char *name) { | |
| 1993/1113 | return netifwalk(ether[c->dev], c, name); | |
| 1992/0424 | } void etherstat(Chan *c, char *dp) { | |
| 1993/1113 | netifstat(ether[c->dev], c, dp); | |
| 1992/0424 | } Chan* etheropen(Chan *c, int omode) { | |
| 1993/1113 | return netifopen(ether[c->dev], c, omode); | |
| 1992/0424 | } void ethercreate(Chan *c, char *name, int omode, ulong perm) { | |
| 1992/0711 | USED(c, name, omode, perm); | |
| 1992/0424 | } void etherclose(Chan *c) { | |
| 1993/1113 | netifclose(ether[c->dev], c); | |
| 1992/0424 | } long | |
| 1993/1113 | etherread(Chan *c, void *buf, long n, ulong offset) | |
| 1992/0424 | { | |
| 1993/1113 | return netifread(ether[c->dev], c, buf, n, offset); | |
| 1992/0411 | } | |
| 1992/0424 | void etherremove(Chan *c) { | |
| 1992/0711 | USED(c); | |
| 1992/0424 | } void etherwstat(Chan *c, char *dp) { | |
| 1993/1113 | netifwstat(ether[c->dev], c, dp); | |
| 1992/0424 | } | |
| 1993/1120 | void etherrloop(Ether *ctlr, Etherpkt *pkt, long len) { ushort type; Netfile *f, **fp, **ep; type = (pkt->type[0]<<8)|pkt->type[1]; ep = &ctlr->f[Ntypes]; for(fp = ctlr->f; fp < ep; fp++){ | |
| 1994/0202 | if((f = *fp) && (f->type == type || f->type < 0)) qproduce(f->in, pkt->d, len); | |
| 1993/1120 | } } static int etherwloop(Ether *ctlr, Etherpkt *pkt, long len) { int s, different; different = memcmp(pkt->d, pkt->s, sizeof(pkt->s)); | |
| 1994/0629 | if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d)) && ctlr->prom==0 && ctlr->all==0) | |
| 1993/1120 | return 0; s = splhi(); etherrloop(ctlr, pkt, len); splx(s); return !different; } | |
| 1993/1113 | long etherwrite(Chan *c, void *buf, long n, ulong offset) | |
| 1992/0407 | { | |
| 1993/1113 | Ether *ctlr; | |
| 1992/0407 | ||
| 1993/1113 | USED(offset); if(n > ETHERMAXTU) error(Ebadarg); ctlr = ether[c->dev]; | |
| 1992/0407 | ||
| 1993/1113 | if(NETTYPE(c->qid.path) != Ndataqid) return netifwrite(ctlr, c, buf, n); | |
| 1992/0403 | ||
| 1993/1120 | if(etherwloop(ctlr, buf, n)) return n; | |
| 1992/1222 | qlock(&ctlr->tlock); | |
| 1992/0403 | if(waserror()){ | |
| 1992/1222 | qunlock(&ctlr->tlock); | |
| 1992/0403 | nexterror(); } | |
| 1993/1113 | n = (*ctlr->write)(ctlr, buf, n); | |
| 1992/0403 | poperror(); | |
| 1993/1113 | qunlock(&ctlr->tlock); | |
| 1992/0403 | ||
| 1993/1113 | return n; | |
| 1992/0403 | } | |
| 1993/1113 | static struct { char *type; int (*reset)(Ether*); | |
| 1993/1119 | } cards[MaxEther+1]; | |
| 1992/0403 | ||
| 1993/1113 | void addethercard(char *t, int (*r)(Ether*)) | |
| 1992/0403 | { | |
| 1993/1113 | static int ncard; | |
| 1992/0403 | ||
| 1993/1119 | if(ncard == MaxEther) | |
| 1993/1113 | panic("too many ether cards"); cards[ncard].type = t; cards[ncard].reset = r; ncard++; | |
| 1992/0403 | } | |
| 1992/0424 | void etherreset(void) { | |
| 1993/1113 | Ether *ctlr; int i, n, ctlrno; ulong irqmask; | |
| 1992/0410 | ||
| 1993/1113 | irqmask = 0; for(ctlr = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){ if(ctlr == 0) ctlr = malloc(sizeof(Ether)); memset(ctlr, 0, sizeof(Ether)); if(isaconfig("ether", ctlrno, ctlr) == 0) continue; for(n = 0; cards[n].type; n++){ if(strcmp(cards[n].type, ctlr->type)) continue; if((*cards[n].reset)(ctlr)) break; | |
| 1992/1222 | /* * IRQ2 doesn't really exist, it's used to gang the interrupt * controllers together. A device set to IRQ2 will appear on * the second interrupt controller as IRQ9. */ | |
| 1993/1113 | if(ctlr->irq == 2) ctlr->irq = 9; if((irqmask & (1<<ctlr->irq)) == 0){ | |
| 1993/1124 | setvec(Int0vec+ctlr->irq, ctlr->interrupt, ctlr); | |
| 1993/1113 | irqmask |= 1<<ctlr->irq; } | |
| 1993/0212 | ||
| 1993/1113 | print("ether%d: %s: port %lux irq %d addr %lux size %d:", ctlrno, ctlr->type, ctlr->port, ctlr->irq, ctlr->mem, ctlr->size); for(i = 0; i < sizeof(ctlr->ea); i++) print(" %2.2ux", ctlr->ea[i]); print("\n"); | |
| 1993/0212 | ||
| 1993/1113 | netifinit(ctlr, "ether", Ntypes, 32*1024); ctlr->alen = Eaddrlen; memmove(ctlr->addr, ctlr->ea, sizeof(ctlr->ea)); memmove(ctlr->bcast, etherbcast, sizeof(etherbcast)); | |
| 1992/0410 | ||
| 1993/1113 | ether[ctlrno] = ctlr; ctlr = 0; | |
| 1993/1120 | break; | |
| 1993/1113 | } | |
| 1992/0403 | } | |
| 1993/1113 | if(ctlr) free(ctlr); | |
| 1992/0403 | } | |