174a4d8c2SCharles.Forsyth #include "u.h"
274a4d8c2SCharles.Forsyth #include "lib.h"
374a4d8c2SCharles.Forsyth #include "mem.h"
474a4d8c2SCharles.Forsyth #include "dat.h"
574a4d8c2SCharles.Forsyth #include "fns.h"
674a4d8c2SCharles.Forsyth #include "io.h"
774a4d8c2SCharles.Forsyth #include "ip.h"
874a4d8c2SCharles.Forsyth
974a4d8c2SCharles.Forsyth #include "etherif.h"
1074a4d8c2SCharles.Forsyth
1174a4d8c2SCharles.Forsyth static Ether ether[MaxEther];
1274a4d8c2SCharles.Forsyth
1374a4d8c2SCharles.Forsyth extern int ether2114xreset(Ether*);
1474a4d8c2SCharles.Forsyth extern int elnk3reset(Ether*);
1574a4d8c2SCharles.Forsyth extern int i82557reset(Ether*);
1674a4d8c2SCharles.Forsyth extern int igbepnp(Ether *);
17*8a8c2d74SCharles.Forsyth extern int i82563pnp(Ether *);
1874a4d8c2SCharles.Forsyth extern int elnk3reset(Ether*);
1974a4d8c2SCharles.Forsyth extern int ether589reset(Ether*);
2074a4d8c2SCharles.Forsyth extern int ne2000reset(Ether*);
2174a4d8c2SCharles.Forsyth extern int wd8003reset(Ether*);
2274a4d8c2SCharles.Forsyth extern int ec2treset(Ether*);
2374a4d8c2SCharles.Forsyth extern int amd79c970reset(Ether*);
2474a4d8c2SCharles.Forsyth extern int rtl8139pnp(Ether*);
2574a4d8c2SCharles.Forsyth extern int rtl8169pnp(Ether*);
2674a4d8c2SCharles.Forsyth extern int ether83815reset(Ether*);
2774a4d8c2SCharles.Forsyth extern int rhinepnp(Ether*);
28*8a8c2d74SCharles.Forsyth extern int ga620pnp(Ether*);
29*8a8c2d74SCharles.Forsyth extern int dp83820pnp(Ether*);
3074a4d8c2SCharles.Forsyth
3174a4d8c2SCharles.Forsyth struct {
3274a4d8c2SCharles.Forsyth char *type;
3374a4d8c2SCharles.Forsyth int (*reset)(Ether*);
3474a4d8c2SCharles.Forsyth int noprobe;
3574a4d8c2SCharles.Forsyth } ethercards[] = {
3674a4d8c2SCharles.Forsyth { "21140", ether2114xreset, 0, },
3774a4d8c2SCharles.Forsyth { "2114x", ether2114xreset, 0, },
3874a4d8c2SCharles.Forsyth { "i82557", i82557reset, 0, },
3974a4d8c2SCharles.Forsyth { "igbe", igbepnp, 0, },
40*8a8c2d74SCharles.Forsyth { "i82563",i82563pnp, 0, },
41*8a8c2d74SCharles.Forsyth { "igbepcie",i82563pnp, 0, },
4274a4d8c2SCharles.Forsyth { "elnk3", elnk3reset, 0, },
4374a4d8c2SCharles.Forsyth { "3C509", elnk3reset, 0, },
4474a4d8c2SCharles.Forsyth { "3C575", elnk3reset, 0, },
4574a4d8c2SCharles.Forsyth { "3C589", ether589reset, 1, },
4674a4d8c2SCharles.Forsyth { "3C562", ether589reset, 1, },
4774a4d8c2SCharles.Forsyth { "589E", ether589reset, 1, },
4874a4d8c2SCharles.Forsyth { "NE2000", ne2000reset, 0, },
4974a4d8c2SCharles.Forsyth { "WD8003", wd8003reset, 1, },
5074a4d8c2SCharles.Forsyth { "EC2T", ec2treset, 0, },
5174a4d8c2SCharles.Forsyth { "AMD79C970", amd79c970reset, 0, },
5274a4d8c2SCharles.Forsyth { "RTL8139", rtl8139pnp, 0, },
5374a4d8c2SCharles.Forsyth { "RTL8169", rtl8169pnp, 0, },
5474a4d8c2SCharles.Forsyth { "83815", ether83815reset, 0, },
5574a4d8c2SCharles.Forsyth { "rhine", rhinepnp, 0, },
56*8a8c2d74SCharles.Forsyth { "vt6102", rhinepnp, 0, },
57*8a8c2d74SCharles.Forsyth { "GA620", ga620pnp, 0, },
58*8a8c2d74SCharles.Forsyth { "83820", dp83820pnp, 0, },
59*8a8c2d74SCharles.Forsyth { "dp83820", dp83820pnp, 0, },
6074a4d8c2SCharles.Forsyth
6174a4d8c2SCharles.Forsyth { 0, }
6274a4d8c2SCharles.Forsyth };
6374a4d8c2SCharles.Forsyth
6474a4d8c2SCharles.Forsyth static void xetherdetach(void);
6574a4d8c2SCharles.Forsyth
6674a4d8c2SCharles.Forsyth int
etherinit(void)6774a4d8c2SCharles.Forsyth etherinit(void)
6874a4d8c2SCharles.Forsyth {
6974a4d8c2SCharles.Forsyth Ether *ctlr;
7074a4d8c2SCharles.Forsyth int ctlrno, i, mask, n, x;
7174a4d8c2SCharles.Forsyth
7274a4d8c2SCharles.Forsyth fmtinstall('E', eipfmt);
7374a4d8c2SCharles.Forsyth
7474a4d8c2SCharles.Forsyth etherdetach = xetherdetach;
7574a4d8c2SCharles.Forsyth mask = 0;
7674a4d8c2SCharles.Forsyth for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
7774a4d8c2SCharles.Forsyth ctlr = ðer[ctlrno];
7874a4d8c2SCharles.Forsyth memset(ctlr, 0, sizeof(Ether));
7974a4d8c2SCharles.Forsyth if(iniread && isaconfig("ether", ctlrno, ctlr) == 0)
8074a4d8c2SCharles.Forsyth continue;
8174a4d8c2SCharles.Forsyth
8274a4d8c2SCharles.Forsyth for(n = 0; ethercards[n].type; n++){
8374a4d8c2SCharles.Forsyth if(!iniread){
8474a4d8c2SCharles.Forsyth if(ethercards[n].noprobe)
8574a4d8c2SCharles.Forsyth continue;
8674a4d8c2SCharles.Forsyth memset(ctlr, 0, sizeof(Ether));
8774a4d8c2SCharles.Forsyth strcpy(ctlr->type, ethercards[n].type);
8874a4d8c2SCharles.Forsyth }
8974a4d8c2SCharles.Forsyth else if(cistrcmp(ethercards[n].type, ctlr->type))
9074a4d8c2SCharles.Forsyth continue;
9174a4d8c2SCharles.Forsyth ctlr->ctlrno = ctlrno;
9274a4d8c2SCharles.Forsyth
9374a4d8c2SCharles.Forsyth x = splhi();
9474a4d8c2SCharles.Forsyth if((*ethercards[n].reset)(ctlr)){
9574a4d8c2SCharles.Forsyth splx(x);
9674a4d8c2SCharles.Forsyth if(iniread)
9774a4d8c2SCharles.Forsyth break;
9874a4d8c2SCharles.Forsyth else
9974a4d8c2SCharles.Forsyth continue;
10074a4d8c2SCharles.Forsyth }
10174a4d8c2SCharles.Forsyth
102*8a8c2d74SCharles.Forsyth ctlr->state = 1; /* card found */
10374a4d8c2SCharles.Forsyth mask |= 1<<ctlrno;
10474a4d8c2SCharles.Forsyth if(ctlr->irq == 2)
10574a4d8c2SCharles.Forsyth ctlr->irq = 9;
10674a4d8c2SCharles.Forsyth setvec(VectorPIC + ctlr->irq, ctlr->interrupt, ctlr);
10774a4d8c2SCharles.Forsyth
10874a4d8c2SCharles.Forsyth print("ether#%d: %s: port 0x%luX irq %lud",
10974a4d8c2SCharles.Forsyth ctlr->ctlrno, ctlr->type, ctlr->port, ctlr->irq);
11074a4d8c2SCharles.Forsyth if(ctlr->mem)
11174a4d8c2SCharles.Forsyth print(" addr 0x%luX", ctlr->mem & ~KZERO);
11274a4d8c2SCharles.Forsyth if(ctlr->size)
11374a4d8c2SCharles.Forsyth print(" size 0x%luX", ctlr->size);
11474a4d8c2SCharles.Forsyth print(": %E\n", ctlr->ea);
11574a4d8c2SCharles.Forsyth
11674a4d8c2SCharles.Forsyth if(ctlr->nrb == 0)
11774a4d8c2SCharles.Forsyth ctlr->nrb = Nrb;
11874a4d8c2SCharles.Forsyth ctlr->rb = ialloc(sizeof(RingBuf)*ctlr->nrb, 0);
11974a4d8c2SCharles.Forsyth if(ctlr->ntb == 0)
12074a4d8c2SCharles.Forsyth ctlr->ntb = Ntb;
12174a4d8c2SCharles.Forsyth ctlr->tb = ialloc(sizeof(RingBuf)*ctlr->ntb, 0);
12274a4d8c2SCharles.Forsyth
12374a4d8c2SCharles.Forsyth ctlr->rh = 0;
12474a4d8c2SCharles.Forsyth ctlr->ri = 0;
12574a4d8c2SCharles.Forsyth for(i = 0; i < ctlr->nrb; i++)
12674a4d8c2SCharles.Forsyth ctlr->rb[i].owner = Interface;
12774a4d8c2SCharles.Forsyth
12874a4d8c2SCharles.Forsyth ctlr->th = 0;
12974a4d8c2SCharles.Forsyth ctlr->ti = 0;
13074a4d8c2SCharles.Forsyth for(i = 0; i < ctlr->ntb; i++)
13174a4d8c2SCharles.Forsyth ctlr->tb[i].owner = Host;
13274a4d8c2SCharles.Forsyth
13374a4d8c2SCharles.Forsyth splx(x);
13474a4d8c2SCharles.Forsyth break;
13574a4d8c2SCharles.Forsyth }
13674a4d8c2SCharles.Forsyth }
13774a4d8c2SCharles.Forsyth
13874a4d8c2SCharles.Forsyth return mask;
13974a4d8c2SCharles.Forsyth }
14074a4d8c2SCharles.Forsyth
14174a4d8c2SCharles.Forsyth void
etherinitdev(int i,char * s)14274a4d8c2SCharles.Forsyth etherinitdev(int i, char *s)
14374a4d8c2SCharles.Forsyth {
14474a4d8c2SCharles.Forsyth sprint(s, "ether%d", i);
14574a4d8c2SCharles.Forsyth }
14674a4d8c2SCharles.Forsyth
14774a4d8c2SCharles.Forsyth void
etherprintdevs(int i)14874a4d8c2SCharles.Forsyth etherprintdevs(int i)
14974a4d8c2SCharles.Forsyth {
15074a4d8c2SCharles.Forsyth print(" ether%d", i);
15174a4d8c2SCharles.Forsyth }
15274a4d8c2SCharles.Forsyth
15374a4d8c2SCharles.Forsyth static Ether*
attach(int ctlrno)15474a4d8c2SCharles.Forsyth attach(int ctlrno)
15574a4d8c2SCharles.Forsyth {
15674a4d8c2SCharles.Forsyth Ether *ctlr;
15774a4d8c2SCharles.Forsyth
15874a4d8c2SCharles.Forsyth if(ctlrno >= MaxEther || ether[ctlrno].state == 0)
15974a4d8c2SCharles.Forsyth return 0;
16074a4d8c2SCharles.Forsyth
16174a4d8c2SCharles.Forsyth ctlr = ðer[ctlrno];
162*8a8c2d74SCharles.Forsyth if(ctlr->state == 1){ /* card found? */
163*8a8c2d74SCharles.Forsyth ctlr->state = 2; /* attaching */
16474a4d8c2SCharles.Forsyth (*ctlr->attach)(ctlr);
16574a4d8c2SCharles.Forsyth }
16674a4d8c2SCharles.Forsyth
16774a4d8c2SCharles.Forsyth return ctlr;
16874a4d8c2SCharles.Forsyth }
16974a4d8c2SCharles.Forsyth
17074a4d8c2SCharles.Forsyth static void
xetherdetach(void)17174a4d8c2SCharles.Forsyth xetherdetach(void)
17274a4d8c2SCharles.Forsyth {
17374a4d8c2SCharles.Forsyth Ether *ctlr;
17474a4d8c2SCharles.Forsyth int ctlrno, x;
17574a4d8c2SCharles.Forsyth
17674a4d8c2SCharles.Forsyth x = splhi();
17774a4d8c2SCharles.Forsyth for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
17874a4d8c2SCharles.Forsyth ctlr = ðer[ctlrno];
179*8a8c2d74SCharles.Forsyth if(ctlr->detach && ctlr->state != 0) /* found | attaching? */
18074a4d8c2SCharles.Forsyth ctlr->detach(ctlr);
18174a4d8c2SCharles.Forsyth }
18274a4d8c2SCharles.Forsyth splx(x);
18374a4d8c2SCharles.Forsyth }
18474a4d8c2SCharles.Forsyth
18574a4d8c2SCharles.Forsyth uchar*
etheraddr(int ctlrno)18674a4d8c2SCharles.Forsyth etheraddr(int ctlrno)
18774a4d8c2SCharles.Forsyth {
18874a4d8c2SCharles.Forsyth Ether *ctlr;
18974a4d8c2SCharles.Forsyth
19074a4d8c2SCharles.Forsyth if((ctlr = attach(ctlrno)) == 0)
19174a4d8c2SCharles.Forsyth return 0;
19274a4d8c2SCharles.Forsyth
19374a4d8c2SCharles.Forsyth return ctlr->ea;
19474a4d8c2SCharles.Forsyth }
19574a4d8c2SCharles.Forsyth
19674a4d8c2SCharles.Forsyth static int
wait(RingBuf * ring,uchar owner,int timo)19774a4d8c2SCharles.Forsyth wait(RingBuf* ring, uchar owner, int timo)
19874a4d8c2SCharles.Forsyth {
19974a4d8c2SCharles.Forsyth ulong start;
20074a4d8c2SCharles.Forsyth
20174a4d8c2SCharles.Forsyth start = m->ticks;
20274a4d8c2SCharles.Forsyth while(TK2MS(m->ticks - start) < timo){
20374a4d8c2SCharles.Forsyth if(ring->owner != owner)
20474a4d8c2SCharles.Forsyth return 1;
20574a4d8c2SCharles.Forsyth }
20674a4d8c2SCharles.Forsyth
20774a4d8c2SCharles.Forsyth return 0;
20874a4d8c2SCharles.Forsyth }
20974a4d8c2SCharles.Forsyth
21074a4d8c2SCharles.Forsyth int
etherrxpkt(int ctlrno,Etherpkt * pkt,int timo)21174a4d8c2SCharles.Forsyth etherrxpkt(int ctlrno, Etherpkt* pkt, int timo)
21274a4d8c2SCharles.Forsyth {
21374a4d8c2SCharles.Forsyth int n;
21474a4d8c2SCharles.Forsyth Ether *ctlr;
21574a4d8c2SCharles.Forsyth RingBuf *ring;
21674a4d8c2SCharles.Forsyth
21774a4d8c2SCharles.Forsyth if((ctlr = attach(ctlrno)) == 0)
21874a4d8c2SCharles.Forsyth return 0;
21974a4d8c2SCharles.Forsyth
22074a4d8c2SCharles.Forsyth ring = &ctlr->rb[ctlr->rh];
22174a4d8c2SCharles.Forsyth if(wait(ring, Interface, timo) == 0){
22274a4d8c2SCharles.Forsyth if(debug)
22374a4d8c2SCharles.Forsyth print("ether%d: rx timeout\n", ctlrno);
22474a4d8c2SCharles.Forsyth return 0;
22574a4d8c2SCharles.Forsyth }
22674a4d8c2SCharles.Forsyth
22774a4d8c2SCharles.Forsyth n = ring->len;
22874a4d8c2SCharles.Forsyth memmove(pkt, ring->pkt, n);
22974a4d8c2SCharles.Forsyth ring->owner = Interface;
23074a4d8c2SCharles.Forsyth ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
23174a4d8c2SCharles.Forsyth
23274a4d8c2SCharles.Forsyth return n;
23374a4d8c2SCharles.Forsyth }
23474a4d8c2SCharles.Forsyth
23574a4d8c2SCharles.Forsyth int
etherrxflush(int ctlrno)23674a4d8c2SCharles.Forsyth etherrxflush(int ctlrno)
23774a4d8c2SCharles.Forsyth {
23874a4d8c2SCharles.Forsyth int n;
23974a4d8c2SCharles.Forsyth Ether *ctlr;
24074a4d8c2SCharles.Forsyth RingBuf *ring;
24174a4d8c2SCharles.Forsyth
24274a4d8c2SCharles.Forsyth if((ctlr = attach(ctlrno)) == 0)
24374a4d8c2SCharles.Forsyth return 0;
24474a4d8c2SCharles.Forsyth
24574a4d8c2SCharles.Forsyth n = 0;
24674a4d8c2SCharles.Forsyth for(;;){
24774a4d8c2SCharles.Forsyth ring = &ctlr->rb[ctlr->rh];
24874a4d8c2SCharles.Forsyth if(wait(ring, Interface, 100) == 0)
24974a4d8c2SCharles.Forsyth break;
25074a4d8c2SCharles.Forsyth
25174a4d8c2SCharles.Forsyth ring->owner = Interface;
25274a4d8c2SCharles.Forsyth ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
25374a4d8c2SCharles.Forsyth n++;
25474a4d8c2SCharles.Forsyth }
25574a4d8c2SCharles.Forsyth
25674a4d8c2SCharles.Forsyth return n;
25774a4d8c2SCharles.Forsyth }
25874a4d8c2SCharles.Forsyth
25974a4d8c2SCharles.Forsyth int
ethertxpkt(int ctlrno,Etherpkt * pkt,int len,int)26074a4d8c2SCharles.Forsyth ethertxpkt(int ctlrno, Etherpkt* pkt, int len, int)
26174a4d8c2SCharles.Forsyth {
26274a4d8c2SCharles.Forsyth Ether *ctlr;
26374a4d8c2SCharles.Forsyth RingBuf *ring;
26474a4d8c2SCharles.Forsyth int s;
26574a4d8c2SCharles.Forsyth
26674a4d8c2SCharles.Forsyth if((ctlr = attach(ctlrno)) == 0)
26774a4d8c2SCharles.Forsyth return 0;
26874a4d8c2SCharles.Forsyth
26974a4d8c2SCharles.Forsyth ring = &ctlr->tb[ctlr->th];
27074a4d8c2SCharles.Forsyth if(wait(ring, Interface, 1000) == 0){
27174a4d8c2SCharles.Forsyth print("ether%d: tx buffer timeout\n", ctlrno);
27274a4d8c2SCharles.Forsyth return 0;
27374a4d8c2SCharles.Forsyth }
27474a4d8c2SCharles.Forsyth
27574a4d8c2SCharles.Forsyth memmove(pkt->s, ctlr->ea, Eaddrlen);
27674a4d8c2SCharles.Forsyth if(debug)
27774a4d8c2SCharles.Forsyth print("%E to %E...\n", pkt->s, pkt->d);
27874a4d8c2SCharles.Forsyth memmove(ring->pkt, pkt, len);
27974a4d8c2SCharles.Forsyth if(len < ETHERMINTU){
28074a4d8c2SCharles.Forsyth memset(ring->pkt+len, 0, ETHERMINTU-len);
28174a4d8c2SCharles.Forsyth len = ETHERMINTU;
28274a4d8c2SCharles.Forsyth }
28374a4d8c2SCharles.Forsyth ring->len = len;
28474a4d8c2SCharles.Forsyth ring->owner = Interface;
28574a4d8c2SCharles.Forsyth ctlr->th = NEXT(ctlr->th, ctlr->ntb);
28674a4d8c2SCharles.Forsyth s = splhi();
28774a4d8c2SCharles.Forsyth (*ctlr->transmit)(ctlr);
28874a4d8c2SCharles.Forsyth splx(s);
28974a4d8c2SCharles.Forsyth
29074a4d8c2SCharles.Forsyth return 1;
29174a4d8c2SCharles.Forsyth }
292