xref: /inferno-os/os/boot/pc/ether.c (revision 4eb166cf184c1f102fb79e31b1465ea3e2021c39)
1 #include "u.h"
2 #include "lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "ip.h"
8 
9 #include "etherif.h"
10 
11 static Ether ether[MaxEther];
12 
13 extern int ether2114xreset(Ether*);
14 extern int elnk3reset(Ether*);
15 extern int i82557reset(Ether*);
16 extern int igbepnp(Ether *);
17 extern int i82563pnp(Ether *);
18 extern int elnk3reset(Ether*);
19 extern int ether589reset(Ether*);
20 extern int ne2000reset(Ether*);
21 extern int wd8003reset(Ether*);
22 extern int ec2treset(Ether*);
23 extern int amd79c970reset(Ether*);
24 extern int rtl8139pnp(Ether*);
25 extern int rtl8169pnp(Ether*);
26 extern int ether83815reset(Ether*);
27 extern int rhinepnp(Ether*);
28 extern int ga620pnp(Ether*);
29 extern int dp83820pnp(Ether*);
30 
31 struct {
32 	char	*type;
33 	int	(*reset)(Ether*);
34 	int	noprobe;
35 } ethercards[] = {
36 	{ "21140", ether2114xreset, 0, },
37 	{ "2114x", ether2114xreset, 0, },
38 	{ "i82557", i82557reset, 0, },
39 	{ "igbe",  igbepnp, 0, },
40 	{ "i82563",i82563pnp, 0, },
41 	{ "igbepcie",i82563pnp, 0, },
42 	{ "elnk3", elnk3reset, 0, },
43 	{ "3C509", elnk3reset, 0, },
44 	{ "3C575", elnk3reset, 0, },
45 	{ "3C589", ether589reset, 1, },
46 	{ "3C562", ether589reset, 1, },
47 	{ "589E", ether589reset, 1, },
48 	{ "NE2000", ne2000reset, 0, },
49 	{ "WD8003", wd8003reset, 1, },
50 	{ "EC2T", ec2treset, 0, },
51 	{ "AMD79C970", amd79c970reset, 0, },
52 	{ "RTL8139", rtl8139pnp, 0, },
53 	{ "RTL8169", rtl8169pnp, 0, },
54 	{ "83815", ether83815reset, 0, },
55 	{ "rhine", rhinepnp, 0, },
56 	{ "vt6102", rhinepnp, 0, },
57 	{ "GA620", ga620pnp, 0, },
58 	{ "83820",   dp83820pnp, 0, },
59 	{ "dp83820", dp83820pnp, 0, },
60 
61 	{ 0, }
62 };
63 
64 static void xetherdetach(void);
65 
66 int
67 etherinit(void)
68 {
69 	Ether *ctlr;
70 	int ctlrno, i, mask, n, x;
71 
72 	fmtinstall('E', eipfmt);
73 
74 	etherdetach = xetherdetach;
75 	mask = 0;
76 	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
77 		ctlr = &ether[ctlrno];
78 		memset(ctlr, 0, sizeof(Ether));
79 		if(iniread && isaconfig("ether", ctlrno, ctlr) == 0)
80 			continue;
81 
82 		for(n = 0; ethercards[n].type; n++){
83 			if(!iniread){
84 				if(ethercards[n].noprobe)
85 					continue;
86 				memset(ctlr, 0, sizeof(Ether));
87 				strcpy(ctlr->type, ethercards[n].type);
88 			}
89 			else if(cistrcmp(ethercards[n].type, ctlr->type))
90 				continue;
91 			ctlr->ctlrno = ctlrno;
92 
93 			x = splhi();
94 			if((*ethercards[n].reset)(ctlr)){
95 				splx(x);
96 				if(iniread)
97 					break;
98 				else
99 					continue;
100 			}
101 
102 			ctlr->state = 1;		/* card found */
103 			mask |= 1<<ctlrno;
104 			if(ctlr->irq == 2)
105 				ctlr->irq = 9;
106 			setvec(VectorPIC + ctlr->irq, ctlr->interrupt, ctlr);
107 
108 			print("ether#%d: %s: port 0x%luX irq %lud",
109 				ctlr->ctlrno, ctlr->type, ctlr->port, ctlr->irq);
110 			if(ctlr->mem)
111 				print(" addr 0x%luX", ctlr->mem & ~KZERO);
112 			if(ctlr->size)
113 				print(" size 0x%luX", ctlr->size);
114 			print(": %E\n", ctlr->ea);
115 
116 			if(ctlr->nrb == 0)
117 				ctlr->nrb = Nrb;
118 			ctlr->rb = ialloc(sizeof(RingBuf)*ctlr->nrb, 0);
119 			if(ctlr->ntb == 0)
120 				ctlr->ntb = Ntb;
121 			ctlr->tb = ialloc(sizeof(RingBuf)*ctlr->ntb, 0);
122 
123 			ctlr->rh = 0;
124 			ctlr->ri = 0;
125 			for(i = 0; i < ctlr->nrb; i++)
126 				ctlr->rb[i].owner = Interface;
127 
128 			ctlr->th = 0;
129 			ctlr->ti = 0;
130 			for(i = 0; i < ctlr->ntb; i++)
131 				ctlr->tb[i].owner = Host;
132 
133 			splx(x);
134 			break;
135 		}
136 	}
137 
138 	return mask;
139 }
140 
141 void
142 etherinitdev(int i, char *s)
143 {
144 	sprint(s, "ether%d", i);
145 }
146 
147 void
148 etherprintdevs(int i)
149 {
150 	print(" ether%d", i);
151 }
152 
153 static Ether*
154 attach(int ctlrno)
155 {
156 	Ether *ctlr;
157 
158 	if(ctlrno >= MaxEther || ether[ctlrno].state == 0)
159 		return 0;
160 
161 	ctlr = &ether[ctlrno];
162 	if(ctlr->state == 1){		/* card found? */
163 		ctlr->state = 2;	/* attaching */
164 		(*ctlr->attach)(ctlr);
165 	}
166 
167 	return ctlr;
168 }
169 
170 static void
171 xetherdetach(void)
172 {
173 	Ether *ctlr;
174 	int ctlrno, x;
175 
176 	x = splhi();
177 	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
178 		ctlr = &ether[ctlrno];
179 		if(ctlr->detach && ctlr->state != 0)	/* found | attaching? */
180 			ctlr->detach(ctlr);
181 	}
182 	splx(x);
183 }
184 
185 uchar*
186 etheraddr(int ctlrno)
187 {
188 	Ether *ctlr;
189 
190 	if((ctlr = attach(ctlrno)) == 0)
191 		return 0;
192 
193 	return ctlr->ea;
194 }
195 
196 static int
197 wait(RingBuf* ring, uchar owner, int timo)
198 {
199 	ulong start;
200 
201 	start = m->ticks;
202 	while(TK2MS(m->ticks - start) < timo){
203 		if(ring->owner != owner)
204 			return 1;
205 	}
206 
207 	return 0;
208 }
209 
210 int
211 etherrxpkt(int ctlrno, Etherpkt* pkt, int timo)
212 {
213 	int n;
214 	Ether *ctlr;
215 	RingBuf *ring;
216 
217 	if((ctlr = attach(ctlrno)) == 0)
218 		return 0;
219 
220 	ring = &ctlr->rb[ctlr->rh];
221 	if(wait(ring, Interface, timo) == 0){
222 		if(debug)
223 			print("ether%d: rx timeout\n", ctlrno);
224 		return 0;
225 	}
226 
227 	n = ring->len;
228 	memmove(pkt, ring->pkt, n);
229 	ring->owner = Interface;
230 	ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
231 
232 	return n;
233 }
234 
235 int
236 etherrxflush(int ctlrno)
237 {
238 	int n;
239 	Ether *ctlr;
240 	RingBuf *ring;
241 
242 	if((ctlr = attach(ctlrno)) == 0)
243 		return 0;
244 
245 	n = 0;
246 	for(;;){
247 		ring = &ctlr->rb[ctlr->rh];
248 		if(wait(ring, Interface, 100) == 0)
249 			break;
250 
251 		ring->owner = Interface;
252 		ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
253 		n++;
254 	}
255 
256 	return n;
257 }
258 
259 int
260 ethertxpkt(int ctlrno, Etherpkt* pkt, int len, int)
261 {
262 	Ether *ctlr;
263 	RingBuf *ring;
264 	int s;
265 
266 	if((ctlr = attach(ctlrno)) == 0)
267 		return 0;
268 
269 	ring = &ctlr->tb[ctlr->th];
270 	if(wait(ring, Interface, 1000) == 0){
271 		print("ether%d: tx buffer timeout\n", ctlrno);
272 		return 0;
273 	}
274 
275 	memmove(pkt->s, ctlr->ea, Eaddrlen);
276 	if(debug)
277 		print("%E to %E...\n", pkt->s, pkt->d);
278 	memmove(ring->pkt, pkt, len);
279 	if(len < ETHERMINTU){
280 		memset(ring->pkt+len, 0, ETHERMINTU-len);
281 		len = ETHERMINTU;
282 	}
283 	ring->len = len;
284 	ring->owner = Interface;
285 	ctlr->th = NEXT(ctlr->th, ctlr->ntb);
286 	s = splhi();
287 	(*ctlr->transmit)(ctlr);
288 	splx(s);
289 
290 	return 1;
291 }
292