1 /* if_en.c 4.11 81/11/20 */ 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/inet_systm.h" 14 #include "../net/imp.h" 15 #include "../net/ip.h" 16 #include "../net/ip_var.h" 17 #include "../net/tcp.h" /* XXX */ 18 #include "../net/tcp_var.h" 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 33 int enrswaps; 34 /* int enwswaps; */ 35 int enprobe(), enattach(), enrint(), enxint(), encollide(); 36 struct uba_device *eninfo[NEN]; 37 u_short enstd[] = { 0 }; 38 struct uba_driver endriver = 39 { enprobe, 0, enattach, 0, enstd, "en", eninfo }; 40 41 #define ENUNIT(x) minor(x) 42 43 struct en_packet *xpkt, *rpkt; 44 struct en_prefix { 45 struct en_header enp_h; 46 struct tcpiphdr enp_th; 47 }; 48 struct uba_regs *enuba; 49 struct pte *enrmr, *enxmr; 50 int enrbdp, enwbdp; 51 int enrproto, enwproto; 52 struct pte enxmap[2]; 53 int enxswapd; 54 55 enprobe(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; 63 enrint(0); enxint(0); encollide(0); 64 #endif 65 66 addr->en_istat = 0; 67 addr->en_ostat = 0; 68 addr->en_owc = -1; 69 addr->en_oba = 0; 70 addr->en_ostat = EN_IEN|EN_GO; 71 DELAY(100000); 72 addr->en_ostat = 0; 73 printf("ethernet address %d\n", ~addr->en_addr&0xff); 74 return (1); 75 } 76 77 /*ARGSUSED*/ 78 enattach(ui) 79 struct uba_device *ui; 80 { 81 82 } 83 84 eninit(unit) 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; 102 i = rmalloc(mbmap, n*2); 103 if (i == 0) 104 panic("eninit"); 105 j = i << 1; 106 cp = (char *)pftom(i); 107 if (memall(&Mbmap[j], k, proc, CSYS) == 0) 108 panic("eninit"); 109 vmaccess(&Mbmap[j], (caddr_t)cp, k); 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]; 131 enxmr = &enuba->uba_map[((imp_stat.oaddr>>9)&0x1ff) + 1]; 132 enxmap[0] = enxmr[0]; 133 enxmap[1] = enxmr[1]; 134 enxswapd = 0; 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 146 #if 0 147 enreset(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) 158 ubarelse(uban, &imp_stat.iaddr); 159 if (imp_stat.oaddr) 160 ubarelse(uban, &imp_stat.oaddr); 161 eninit(unit); 162 printf("en%d ", unit); 163 } 164 } 165 #endif 166 167 int enlastdel = 25; 168 int enlastx = 0; 169 enstart(dev) 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; 177 struct uba_device *ui; 178 int enxswapnow = 0; 179 COUNT(ENSTART); 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) { 199 char *dp; 200 if (cp + m->m_len > top) { 201 printf("imp_snd: my packet runneth over\n"); 202 m_freem(m); 203 return; 204 } 205 dp = mtod(m, char *); 206 if (((int)cp&0x3ff)==0 && ((int)dp&0x3ff)==0) { 207 struct pte *pte = &Mbmap[mtopf(dp)*2]; 208 *(int *)enxmr = enwproto | pte++->pg_pfnum; 209 *(int *)(enxmr+1) = enwproto | pte->pg_pfnum; 210 enxswapd = enxswapnow = 1; 211 } else 212 bcopy(mtod(m, caddr_t), cp, 213 (unsigned)m->m_len); 214 cp += m->m_len; 215 /* too soon! */ 216 MFREE(m, mp); 217 m = mp; 218 } 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; 227 } 228 len = ntohs((u_short)(((struct ip *)((int)xpkt + L1822))->ip_len)) + 229 L1822; 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: 238 UBA_PURGE780(enuba, enwbdp); 239 break; 240 #endif 241 #if defined(VAX750) 242 case VAX_750: 243 UBA_PURGE750(enuba, enwbdp); 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 255 addr->en_ostat = EN_IEN|EN_GO; 256 } 257 258 /* 259 * Output interrupt handler. 260 */ 261 enxint(unit) 262 int unit; 263 { 264 register struct endevice *addr; 265 register struct uba_device *ui; 266 COUNT(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; 281 if (addr->en_ostat&EN_OERROR) 282 printf("en%d: output error ostat=%b\n", unit, 283 addr->en_ostat, EN_BITS); 284 imp_stat.outactive = 0; 285 if (imp_stat.outq_head) 286 enstart(unit); 287 else 288 enlastx = 0; 289 } 290 291 int collisions; 292 encollide(unit) 293 int unit; 294 { 295 register struct endevice *addr; 296 register struct uba_device *ui; 297 COUNT(ENCOLLIDE); 298 299 collisions++; 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; 316 imp_stat.endelay = mfpr(ICR) & ~imp_stat.enmask; 317 } 318 enstart(unit); 319 } 320 321 enrint(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; 332 u_int hlen; 333 COUNT(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; 342 if (addr->en_istat&EN_IERROR) { 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); 364 len = ntohs((u_short *)ip->ip_len) + L1822; 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 372 case IPPROTO_TCP: 373 hlen += ((struct tcpiphdr *)ip)->ti_off << 2; 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; 382 bcopy((caddr_t)rpkt, mtod(m, caddr_t), hlen); 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) { 397 struct pte *cpte = &Mbmap[mtopf(cp)*2]; 398 struct pte *ppte = &Mbmap[mtopf(p)*2]; 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 { 414 nopage: 415 m->m_len = MIN(MLEN, len); 416 m->m_off = MMINOFF; 417 } 418 bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len); 419 nocopy: 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(); 436 goto setup; 437 flush: 438 m_freem(top); 439 #ifdef IMPDEBUG 440 printf("en%d: flushing packet %x\n", unit, top); 441 #endif 442 setup: 443 addr->en_iba = imp_stat.iaddr; 444 addr->en_iwc = -600; 445 addr->en_istat = EN_IEN|EN_GO; 446 } 447 448 #ifdef IMPDEBUG 449 prt_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 464