1 /* if_en.c 4.13 81/11/24 */ 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" 11 #include "../net/inet.h" 12 #include "../net/inet_pcb.h" 13 #include "../net/if.h" 14 #include "../net/inet_systm.h" 15 #include "../net/imp.h" 16 #include "../net/ip.h" 17 #include "../net/ip_var.h" 18 #include "../net/tcp.h" /* XXX */ 19 #include "../net/tcp_var.h" 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 34 int enrswaps; 35 /* int enwswaps; */ 36 int enprobe(), enattach(), enrint(), enxint(), encollide(); 37 struct uba_device *eninfo[NEN]; 38 u_short enstd[] = { 0 }; 39 struct uba_driver endriver = 40 { enprobe, 0, enattach, 0, enstd, "en", eninfo }; 41 42 #define ENUNIT(x) minor(x) 43 44 struct en_packet *xpkt, *rpkt; 45 struct en_prefix { 46 struct en_header enp_h; 47 struct tcpiphdr enp_th; 48 }; 49 struct uba_regs *enuba; 50 struct pte *enrmr, *enxmr; 51 int enrbdp, enwbdp; 52 int enrproto, enwproto; 53 struct pte enxmap[2]; 54 int enxswapd; 55 56 enprobe(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; 64 enrint(0); enxint(0); encollide(0); 65 #endif 66 67 addr->en_istat = 0; 68 addr->en_ostat = 0; 69 addr->en_owc = -1; 70 addr->en_oba = 0; 71 addr->en_ostat = EN_IEN|EN_GO; 72 DELAY(100000); 73 addr->en_ostat = 0; 74 printf("ethernet address %d\n", ~addr->en_addr&0xff); 75 return (1); 76 } 77 78 /*ARGSUSED*/ 79 enattach(ui) 80 struct uba_device *ui; 81 { 82 extern struct ifnet ifen; 83 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; 90 } 91 92 eninit(unit) 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; 110 i = rmalloc(mbmap, n*2); 111 if (i == 0) 112 panic("eninit"); 113 j = i << 1; 114 cp = (char *)pftom(i); 115 if (memall(&Mbmap[j], k, proc, CSYS) == 0) 116 panic("eninit"); 117 vmaccess(&Mbmap[j], (caddr_t)cp, k); 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]; 139 enxmr = &enuba->uba_map[((imp_stat.oaddr>>9)&0x1ff) + 1]; 140 enxmap[0] = enxmr[0]; 141 enxmap[1] = enxmr[1]; 142 enxswapd = 0; 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 154 #if 0 155 enreset(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) 166 ubarelse(uban, &imp_stat.iaddr); 167 if (imp_stat.oaddr) 168 ubarelse(uban, &imp_stat.oaddr); 169 eninit(unit); 170 printf("en%d ", unit); 171 } 172 } 173 #endif 174 175 int enlastdel = 25; 176 int enlastx = 0; 177 enstart(dev) 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; 185 struct uba_device *ui; 186 int enxswapnow = 0; 187 COUNT(ENSTART); 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) { 207 char *dp; 208 if (cp + m->m_len > top) { 209 printf("imp_snd: my packet runneth over\n"); 210 m_freem(m); 211 return; 212 } 213 dp = mtod(m, char *); 214 if (((int)cp&0x3ff)==0 && ((int)dp&0x3ff)==0) { 215 struct pte *pte = &Mbmap[mtopf(dp)*2]; 216 *(int *)enxmr = enwproto | pte++->pg_pfnum; 217 *(int *)(enxmr+1) = enwproto | pte->pg_pfnum; 218 enxswapd = enxswapnow = 1; 219 } else 220 bcopy(mtod(m, caddr_t), cp, 221 (unsigned)m->m_len); 222 cp += m->m_len; 223 /* too soon! */ 224 MFREE(m, mp); 225 m = mp; 226 } 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; 235 } 236 len = ntohs((u_short)(((struct ip *)((int)xpkt + L1822))->ip_len)) + 237 L1822; 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: 246 UBA_PURGE780(enuba, enwbdp); 247 break; 248 #endif 249 #if defined(VAX750) 250 case VAX_750: 251 UBA_PURGE750(enuba, enwbdp); 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 263 addr->en_ostat = EN_IEN|EN_GO; 264 } 265 266 /* 267 * Output interrupt handler. 268 */ 269 enxint(unit) 270 int unit; 271 { 272 register struct endevice *addr; 273 register struct uba_device *ui; 274 COUNT(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; 289 if (addr->en_ostat&EN_OERROR) 290 printf("en%d: output error ostat=%b\n", unit, 291 addr->en_ostat, EN_BITS); 292 imp_stat.outactive = 0; 293 if (imp_stat.outq_head) 294 enstart(unit); 295 else 296 enlastx = 0; 297 } 298 299 int collisions; 300 encollide(unit) 301 int unit; 302 { 303 register struct endevice *addr; 304 register struct uba_device *ui; 305 COUNT(ENCOLLIDE); 306 307 collisions++; 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; 324 imp_stat.endelay = mfpr(ICR) & ~imp_stat.enmask; 325 } 326 enstart(unit); 327 } 328 329 enrint(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; 340 u_int hlen; 341 COUNT(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; 350 if (addr->en_istat&EN_IERROR) { 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); 372 len = ntohs((u_short *)ip->ip_len) + L1822; 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 380 case IPPROTO_TCP: 381 hlen += ((struct tcpiphdr *)ip)->ti_off << 2; 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; 390 bcopy((caddr_t)rpkt, mtod(m, caddr_t), hlen); 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) { 405 struct pte *cpte = &Mbmap[mtopf(cp)*2]; 406 struct pte *ppte = &Mbmap[mtopf(p)*2]; 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 { 422 nopage: 423 m->m_len = MIN(MLEN, len); 424 m->m_off = MMINOFF; 425 } 426 bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len); 427 nocopy: 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(); 444 goto setup; 445 flush: 446 m_freem(top); 447 #ifdef IMPDEBUG 448 printf("en%d: flushing packet %x\n", unit, top); 449 #endif 450 setup: 451 addr->en_iba = imp_stat.iaddr; 452 addr->en_iwc = -600; 453 addr->en_istat = EN_IEN|EN_GO; 454 } 455 456 #ifdef IMPDEBUG 457 prt_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 472