1 /* if_en.c 4.9 81/11/16 */ 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(), enxint(), encollide(); 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 enreset(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) 157 ubarelse(uban, &imp_stat.iaddr); 158 if (imp_stat.oaddr) 159 ubarelse(uban, &imp_stat.oaddr); 160 eninit(unit); 161 printf("en%d ", unit); 162 } 163 } 164 165 int enlastdel = 25; 166 int enlastx = 0; 167 enstart(dev) 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; 175 struct uba_device *ui; 176 int enxswapnow = 0; 177 COUNT(ENSTART); 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) { 197 char *dp; 198 if (cp + m->m_len > top) { 199 printf("imp_snd: my packet runneth over\n"); 200 m_freem(m); 201 return; 202 } 203 dp = mtod(m, char *); 204 if (((int)cp&0x3ff)==0 && ((int)dp&0x3ff)==0) { 205 struct pte *pte = &Mbmap[mtopf(dp)*2]; 206 *(int *)enxmr = enwproto | pte++->pg_pfnum; 207 *(int *)(enxmr+1) = enwproto | pte->pg_pfnum; 208 enxswapd = enxswapnow = 1; 209 } else 210 bcopy(mtod(m, caddr_t), cp, 211 (unsigned)m->m_len); 212 cp += m->m_len; 213 /* too soon! */ 214 MFREE(m, mp); 215 m = mp; 216 } 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; 225 } 226 len = ntohs((u_short)(((struct ip *)((int)xpkt + L1822))->ip_len)) + 227 L1822; 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: 236 UBA_PURGE780(enuba, enwbdp); 237 break; 238 #endif 239 #if defined(VAX750) 240 case VAX_750: 241 UBA_PURGE750(enuba, enwbdp); 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 253 addr->en_ostat = EN_IEN|EN_GO; 254 } 255 256 /* 257 * Output interrupt handler. 258 */ 259 enxint(unit) 260 int unit; 261 { 262 register struct endevice *addr; 263 register struct uba_device *ui; 264 COUNT(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; 279 if (addr->en_ostat&EN_OERROR) 280 printf("en%d: output error ostat=%b\n", unit, 281 addr->en_ostat, EN_BITS); 282 imp_stat.outactive = 0; 283 if (imp_stat.outq_head) 284 enstart(unit); 285 else 286 enlastx = 0; 287 } 288 289 int collisions; 290 encollide(unit) 291 int unit; 292 { 293 register struct endevice *addr; 294 register struct uba_device *ui; 295 COUNT(ENCOLLIDE); 296 297 collisions++; 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; 314 imp_stat.endelay = mfpr(ICR) & ~imp_stat.enmask; 315 } 316 enstart(unit); 317 } 318 319 enrint(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; 330 u_int hlen; 331 COUNT(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; 340 if (addr->en_istat&EN_IERROR) { 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 370 case IPPROTO_TCP: 371 hlen += ((struct tcpiphdr *)ip)->ti_off << 2; 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; 380 bcopy((caddr_t)rpkt, mtod(m, caddr_t), hlen); 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) { 395 struct pte *cpte = &Mbmap[mtopf(cp)*2]; 396 struct pte *ppte = &Mbmap[mtopf(p)*2]; 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 { 412 nopage: 413 m->m_len = MIN(MLEN, len); 414 m->m_off = MMINOFF; 415 } 416 bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len); 417 nocopy: 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(); 434 goto setup; 435 flush: 436 m_freem(top); 437 #ifdef IMPDEBUG 438 printf("en%d: flushing packet %x\n", unit, top); 439 #endif 440 setup: 441 addr->en_iba = imp_stat.iaddr; 442 addr->en_iwc = -600; 443 addr->en_istat = EN_IEN|EN_GO; 444 } 445 446 #ifdef IMPDEBUG 447 prt_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 462