1*9ef1f84bSDavid du Colombier /*
2*9ef1f84bSDavid du Colombier * Dummy ethernet
3*9ef1f84bSDavid du Colombier */
4*9ef1f84bSDavid du Colombier #include "u.h"
5*9ef1f84bSDavid du Colombier #include "../port/lib.h"
6*9ef1f84bSDavid du Colombier #include "mem.h"
7*9ef1f84bSDavid du Colombier #include "dat.h"
8*9ef1f84bSDavid du Colombier #include "fns.h"
9*9ef1f84bSDavid du Colombier #include "io.h"
10*9ef1f84bSDavid du Colombier #include "../port/error.h"
11*9ef1f84bSDavid du Colombier #include "../port/netif.h"
12*9ef1f84bSDavid du Colombier #include "etherif.h"
13*9ef1f84bSDavid du Colombier
14*9ef1f84bSDavid du Colombier enum {
15*9ef1f84bSDavid du Colombier Rbsz = ETHERMAXTU+32, /* +slop is for vlan headers, crcs, etc. */
16*9ef1f84bSDavid du Colombier Descalign= 128, /* 599 manual needs 128-byte alignment */
17*9ef1f84bSDavid du Colombier
18*9ef1f84bSDavid du Colombier /* tunable parameters */
19*9ef1f84bSDavid du Colombier Nrd = 4,
20*9ef1f84bSDavid du Colombier Nrb = 8,
21*9ef1f84bSDavid du Colombier Ntd = 4,
22*9ef1f84bSDavid du Colombier };
23*9ef1f84bSDavid du Colombier
24*9ef1f84bSDavid du Colombier enum {
25*9ef1f84bSDavid du Colombier Factive = 1<<0,
26*9ef1f84bSDavid du Colombier };
27*9ef1f84bSDavid du Colombier
28*9ef1f84bSDavid du Colombier typedef struct {
29*9ef1f84bSDavid du Colombier Pcidev *p;
30*9ef1f84bSDavid du Colombier Ether *edev;
31*9ef1f84bSDavid du Colombier int type;
32*9ef1f84bSDavid du Colombier
33*9ef1f84bSDavid du Colombier /* virtual */
34*9ef1f84bSDavid du Colombier uintptr *reg;
35*9ef1f84bSDavid du Colombier
36*9ef1f84bSDavid du Colombier uchar flag;
37*9ef1f84bSDavid du Colombier int nrd;
38*9ef1f84bSDavid du Colombier int ntd;
39*9ef1f84bSDavid du Colombier int nrb;
40*9ef1f84bSDavid du Colombier uint rbsz;
41*9ef1f84bSDavid du Colombier int procsrunning;
42*9ef1f84bSDavid du Colombier int attached;
43*9ef1f84bSDavid du Colombier
44*9ef1f84bSDavid du Colombier Lock slock;
45*9ef1f84bSDavid du Colombier Lock alock; /* attach lock */
46*9ef1f84bSDavid du Colombier QLock tlock;
47*9ef1f84bSDavid du Colombier
48*9ef1f84bSDavid du Colombier uint im;
49*9ef1f84bSDavid du Colombier Lock imlock;
50*9ef1f84bSDavid du Colombier
51*9ef1f84bSDavid du Colombier Block **rb;
52*9ef1f84bSDavid du Colombier uint rdt;
53*9ef1f84bSDavid du Colombier uint rdfree;
54*9ef1f84bSDavid du Colombier
55*9ef1f84bSDavid du Colombier uint tdh;
56*9ef1f84bSDavid du Colombier uint tdt;
57*9ef1f84bSDavid du Colombier Block **tb;
58*9ef1f84bSDavid du Colombier
59*9ef1f84bSDavid du Colombier uchar ra[Eaddrlen];
60*9ef1f84bSDavid du Colombier } Ctlr;
61*9ef1f84bSDavid du Colombier
62*9ef1f84bSDavid du Colombier static Ctlr *ctlrtab[4];
63*9ef1f84bSDavid du Colombier static int nctlr;
64*9ef1f84bSDavid du Colombier static Lock rblock;
65*9ef1f84bSDavid du Colombier static Block *rbpool;
66*9ef1f84bSDavid du Colombier
67*9ef1f84bSDavid du Colombier static long
ifstat(Ether * e,void * a,long n,ulong offset)68*9ef1f84bSDavid du Colombier ifstat(Ether *e, void *a, long n, ulong offset)
69*9ef1f84bSDavid du Colombier {
70*9ef1f84bSDavid du Colombier char *s, *p, *q;
71*9ef1f84bSDavid du Colombier Ctlr *c;
72*9ef1f84bSDavid du Colombier
73*9ef1f84bSDavid du Colombier c = e->ctlr;
74*9ef1f84bSDavid du Colombier p = s = malloc(READSTR);
75*9ef1f84bSDavid du Colombier if(p == nil)
76*9ef1f84bSDavid du Colombier error(Enomem);
77*9ef1f84bSDavid du Colombier q = p + READSTR;
78*9ef1f84bSDavid du Colombier
79*9ef1f84bSDavid du Colombier p = seprint(p, q, "mtu: min:%d max:%d\n", e->minmtu, e->maxmtu);
80*9ef1f84bSDavid du Colombier seprint(p, q, "rdfree %d\n", c->rdfree);
81*9ef1f84bSDavid du Colombier n = readstr(offset, a, n, s);
82*9ef1f84bSDavid du Colombier free(s);
83*9ef1f84bSDavid du Colombier
84*9ef1f84bSDavid du Colombier return n;
85*9ef1f84bSDavid du Colombier }
86*9ef1f84bSDavid du Colombier
87*9ef1f84bSDavid du Colombier static long
ctl(Ether *,void *,long)88*9ef1f84bSDavid du Colombier ctl(Ether *, void *, long)
89*9ef1f84bSDavid du Colombier {
90*9ef1f84bSDavid du Colombier error(Ebadarg);
91*9ef1f84bSDavid du Colombier return -1;
92*9ef1f84bSDavid du Colombier }
93*9ef1f84bSDavid du Colombier
94*9ef1f84bSDavid du Colombier static Block*
rballoc(void)95*9ef1f84bSDavid du Colombier rballoc(void)
96*9ef1f84bSDavid du Colombier {
97*9ef1f84bSDavid du Colombier Block *bp;
98*9ef1f84bSDavid du Colombier
99*9ef1f84bSDavid du Colombier ilock(&rblock);
100*9ef1f84bSDavid du Colombier if((bp = rbpool) != nil){
101*9ef1f84bSDavid du Colombier rbpool = bp->next;
102*9ef1f84bSDavid du Colombier bp->next = 0;
103*9ef1f84bSDavid du Colombier // ainc(&bp->ref); /* prevent bp from being freed */
104*9ef1f84bSDavid du Colombier }
105*9ef1f84bSDavid du Colombier iunlock(&rblock);
106*9ef1f84bSDavid du Colombier return bp;
107*9ef1f84bSDavid du Colombier }
108*9ef1f84bSDavid du Colombier
109*9ef1f84bSDavid du Colombier void
drbfree(Block * b)110*9ef1f84bSDavid du Colombier drbfree(Block *b)
111*9ef1f84bSDavid du Colombier {
112*9ef1f84bSDavid du Colombier b->rp = b->wp = (uchar*)ROUNDUP((uintptr)b->base, 2*KiB);
113*9ef1f84bSDavid du Colombier b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
114*9ef1f84bSDavid du Colombier ilock(&rblock);
115*9ef1f84bSDavid du Colombier b->next = rbpool;
116*9ef1f84bSDavid du Colombier rbpool = b;
117*9ef1f84bSDavid du Colombier iunlock(&rblock);
118*9ef1f84bSDavid du Colombier }
119*9ef1f84bSDavid du Colombier
120*9ef1f84bSDavid du Colombier void
dtransmit(Ether * e)121*9ef1f84bSDavid du Colombier dtransmit(Ether *e)
122*9ef1f84bSDavid du Colombier {
123*9ef1f84bSDavid du Colombier Block *b;
124*9ef1f84bSDavid du Colombier
125*9ef1f84bSDavid du Colombier while((b = qget(e->oq)) != nil)
126*9ef1f84bSDavid du Colombier freeb(b);
127*9ef1f84bSDavid du Colombier }
128*9ef1f84bSDavid du Colombier
129*9ef1f84bSDavid du Colombier static void
rxinit(Ctlr * c)130*9ef1f84bSDavid du Colombier rxinit(Ctlr *c)
131*9ef1f84bSDavid du Colombier {
132*9ef1f84bSDavid du Colombier int i;
133*9ef1f84bSDavid du Colombier Block *b;
134*9ef1f84bSDavid du Colombier
135*9ef1f84bSDavid du Colombier for(i = 0; i < c->nrd; i++){
136*9ef1f84bSDavid du Colombier b = c->rb[i];
137*9ef1f84bSDavid du Colombier c->rb[i] = 0;
138*9ef1f84bSDavid du Colombier if(b)
139*9ef1f84bSDavid du Colombier freeb(b);
140*9ef1f84bSDavid du Colombier }
141*9ef1f84bSDavid du Colombier c->rdfree = 0;
142*9ef1f84bSDavid du Colombier }
143*9ef1f84bSDavid du Colombier
144*9ef1f84bSDavid du Colombier static void
promiscuous(void *,int)145*9ef1f84bSDavid du Colombier promiscuous(void*, int)
146*9ef1f84bSDavid du Colombier {
147*9ef1f84bSDavid du Colombier }
148*9ef1f84bSDavid du Colombier
149*9ef1f84bSDavid du Colombier static void
multicast(void *,uchar *,int)150*9ef1f84bSDavid du Colombier multicast(void *, uchar *, int)
151*9ef1f84bSDavid du Colombier {
152*9ef1f84bSDavid du Colombier }
153*9ef1f84bSDavid du Colombier
154*9ef1f84bSDavid du Colombier static void
freemem(Ctlr * c)155*9ef1f84bSDavid du Colombier freemem(Ctlr *c)
156*9ef1f84bSDavid du Colombier {
157*9ef1f84bSDavid du Colombier Block *b;
158*9ef1f84bSDavid du Colombier
159*9ef1f84bSDavid du Colombier while(b = rballoc()){
160*9ef1f84bSDavid du Colombier b->free = 0;
161*9ef1f84bSDavid du Colombier freeb(b);
162*9ef1f84bSDavid du Colombier }
163*9ef1f84bSDavid du Colombier free(c->rb);
164*9ef1f84bSDavid du Colombier c->rb = nil;
165*9ef1f84bSDavid du Colombier free(c->tb);
166*9ef1f84bSDavid du Colombier c->tb = nil;
167*9ef1f84bSDavid du Colombier }
168*9ef1f84bSDavid du Colombier
169*9ef1f84bSDavid du Colombier static int
detach(Ctlr * c)170*9ef1f84bSDavid du Colombier detach(Ctlr *c)
171*9ef1f84bSDavid du Colombier {
172*9ef1f84bSDavid du Colombier c->attached = 0;
173*9ef1f84bSDavid du Colombier return 0;
174*9ef1f84bSDavid du Colombier }
175*9ef1f84bSDavid du Colombier
176*9ef1f84bSDavid du Colombier static void
shutdown(Ether * e)177*9ef1f84bSDavid du Colombier shutdown(Ether *e)
178*9ef1f84bSDavid du Colombier {
179*9ef1f84bSDavid du Colombier detach(e->ctlr);
180*9ef1f84bSDavid du Colombier // freemem(e->ctlr);
181*9ef1f84bSDavid du Colombier }
182*9ef1f84bSDavid du Colombier
183*9ef1f84bSDavid du Colombier
184*9ef1f84bSDavid du Colombier static int
reset(Ctlr * c)185*9ef1f84bSDavid du Colombier reset(Ctlr *c)
186*9ef1f84bSDavid du Colombier {
187*9ef1f84bSDavid du Colombier if(detach(c)){
188*9ef1f84bSDavid du Colombier print("dummy: reset timeout\n");
189*9ef1f84bSDavid du Colombier return -1;
190*9ef1f84bSDavid du Colombier }
191*9ef1f84bSDavid du Colombier return 0;
192*9ef1f84bSDavid du Colombier }
193*9ef1f84bSDavid du Colombier
194*9ef1f84bSDavid du Colombier static void
txinit(Ctlr * c)195*9ef1f84bSDavid du Colombier txinit(Ctlr *c)
196*9ef1f84bSDavid du Colombier {
197*9ef1f84bSDavid du Colombier Block *b;
198*9ef1f84bSDavid du Colombier int i;
199*9ef1f84bSDavid du Colombier
200*9ef1f84bSDavid du Colombier for(i = 0; i < c->ntd; i++){
201*9ef1f84bSDavid du Colombier b = c->tb[i];
202*9ef1f84bSDavid du Colombier c->tb[i] = 0;
203*9ef1f84bSDavid du Colombier if(b)
204*9ef1f84bSDavid du Colombier freeb(b);
205*9ef1f84bSDavid du Colombier }
206*9ef1f84bSDavid du Colombier }
207*9ef1f84bSDavid du Colombier
208*9ef1f84bSDavid du Colombier static void
attach(Ether * e)209*9ef1f84bSDavid du Colombier attach(Ether *e)
210*9ef1f84bSDavid du Colombier {
211*9ef1f84bSDavid du Colombier Block *b;
212*9ef1f84bSDavid du Colombier Ctlr *c;
213*9ef1f84bSDavid du Colombier
214*9ef1f84bSDavid du Colombier c = e->ctlr;
215*9ef1f84bSDavid du Colombier c->edev = e; /* point back to Ether* */
216*9ef1f84bSDavid du Colombier lock(&c->alock);
217*9ef1f84bSDavid du Colombier if(waserror()){
218*9ef1f84bSDavid du Colombier unlock(&c->alock);
219*9ef1f84bSDavid du Colombier freemem(c);
220*9ef1f84bSDavid du Colombier nexterror();
221*9ef1f84bSDavid du Colombier }
222*9ef1f84bSDavid du Colombier if(c->rb == nil) {
223*9ef1f84bSDavid du Colombier c->nrd = Nrd;
224*9ef1f84bSDavid du Colombier c->ntd = Ntd;
225*9ef1f84bSDavid du Colombier c->rb = malloc(c->nrd * sizeof(Block *));
226*9ef1f84bSDavid du Colombier c->tb = malloc(c->ntd * sizeof(Block *));
227*9ef1f84bSDavid du Colombier if (c->rb == nil || c->tb == nil)
228*9ef1f84bSDavid du Colombier error(Enomem);
229*9ef1f84bSDavid du Colombier
230*9ef1f84bSDavid du Colombier for(c->nrb = 0; c->nrb < 2*Nrb; c->nrb++){
231*9ef1f84bSDavid du Colombier b = allocb(c->rbsz + 2*KiB); /* see rbfree() */
232*9ef1f84bSDavid du Colombier if(b == nil)
233*9ef1f84bSDavid du Colombier error(Enomem);
234*9ef1f84bSDavid du Colombier b->free = drbfree;
235*9ef1f84bSDavid du Colombier freeb(b);
236*9ef1f84bSDavid du Colombier }
237*9ef1f84bSDavid du Colombier }
238*9ef1f84bSDavid du Colombier if (!c->attached) {
239*9ef1f84bSDavid du Colombier rxinit(c);
240*9ef1f84bSDavid du Colombier txinit(c);
241*9ef1f84bSDavid du Colombier c->attached = 1;
242*9ef1f84bSDavid du Colombier }
243*9ef1f84bSDavid du Colombier unlock(&c->alock);
244*9ef1f84bSDavid du Colombier poperror();
245*9ef1f84bSDavid du Colombier }
246*9ef1f84bSDavid du Colombier
247*9ef1f84bSDavid du Colombier static void
interrupt(Ureg *,void *)248*9ef1f84bSDavid du Colombier interrupt(Ureg*, void *)
249*9ef1f84bSDavid du Colombier {
250*9ef1f84bSDavid du Colombier }
251*9ef1f84bSDavid du Colombier
252*9ef1f84bSDavid du Colombier static void
scan(void)253*9ef1f84bSDavid du Colombier scan(void)
254*9ef1f84bSDavid du Colombier {
255*9ef1f84bSDavid du Colombier Ctlr *c;
256*9ef1f84bSDavid du Colombier int i;
257*9ef1f84bSDavid du Colombier
258*9ef1f84bSDavid du Colombier for(i = 0; i < 2; i++){
259*9ef1f84bSDavid du Colombier if(nctlr == nelem(ctlrtab)){
260*9ef1f84bSDavid du Colombier print("dummy: too many controllers\n");
261*9ef1f84bSDavid du Colombier return;
262*9ef1f84bSDavid du Colombier }
263*9ef1f84bSDavid du Colombier
264*9ef1f84bSDavid du Colombier c = malloc(sizeof *c);
265*9ef1f84bSDavid du Colombier c->rbsz = Rbsz;
266*9ef1f84bSDavid du Colombier if(reset(c)){
267*9ef1f84bSDavid du Colombier print("dummy: can't reset\n");
268*9ef1f84bSDavid du Colombier free(c);
269*9ef1f84bSDavid du Colombier continue;
270*9ef1f84bSDavid du Colombier }
271*9ef1f84bSDavid du Colombier ctlrtab[nctlr++] = c;
272*9ef1f84bSDavid du Colombier }
273*9ef1f84bSDavid du Colombier }
274*9ef1f84bSDavid du Colombier
275*9ef1f84bSDavid du Colombier static int
pnp(Ether * e)276*9ef1f84bSDavid du Colombier pnp(Ether *e)
277*9ef1f84bSDavid du Colombier {
278*9ef1f84bSDavid du Colombier int i;
279*9ef1f84bSDavid du Colombier Ctlr *c = nil;
280*9ef1f84bSDavid du Colombier
281*9ef1f84bSDavid du Colombier if(nctlr == 0)
282*9ef1f84bSDavid du Colombier scan();
283*9ef1f84bSDavid du Colombier for(i = 0; i < nctlr; i++){
284*9ef1f84bSDavid du Colombier c = ctlrtab[i];
285*9ef1f84bSDavid du Colombier if(c == nil || c->flag & Factive)
286*9ef1f84bSDavid du Colombier continue;
287*9ef1f84bSDavid du Colombier if(e->port == 0 || e->port == PTR2UINT(c->reg))
288*9ef1f84bSDavid du Colombier break;
289*9ef1f84bSDavid du Colombier }
290*9ef1f84bSDavid du Colombier if (i >= nctlr)
291*9ef1f84bSDavid du Colombier return -1;
292*9ef1f84bSDavid du Colombier
293*9ef1f84bSDavid du Colombier c->flag |= Factive;
294*9ef1f84bSDavid du Colombier e->ctlr = c;
295*9ef1f84bSDavid du Colombier e->irq = -1;
296*9ef1f84bSDavid du Colombier e->mbps = 10000;
297*9ef1f84bSDavid du Colombier e->maxmtu = ETHERMAXTU;
298*9ef1f84bSDavid du Colombier memmove(e->ea, c->ra, Eaddrlen);
299*9ef1f84bSDavid du Colombier
300*9ef1f84bSDavid du Colombier e->arg = e;
301*9ef1f84bSDavid du Colombier e->attach = attach;
302*9ef1f84bSDavid du Colombier e->ctl = ctl;
303*9ef1f84bSDavid du Colombier e->ifstat = ifstat;
304*9ef1f84bSDavid du Colombier e->interrupt = interrupt;
305*9ef1f84bSDavid du Colombier e->multicast = multicast;
306*9ef1f84bSDavid du Colombier e->promiscuous = promiscuous;
307*9ef1f84bSDavid du Colombier e->shutdown = shutdown;
308*9ef1f84bSDavid du Colombier e->transmit = dtransmit;
309*9ef1f84bSDavid du Colombier
310*9ef1f84bSDavid du Colombier return 0;
311*9ef1f84bSDavid du Colombier }
312*9ef1f84bSDavid du Colombier
313*9ef1f84bSDavid du Colombier void
etherdummylink(void)314*9ef1f84bSDavid du Colombier etherdummylink(void)
315*9ef1f84bSDavid du Colombier {
316*9ef1f84bSDavid du Colombier addethercard("dummy", pnp);
317*9ef1f84bSDavid du Colombier }
318