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