band-aid to setup ifen
[unix-history] / usr / src / sys / vax / if / if_en.c
CommitLineData
2b8d82a0 1/* if_en.c 4.12 81/11/23 */
11720282
BJ
2
3#include "en.h"
4/*
5 * Ethernet interface driver
6 */
7
8#include "../h/param.h"
9#include "../h/systm.h"
10#include "../h/mbuf.h"
d52566dd 11#include "../net/inet.h"
eb44bfb2 12#include "../net/inet_pcb.h"
2b8d82a0 13#include "../net/if.h"
d52566dd
BJ
14#include "../net/inet_systm.h"
15#include "../net/imp.h"
16#include "../net/ip.h"
eb44bfb2 17#include "../net/ip_var.h"
53a5409e 18#include "../net/tcp.h" /* XXX */
eb44bfb2 19#include "../net/tcp_var.h"
11720282
BJ
20#include "../h/map.h"
21#include "../h/pte.h"
22#include "../h/buf.h"
23#include "../h/ubareg.h"
24#include "../h/ubavar.h"
25#include "../h/conf.h"
26#include "../h/dir.h"
27#include "../h/user.h"
28#include "../h/proc.h"
29#include "../h/enreg.h"
30#include "../h/mtpr.h"
31#include "../h/cpu.h"
32#include "../h/cmap.h"
33
cdad2eb1
BJ
34int enrswaps;
35/* int enwswaps; */
11720282
BJ
36int enprobe(), enattach(), enrint(), enxint(), encollide();
37struct uba_device *eninfo[NEN];
38u_short enstd[] = { 0 };
39struct uba_driver endriver =
40 { enprobe, 0, enattach, 0, enstd, "en", eninfo };
41
42#define ENUNIT(x) minor(x)
43
44struct en_packet *xpkt, *rpkt;
45struct en_prefix {
46 struct en_header enp_h;
53a5409e 47 struct tcpiphdr enp_th;
11720282
BJ
48};
49struct uba_regs *enuba;
ae348eea 50struct pte *enrmr, *enxmr;
11720282
BJ
51int enrbdp, enwbdp;
52int enrproto, enwproto;
ae348eea
BJ
53struct pte enxmap[2];
54int enxswapd;
11720282
BJ
55
56enprobe(reg)
57 caddr_t reg;
58{
59 register int br, cvec;
60 register struct endevice *addr = (struct endevice *)reg;
61
62#ifdef lint
63 br = 0; cvec = br; br = cvec;
2b4b57cd 64 enrint(0); enxint(0); encollide(0);
11720282
BJ
65#endif
66
67 addr->en_istat = 0;
68 addr->en_ostat = 0;
69 addr->en_owc = -1;
70 addr->en_oba = 0;
941ee7ef 71 addr->en_ostat = EN_IEN|EN_GO;
11720282
BJ
72 DELAY(100000);
73 addr->en_ostat = 0;
74 printf("ethernet address %d\n", ~addr->en_addr&0xff);
75 return (1);
76}
77
cdad2eb1 78/*ARGSUSED*/
11720282
BJ
79enattach(ui)
80 struct uba_device *ui;
81{
2b8d82a0 82 extern struct ifnet ifen;
ae348eea 83
2b8d82a0
BJ
84 ifen.if_mtu = 1024;
85 ifen.if_net = 10;
86 ifen.if_addr.s_host = LOCALHST;
87 ifen.if_addr.s_net = LOCALNET;
88 ifen.if_addr.s_imp = LOCALIMP;
89 n_lhost = ifen.if_addr;
11720282
BJ
90}
91
ae348eea 92eninit(unit)
11720282
BJ
93 int unit;
94{
95 register struct endevice *addr;
96 register struct uba_device *ui;
97 int uban, x;
98 static reenter;
99
100 if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0) {
101 printf("en%d: not alive\n", unit);
102 return;
103 }
104 x = splimp();
105 if (reenter == 0) {
106 int n, j, i, k; char *cp;
107 reenter = 1;
108 n = 10;
109 k = n<<1;
d52566dd 110 i = rmalloc(mbmap, n*2);
11720282 111 if (i == 0)
ae348eea 112 panic("eninit");
11720282
BJ
113 j = i << 1;
114 cp = (char *)pftom(i);
d52566dd 115 if (memall(&Mbmap[j], k, proc, CSYS) == 0)
cdad2eb1 116 panic("eninit");
d52566dd 117 vmaccess(&Mbmap[j], (caddr_t)cp, k);
11720282
BJ
118 rpkt = (struct en_packet *)
119 (cp + 1024 - sizeof (struct en_prefix));
120 xpkt = (struct en_packet *)
121 (cp + 5 * 1024 + 1024 - sizeof (struct en_prefix));
122 for (j = 0; j < n; j++)
123 mprefcnt[i+j] = 1;
124 }
125 uban = ui->ui_ubanum;
126 addr = (struct endevice *)ui->ui_addr;
127 addr->en_istat = 0;
128 addr->en_ostat = 0;
129 imp_stat.iaddr =
130 uballoc(uban, (caddr_t)rpkt, 1024+512, UBA_NEED16|UBA_NEEDBDP);
131 imp_stat.oaddr =
132 uballoc(uban, (caddr_t)xpkt, 1024+512, UBA_NEED16|UBA_NEEDBDP);
133 enuba = ui->ui_hd->uh_uba;
134 enrbdp = (imp_stat.iaddr >> 28) & 0xf;
135 enwbdp = (imp_stat.oaddr >> 28) & 0xf;
136 enrproto = UBAMR_MRV | (enrbdp << 21);
137 enwproto = UBAMR_MRV | (enwbdp << 21);
138 enrmr = &enuba->uba_map[((imp_stat.iaddr>>9)&0x1ff) + 1];
ae348eea
BJ
139 enxmr = &enuba->uba_map[((imp_stat.oaddr>>9)&0x1ff) + 1];
140 enxmap[0] = enxmr[0];
141 enxmap[1] = enxmr[1];
142 enxswapd = 0;
11720282
BJ
143 printf("enrbdp %x enrproto %x enrmr %x imp_stat.iaddr %x\n",
144 enrbdp, enrproto, enrmr, imp_stat.iaddr);
145 imp_stat.impopen = 1;
146 imp_stat.flush = 0;
147 splx(x);
148#ifdef IMPDEBUG
149 printf("eninit(%d): iaddr = %x, oaddr = %x\n",
150 unit, imp_stat.iaddr, imp_stat.oaddr);
151#endif
152}
153
2752c877 154#if 0
11720282
BJ
155enreset(uban)
156 int uban;
157{
158 register int unit;
159 struct uba_device *ui;
160
161 for (unit = 0; unit < NEN; unit++) {
162 ui = eninfo[unit];
163 if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
164 continue;
165 if (imp_stat.iaddr)
cdad2eb1 166 ubarelse(uban, &imp_stat.iaddr);
11720282 167 if (imp_stat.oaddr)
cdad2eb1 168 ubarelse(uban, &imp_stat.oaddr);
ae348eea 169 eninit(unit);
11720282
BJ
170 printf("en%d ", unit);
171 }
172}
2752c877 173#endif
11720282 174
3552a746
BJ
175int enlastdel = 25;
176int enlastx = 0;
ae348eea 177enstart(dev)
11720282
BJ
178 dev_t dev;
179{
180 register struct mbuf *m, *mp;
181 register struct endevice *addr;
182 register caddr_t cp, top;
183 int unit;
184 register int len;
11720282 185 struct uba_device *ui;
ae348eea
BJ
186 int enxswapnow = 0;
187COUNT(ENSTART);
11720282
BJ
188
189 unit = ENUNIT(dev);
190 ui = eninfo[unit];
191 if (ui == 0 || ui->ui_alive == 0) {
192 printf("en%d (imp_output): not alive\n", unit);
193 return;
194 }
195 addr = (struct endevice *)ui->ui_addr;
196 if (!imp_stat.outactive) {
197 if ((m = imp_stat.outq_head) == NULL)
198 return;
199 imp_stat.outactive = 1; /* set myself active */
200 imp_stat.outq_head = m->m_act; /* -> next packet chain */
201 /*
202 * Pack mbufs into ethernet packet.
203 */
204 cp = (caddr_t)xpkt;
205 top = (caddr_t)xpkt + sizeof(struct en_packet);
206 while (m != NULL) {
ae348eea 207 char *dp;
11720282
BJ
208 if (cp + m->m_len > top) {
209 printf("imp_snd: my packet runneth over\n");
210 m_freem(m);
211 return;
212 }
ae348eea
BJ
213 dp = mtod(m, char *);
214 if (((int)cp&0x3ff)==0 && ((int)dp&0x3ff)==0) {
d52566dd 215 struct pte *pte = &Mbmap[mtopf(dp)*2];
ae348eea
BJ
216 *(int *)enxmr = enwproto | pte++->pg_pfnum;
217 *(int *)(enxmr+1) = enwproto | pte->pg_pfnum;
218 enxswapd = enxswapnow = 1;
219 } else
cdad2eb1
BJ
220 bcopy(mtod(m, caddr_t), cp,
221 (unsigned)m->m_len);
11720282 222 cp += m->m_len;
ae348eea 223 /* too soon! */
11720282
BJ
224 MFREE(m, mp);
225 m = mp;
226 }
3552a746
BJ
227 if (enxswapnow == 0 && enxswapd) {
228 enxmr[0] = enxmap[0];
229 enxmr[1] = enxmap[1];
230 }
231 if (enlastx && enlastx == xpkt->Header.en_dhost)
232 imp_stat.endelay = enlastdel;
233 else
234 enlastx = xpkt->Header.en_dhost;
ae348eea 235 }
cdad2eb1
BJ
236 len = ntohs((u_short)(((struct ip *)((int)xpkt + L1822))->ip_len)) +
237 L1822;
11720282
BJ
238 if (len > sizeof(struct en_packet)) {
239 printf("imp_output: ridiculous IP length %d\n", len);
240 return;
241 }
242#if defined(VAX780) || defined(VAX750)
243 switch (cpu) {
244#if defined(VAX780)
245 case VAX_780:
ae348eea 246 UBA_PURGE780(enuba, enwbdp);
11720282
BJ
247 break;
248#endif
249#if defined(VAX750)
250 case VAX_750:
ae348eea 251 UBA_PURGE750(enuba, enwbdp);
11720282
BJ
252 break;
253#endif
254 }
255#endif
256 addr->en_oba = imp_stat.oaddr;
257 addr->en_odelay = imp_stat.endelay;
258 addr->en_owc = -((len + 1) >> 1);
259#ifdef IMPDEBUG
260 printf("en%d: sending packet (%d bytes)\n", unit, len);
261 prt_byte(xpkt, len);
262#endif
941ee7ef 263 addr->en_ostat = EN_IEN|EN_GO;
11720282
BJ
264}
265
11720282
BJ
266/*
267 * Output interrupt handler.
268 */
269enxint(unit)
270 int unit;
271{
272 register struct endevice *addr;
273 register struct uba_device *ui;
274COUNT(ENXINT);
275
276 ui = eninfo[unit];
277 addr = (struct endevice *)ui->ui_addr;
278
279#ifdef IMPDEBUG
280 printf("en%d: enxint ostat=%b\n", unit, addr->en_ostat, EN_BITS);
281#endif
282 if (!imp_stat.outactive) {
283 printf("en%d: phantom output intr ostat=%b\n",
284 unit, addr->en_ostat, EN_BITS);
285 return;
286 }
287 imp_stat.endelay = 0;
288 imp_stat.enmask = ~0;
941ee7ef 289 if (addr->en_ostat&EN_OERROR)
11720282
BJ
290 printf("en%d: output error ostat=%b\n", unit,
291 addr->en_ostat, EN_BITS);
292 imp_stat.outactive = 0;
ae348eea
BJ
293 if (imp_stat.outq_head)
294 enstart(unit);
3552a746
BJ
295 else
296 enlastx = 0;
11720282
BJ
297}
298
3552a746 299int collisions;
11720282
BJ
300encollide(unit)
301 int unit;
302{
303 register struct endevice *addr;
304 register struct uba_device *ui;
305COUNT(ENCOLLIDE);
306
3552a746 307 collisions++;
11720282
BJ
308 ui = eninfo[unit];
309 addr = (struct endevice *)ui->ui_addr;
310
311#ifdef IMPDEBUG
312 printf("en%d: collision ostat=%b\n", unit, addr->en_ostat, EN_BITS);
313#endif
314 if (!imp_stat.outactive) {
315 printf("en%d: phantom collision intr ostat=%b\n",
316 unit, addr->en_ostat, EN_BITS);
317 return;
318 }
319 if (imp_stat.enmask == 0) {
320 printf("en%d: output error ostat=%b\n", unit,
321 addr->en_ostat, EN_BITS);
322 } else {
323 imp_stat.enmask <<= 1;
3552a746 324 imp_stat.endelay = mfpr(ICR) & ~imp_stat.enmask;
11720282 325 }
ae348eea 326 enstart(unit);
11720282
BJ
327}
328
329enrint(unit)
330 int unit;
331{
332 register struct mbuf *m;
333 struct mbuf *mp;
334 register struct endevice *addr;
335 register struct uba_device *ui;
336 register int len;
337 register caddr_t cp;
338 struct mbuf *p, *top = 0;
339 struct ip *ip;
cdad2eb1 340 u_int hlen;
11720282
BJ
341COUNT(ENRINT);
342
343 ui = eninfo[unit];
344 addr = (struct endevice *)ui->ui_addr;
345#ifdef IMPDEBUG
346 printf("en%d: enrint istat=%b\n", unit, addr->en_istat, EN_BITS);
347#endif
348 if (imp_stat.flush)
349 goto flush;
941ee7ef 350 if (addr->en_istat&EN_IERROR) {
11720282
BJ
351#ifdef notdef
352 printf("en%d: input error istat=%b\n", unit,
353 addr->en_istat, EN_BITS);
354#endif
355 goto flush;
356 }
357#if defined(VAX780) || defined(VAX750)
358 switch (cpu) {
359#if defined(VAX780)
360 case VAX_780:
361 UBA_PURGE780(enuba, enrbdp);
362 break;
363#endif
364#if defined(VAX750)
365 case VAX_750:
366 UBA_PURGE750(enuba, enrbdp);
367 break;
368#endif
369 }
370#endif
371 ip = (struct ip *)((int)rpkt + L1822);
2752c877 372 len = ntohs((u_short *)ip->ip_len) + L1822;
11720282
BJ
373 if (len > sizeof(struct en_packet) || len < sizeof (struct ip)) {
374 printf("enrint: bad ip length %d\n", len);
375 goto flush;
376 }
377 hlen = L1822 + sizeof (struct ip);
378 switch (ip->ip_p) {
379
e1506033 380 case IPPROTO_TCP:
eb44bfb2 381 hlen += ((struct tcpiphdr *)ip)->ti_off << 2;
11720282
BJ
382 break;
383 }
384 MGET(m, 0);
385 if (m == 0)
386 goto flush;
387 top = m;
388 m->m_off = MMINOFF;
389 m->m_len = hlen;
cdad2eb1 390 bcopy((caddr_t)rpkt, mtod(m, caddr_t), hlen);
11720282
BJ
391 len -= hlen;
392 cp = (caddr_t)rpkt + hlen;
393 mp = m;
394 while (len > 0) {
395 MGET(m, 0);
396 if (m == NULL)
397 goto flush;
398 if (len >= PGSIZE) {
399 MPGET(p, 1);
400 if (p == 0)
401 goto nopage;
402 m->m_len = PGSIZE;
403 m->m_off = (int)p - (int)m;
404 if (((int)cp & 0x3ff) == 0) {
d52566dd
BJ
405 struct pte *cpte = &Mbmap[mtopf(cp)*2];
406 struct pte *ppte = &Mbmap[mtopf(p)*2];
11720282
BJ
407 struct pte t;
408 enrswaps++;
409 t = *ppte; *ppte++ = *cpte; *cpte++ = t;
410 t = *ppte; *ppte = *cpte; *cpte = t;
411 mtpr(TBIS, (caddr_t)cp);
412 mtpr(TBIS, (caddr_t)cp+512);
413 mtpr(TBIS, (caddr_t)p);
414 mtpr(TBIS, (caddr_t)p+512);
415 *(int *)(enrmr+1) =
416 cpte[0].pg_pfnum | enrproto;
417 *(int *)(enrmr) =
418 cpte[-1].pg_pfnum | enrproto;
419 goto nocopy;
420 }
421 } else {
422nopage:
423 m->m_len = MIN(MLEN, len);
424 m->m_off = MMINOFF;
425 }
cdad2eb1 426 bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len);
11720282
BJ
427nocopy:
428 cp += m->m_len;
429 len -= m->m_len;
430 mp->m_next = m;
431 mp = m;
432 }
433 m = top;
434 if (imp_stat.inq_head != NULL)
435 imp_stat.inq_tail->m_act = m;
436 else
437 imp_stat.inq_head = m;
438 imp_stat.inq_tail = m;
439#ifdef IMPDEBUG
440 printf("en%d: received packet (%d bytes)\n", unit, len);
441 prt_byte(rpkt, len);
442#endif
443 setsoftnet();
ae348eea 444 goto setup;
11720282
BJ
445flush:
446 m_freem(top);
447#ifdef IMPDEBUG
448 printf("en%d: flushing packet %x\n", unit, top);
449#endif
ae348eea
BJ
450setup:
451 addr->en_iba = imp_stat.iaddr;
452 addr->en_iwc = -600;
941ee7ef 453 addr->en_istat = EN_IEN|EN_GO;
ae348eea 454}
11720282
BJ
455
456#ifdef IMPDEBUG
457prt_byte(s, ct)
458 register char *s;
459 int ct;
460{
461 register i, j, c;
462
463 for (i=0; i<ct; i++) {
464 c = *s++;
465 for (j=0; j<2 ; j++)
466 putchar("0123456789abcdef"[(c>>((1-j)*4))&0xf]);
467 putchar(' ');
468 }
469 putchar('\n');
470}
471#endif IMPDEBUG