fixed bug making 2dd screw up on vt100's with "set number".
[unix-history] / usr / src / sys / vax / if / if_en.c
CommitLineData
cdad2eb1 1/* if_en.c 4.9 81/11/16 */
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;
cdad2eb1 63 enrint(), enxint(), encollide();
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
146enreset(uban)
147 int uban;
148{
149 register int unit;
150 struct uba_device *ui;
151
152 for (unit = 0; unit < NEN; unit++) {
153 ui = eninfo[unit];
154 if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
155 continue;
156 if (imp_stat.iaddr)
cdad2eb1 157 ubarelse(uban, &imp_stat.iaddr);
11720282 158 if (imp_stat.oaddr)
cdad2eb1 159 ubarelse(uban, &imp_stat.oaddr);
ae348eea 160 eninit(unit);
11720282
BJ
161 printf("en%d ", unit);
162 }
163}
164
3552a746
BJ
165int enlastdel = 25;
166int enlastx = 0;
ae348eea 167enstart(dev)
11720282
BJ
168 dev_t dev;
169{
170 register struct mbuf *m, *mp;
171 register struct endevice *addr;
172 register caddr_t cp, top;
173 int unit;
174 register int len;
11720282 175 struct uba_device *ui;
ae348eea
BJ
176 int enxswapnow = 0;
177COUNT(ENSTART);
11720282
BJ
178
179 unit = ENUNIT(dev);
180 ui = eninfo[unit];
181 if (ui == 0 || ui->ui_alive == 0) {
182 printf("en%d (imp_output): not alive\n", unit);
183 return;
184 }
185 addr = (struct endevice *)ui->ui_addr;
186 if (!imp_stat.outactive) {
187 if ((m = imp_stat.outq_head) == NULL)
188 return;
189 imp_stat.outactive = 1; /* set myself active */
190 imp_stat.outq_head = m->m_act; /* -> next packet chain */
191 /*
192 * Pack mbufs into ethernet packet.
193 */
194 cp = (caddr_t)xpkt;
195 top = (caddr_t)xpkt + sizeof(struct en_packet);
196 while (m != NULL) {
ae348eea 197 char *dp;
11720282
BJ
198 if (cp + m->m_len > top) {
199 printf("imp_snd: my packet runneth over\n");
200 m_freem(m);
201 return;
202 }
ae348eea
BJ
203 dp = mtod(m, char *);
204 if (((int)cp&0x3ff)==0 && ((int)dp&0x3ff)==0) {
d52566dd 205 struct pte *pte = &Mbmap[mtopf(dp)*2];
ae348eea
BJ
206 *(int *)enxmr = enwproto | pte++->pg_pfnum;
207 *(int *)(enxmr+1) = enwproto | pte->pg_pfnum;
208 enxswapd = enxswapnow = 1;
209 } else
cdad2eb1
BJ
210 bcopy(mtod(m, caddr_t), cp,
211 (unsigned)m->m_len);
11720282 212 cp += m->m_len;
ae348eea 213 /* too soon! */
11720282
BJ
214 MFREE(m, mp);
215 m = mp;
216 }
3552a746
BJ
217 if (enxswapnow == 0 && enxswapd) {
218 enxmr[0] = enxmap[0];
219 enxmr[1] = enxmap[1];
220 }
221 if (enlastx && enlastx == xpkt->Header.en_dhost)
222 imp_stat.endelay = enlastdel;
223 else
224 enlastx = xpkt->Header.en_dhost;
ae348eea 225 }
cdad2eb1
BJ
226 len = ntohs((u_short)(((struct ip *)((int)xpkt + L1822))->ip_len)) +
227 L1822;
11720282
BJ
228 if (len > sizeof(struct en_packet)) {
229 printf("imp_output: ridiculous IP length %d\n", len);
230 return;
231 }
232#if defined(VAX780) || defined(VAX750)
233 switch (cpu) {
234#if defined(VAX780)
235 case VAX_780:
ae348eea 236 UBA_PURGE780(enuba, enwbdp);
11720282
BJ
237 break;
238#endif
239#if defined(VAX750)
240 case VAX_750:
ae348eea 241 UBA_PURGE750(enuba, enwbdp);
11720282
BJ
242 break;
243#endif
244 }
245#endif
246 addr->en_oba = imp_stat.oaddr;
247 addr->en_odelay = imp_stat.endelay;
248 addr->en_owc = -((len + 1) >> 1);
249#ifdef IMPDEBUG
250 printf("en%d: sending packet (%d bytes)\n", unit, len);
251 prt_byte(xpkt, len);
252#endif
941ee7ef 253 addr->en_ostat = EN_IEN|EN_GO;
11720282
BJ
254}
255
11720282
BJ
256/*
257 * Output interrupt handler.
258 */
259enxint(unit)
260 int unit;
261{
262 register struct endevice *addr;
263 register struct uba_device *ui;
264COUNT(ENXINT);
265
266 ui = eninfo[unit];
267 addr = (struct endevice *)ui->ui_addr;
268
269#ifdef IMPDEBUG
270 printf("en%d: enxint ostat=%b\n", unit, addr->en_ostat, EN_BITS);
271#endif
272 if (!imp_stat.outactive) {
273 printf("en%d: phantom output intr ostat=%b\n",
274 unit, addr->en_ostat, EN_BITS);
275 return;
276 }
277 imp_stat.endelay = 0;
278 imp_stat.enmask = ~0;
941ee7ef 279 if (addr->en_ostat&EN_OERROR)
11720282
BJ
280 printf("en%d: output error ostat=%b\n", unit,
281 addr->en_ostat, EN_BITS);
282 imp_stat.outactive = 0;
ae348eea
BJ
283 if (imp_stat.outq_head)
284 enstart(unit);
3552a746
BJ
285 else
286 enlastx = 0;
11720282
BJ
287}
288
3552a746 289int collisions;
11720282
BJ
290encollide(unit)
291 int unit;
292{
293 register struct endevice *addr;
294 register struct uba_device *ui;
295COUNT(ENCOLLIDE);
296
3552a746 297 collisions++;
11720282
BJ
298 ui = eninfo[unit];
299 addr = (struct endevice *)ui->ui_addr;
300
301#ifdef IMPDEBUG
302 printf("en%d: collision ostat=%b\n", unit, addr->en_ostat, EN_BITS);
303#endif
304 if (!imp_stat.outactive) {
305 printf("en%d: phantom collision intr ostat=%b\n",
306 unit, addr->en_ostat, EN_BITS);
307 return;
308 }
309 if (imp_stat.enmask == 0) {
310 printf("en%d: output error ostat=%b\n", unit,
311 addr->en_ostat, EN_BITS);
312 } else {
313 imp_stat.enmask <<= 1;
3552a746 314 imp_stat.endelay = mfpr(ICR) & ~imp_stat.enmask;
11720282 315 }
ae348eea 316 enstart(unit);
11720282
BJ
317}
318
319enrint(unit)
320 int unit;
321{
322 register struct mbuf *m;
323 struct mbuf *mp;
324 register struct endevice *addr;
325 register struct uba_device *ui;
326 register int len;
327 register caddr_t cp;
328 struct mbuf *p, *top = 0;
329 struct ip *ip;
cdad2eb1 330 u_int hlen;
11720282
BJ
331COUNT(ENRINT);
332
333 ui = eninfo[unit];
334 addr = (struct endevice *)ui->ui_addr;
335#ifdef IMPDEBUG
336 printf("en%d: enrint istat=%b\n", unit, addr->en_istat, EN_BITS);
337#endif
338 if (imp_stat.flush)
339 goto flush;
941ee7ef 340 if (addr->en_istat&EN_IERROR) {
11720282
BJ
341#ifdef notdef
342 printf("en%d: input error istat=%b\n", unit,
343 addr->en_istat, EN_BITS);
344#endif
345 goto flush;
346 }
347#if defined(VAX780) || defined(VAX750)
348 switch (cpu) {
349#if defined(VAX780)
350 case VAX_780:
351 UBA_PURGE780(enuba, enrbdp);
352 break;
353#endif
354#if defined(VAX750)
355 case VAX_750:
356 UBA_PURGE750(enuba, enrbdp);
357 break;
358#endif
359 }
360#endif
361 ip = (struct ip *)((int)rpkt + L1822);
362 len = ntohs(ip->ip_len) + L1822;
363 if (len > sizeof(struct en_packet) || len < sizeof (struct ip)) {
364 printf("enrint: bad ip length %d\n", len);
365 goto flush;
366 }
367 hlen = L1822 + sizeof (struct ip);
368 switch (ip->ip_p) {
369
e1506033 370 case IPPROTO_TCP:
eb44bfb2 371 hlen += ((struct tcpiphdr *)ip)->ti_off << 2;
11720282
BJ
372 break;
373 }
374 MGET(m, 0);
375 if (m == 0)
376 goto flush;
377 top = m;
378 m->m_off = MMINOFF;
379 m->m_len = hlen;
cdad2eb1 380 bcopy((caddr_t)rpkt, mtod(m, caddr_t), hlen);
11720282
BJ
381 len -= hlen;
382 cp = (caddr_t)rpkt + hlen;
383 mp = m;
384 while (len > 0) {
385 MGET(m, 0);
386 if (m == NULL)
387 goto flush;
388 if (len >= PGSIZE) {
389 MPGET(p, 1);
390 if (p == 0)
391 goto nopage;
392 m->m_len = PGSIZE;
393 m->m_off = (int)p - (int)m;
394 if (((int)cp & 0x3ff) == 0) {
d52566dd
BJ
395 struct pte *cpte = &Mbmap[mtopf(cp)*2];
396 struct pte *ppte = &Mbmap[mtopf(p)*2];
11720282
BJ
397 struct pte t;
398 enrswaps++;
399 t = *ppte; *ppte++ = *cpte; *cpte++ = t;
400 t = *ppte; *ppte = *cpte; *cpte = t;
401 mtpr(TBIS, (caddr_t)cp);
402 mtpr(TBIS, (caddr_t)cp+512);
403 mtpr(TBIS, (caddr_t)p);
404 mtpr(TBIS, (caddr_t)p+512);
405 *(int *)(enrmr+1) =
406 cpte[0].pg_pfnum | enrproto;
407 *(int *)(enrmr) =
408 cpte[-1].pg_pfnum | enrproto;
409 goto nocopy;
410 }
411 } else {
412nopage:
413 m->m_len = MIN(MLEN, len);
414 m->m_off = MMINOFF;
415 }
cdad2eb1 416 bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len);
11720282
BJ
417nocopy:
418 cp += m->m_len;
419 len -= m->m_len;
420 mp->m_next = m;
421 mp = m;
422 }
423 m = top;
424 if (imp_stat.inq_head != NULL)
425 imp_stat.inq_tail->m_act = m;
426 else
427 imp_stat.inq_head = m;
428 imp_stat.inq_tail = m;
429#ifdef IMPDEBUG
430 printf("en%d: received packet (%d bytes)\n", unit, len);
431 prt_byte(rpkt, len);
432#endif
433 setsoftnet();
ae348eea 434 goto setup;
11720282
BJ
435flush:
436 m_freem(top);
437#ifdef IMPDEBUG
438 printf("en%d: flushing packet %x\n", unit, top);
439#endif
ae348eea
BJ
440setup:
441 addr->en_iba = imp_stat.iaddr;
442 addr->en_iwc = -600;
941ee7ef 443 addr->en_istat = EN_IEN|EN_GO;
ae348eea 444}
11720282
BJ
445
446#ifdef IMPDEBUG
447prt_byte(s, ct)
448 register char *s;
449 int ct;
450{
451 register i, j, c;
452
453 for (i=0; i<ct; i++) {
454 c = *s++;
455 for (j=0; j<2 ; j++)
456 putchar("0123456789abcdef"[(c>>((1-j)*4))&0xf]);
457 putchar(' ');
458 }
459 putchar('\n');
460}
461#endif IMPDEBUG