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