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