xref: /plan9-contrib/sys/src/boot/vt4/ether.c (revision da917039c7f233c1a27d212bf012c6afa758af39)
1 #include "include.h"
2 #include "ip.h"
3 
4 static Ether *ether;
5 
6 int debug;
7 
8 int	temacreset(Ether*);
9 int	plbtemacreset(Ether*);
10 int	isaconfig(char*, int, ISAConf*);
11 
12 typedef struct Ethercard Ethercard;
13 struct Ethercard {
14 	char	*type;
15 	int	(*reset)(Ether*);
16 	int	noprobe;
17 } ethercards[] = {
18 	{ "temac", temacreset, 0, },
19 	{ 0, }
20 };
21 
22 static void xetherdetach(void);
23 
24 int
etherinit(void)25 etherinit(void)		/* called from probe() */
26 {
27 	Ether *ctlr;
28 	int ctlrno, i, mask, n, x;
29 
30 	fmtinstall('E', eipfmt);
31 	fmtinstall('V', eipfmt);
32 
33 	etherdetach = xetherdetach;
34 	mask = 0;
35 	ether = malloc(MaxEther * sizeof *ether);
36 	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
37 		ctlr = &ether[ctlrno];
38 		memset(ctlr, 0, sizeof(Ether));
39 //		if(isaconfig("ether", ctlrno, ctlr) == 0)
40 //			continue;
41 
42 		for(n = 0; ethercards[n].type; n++){
43 			Ethercard *ecp;
44 
45 			ecp = &ethercards[n];
46 			if (1) {
47 				if(ecp->noprobe)
48 					continue;
49 				memset(ctlr, 0, sizeof(Ether));
50 //				strecpy(ctlr->type, &ctlr->type[NAMELEN],
51 //					ecp->type);
52 			}
53 //			else if(cistrcmp(ecp->type, ctlr->type) != 0)
54 //				continue;
55 			ctlr->ctlrno = ctlrno;
56 
57 			x = splhi();
58 			if((*ecp->reset)(ctlr)){
59 				splx(x);
60 				continue;
61 			}
62 
63 			ctlr->state = 1;		/* card found */
64 			mask |= 1<<ctlrno;
65 //			setvec(VectorPIC + ctlr->irq, ctlr->interrupt, ctlr);
66 			intrenable(Inttemac, ctlr->interrupt);
67 
68 			print("ether#%d: port 0x%lux", ctlr->ctlrno, ctlr->port);
69 			if(ctlr->mem)
70 				print(" addr 0x%luX", ctlr->mem & ~KZERO);
71 			if(ctlr->size)
72 				print(" size 0x%luX", ctlr->size);
73 			print(": %E\n", ctlr->ea);
74 
75 			if(ctlr->nrb == 0)
76 				ctlr->nrb = Nrb;
77 			ctlr->rb = ialloc(sizeof(RingBuf)*ctlr->nrb, 0);
78 			if(ctlr->ntb == 0)
79 				ctlr->ntb = Ntb;
80 			ctlr->tb = ialloc(sizeof(RingBuf)*ctlr->ntb, 0);
81 
82 			ctlr->rh = 0;
83 			ctlr->ri = 0;
84 			for(i = 0; i < ctlr->nrb; i++)
85 				ctlr->rb[i].owner = Interface;
86 
87 			ctlr->th = 0;
88 			ctlr->ti = 0;
89 			for(i = 0; i < ctlr->ntb; i++)
90 				ctlr->tb[i].owner = Host;
91 
92 			splx(x);
93 			break;
94 		}
95 	}
96 
97 	return mask;
98 }
99 
100 void
etherinitdev(int i,char * s)101 etherinitdev(int i, char *s)
102 {
103 	seprint(s, s + NAMELEN, "ether%d", i);
104 }
105 
106 void
etherprintdevs(int i)107 etherprintdevs(int i)
108 {
109 	print(" ether%d", i);
110 }
111 
112 static Ether*
attach(int ctlrno)113 attach(int ctlrno)
114 {
115 	Ether *ctlr;
116 
117 	if(ctlrno >= MaxEther || ether[ctlrno].state == 0)
118 		return 0;
119 
120 	ctlr = &ether[ctlrno];
121 	if(ctlr->state == 1){		/* card found? */
122 		ctlr->state = 2;	/* attaching */
123 		(*ctlr->attach)(ctlr);
124 	}
125 
126 	return ctlr;
127 }
128 
129 static void
xetherdetach(void)130 xetherdetach(void)
131 {
132 	Ether *ctlr;
133 	int ctlrno, x;
134 
135 	x = splhi();
136 	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
137 		ctlr = &ether[ctlrno];
138 		if(ctlr->detach && ctlr->state != 0)	/* found | attaching? */
139 			ctlr->detach(ctlr);
140 	}
141 	splx(x);
142 }
143 
144 uchar*
etheraddr(int ctlrno)145 etheraddr(int ctlrno)
146 {
147 	Ether *ctlr;
148 
149 	if((ctlr = attach(ctlrno)) == 0)
150 		return 0;
151 
152 	return ctlr->ea;
153 }
154 
155 /* wait for owner of RingBuf to change from `owner' */
156 static int
wait(RingBuf * ring,uchar owner,int timo)157 wait(RingBuf* ring, uchar owner, int timo)
158 {
159 	ulong start;
160 
161 	start = m->ticks;
162 	while(TK2MS(m->ticks - start) < timo)
163 		if(ring->owner != owner)
164 			return 1;
165 	return 0;
166 }
167 
168 int
etherrxpkt(int ctlrno,Etherpkt * pkt,int timo)169 etherrxpkt(int ctlrno, Etherpkt* pkt, int timo)
170 {
171 	int n;
172 	Ether *ctlr;
173 	RingBuf *ring;
174 
175 	if((ctlr = attach(ctlrno)) == 0)
176 		return 0;
177 
178 	ring = &ctlr->rb[ctlr->rh];
179 	if(wait(ring, Interface, timo) == 0){
180 		if(debug)
181 			print("ether%d: rx timeout\n", ctlrno);
182 		return 0;
183 	}
184 
185 	n = ring->len;
186 	memmove(pkt, ring->pkt, n);
187 	coherence();
188 	ring->owner = Interface;
189 	ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
190 
191 	return n;
192 }
193 
194 int
etherrxflush(int ctlrno)195 etherrxflush(int ctlrno)
196 {
197 	int n;
198 	Ether *ctlr;
199 	RingBuf *ring;
200 
201 	if((ctlr = attach(ctlrno)) == 0)
202 		return 0;
203 
204 	n = 0;
205 	for(;;){
206 		ring = &ctlr->rb[ctlr->rh];
207 		if(wait(ring, Interface, 100) == 0)
208 			break;
209 
210 		ring->owner = Interface;
211 		ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
212 		n++;
213 	}
214 
215 	return n;
216 }
217 
218 int
ethertxpkt(int ctlrno,Etherpkt * pkt,int len,int)219 ethertxpkt(int ctlrno, Etherpkt* pkt, int len, int)
220 {
221 	Ether *ctlr;
222 	RingBuf *ring;
223 	int s;
224 
225 	if((ctlr = attach(ctlrno)) == 0)
226 		return 0;
227 
228 	ring = &ctlr->tb[ctlr->th];
229 	if(wait(ring, Interface, 1000) == 0){
230 		print("ether%d: tx buffer timeout\n", ctlrno);
231 		return 0;
232 	}
233 
234 	memmove(pkt->s, ctlr->ea, Eaddrlen);
235 	if(debug)
236 		print("%E to %E...\n", pkt->s, pkt->d);
237 	memmove(ring->pkt, pkt, len);
238 	if(len < ETHERMINTU){
239 		memset(ring->pkt+len, 0, ETHERMINTU-len);
240 		len = ETHERMINTU;
241 	}
242 	ring->len = len;
243 	ring->owner = Interface;
244 	ctlr->th = NEXT(ctlr->th, ctlr->ntb);
245 	coherence();
246 	s = splhi();
247 	(*ctlr->transmit)(ctlr);
248 	splx(s);
249 
250 	return 1;
251 }
252