1 #include "ne.h" 2 #if NNE > 0 3 /*- 4 * NE2000 Ethernet driver 5 * Copyright (C) 1990,91 W. Jolitz 6 * Copyright (c) 1990 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)if_ne.c 7.1 (Berkeley) 05/09/91 12 * 13 * Parts inspired from Tim Tucker's if_wd driver for the wd8003, 14 * insight on the ne2000 gained from Robert Clements PC/FTP driver. 15 */ 16 17 #include "param.h" 18 #include "systm.h" 19 #include "mbuf.h" 20 #include "buf.h" 21 #include "protosw.h" 22 #include "socket.h" 23 #include "ioctl.h" 24 #include "errno.h" 25 #include "syslog.h" 26 27 #include "net/if.h" 28 #include "net/netisr.h" 29 #include "net/route.h" 30 31 #ifdef INET 32 #include "netinet/in.h" 33 #include "netinet/in_systm.h" 34 #include "netinet/in_var.h" 35 #include "netinet/ip.h" 36 #include "netinet/if_ether.h" 37 #endif 38 39 #ifdef NS 40 #include "netns/ns.h" 41 #include "netns/ns_if.h" 42 #endif 43 44 #include "i386/isa/isa_device.h" 45 #include "i386/isa/if_nereg.h" 46 #include "i386/isa/icu.h" 47 48 int neprobe(), neattach(), neintr(); 49 int nestart(),neinit(), ether_output(), neioctl(); 50 51 struct isa_driver nedriver = { 52 neprobe, neattach, "ne", 53 }; 54 55 struct mbuf *neget(); 56 57 /* 58 * Ethernet software status per interface. 59 * 60 * Each interface is referenced by a network interface structure, 61 * ns_if, which the routing code uses to locate the interface. 62 * This structure contains the output queue for the interface, its address, ... 63 */ 64 struct ne_softc { 65 struct arpcom ns_ac; /* Ethernet common part */ 66 #define ns_if ns_ac.ac_if /* network-visible interface */ 67 #define ns_addr ns_ac.ac_enaddr /* hardware Ethernet address */ 68 int ns_flags; 69 #define DSF_LOCK 1 /* block re-entering enstart */ 70 int ns_oactive ; 71 int ns_mask ; 72 int ns_ba; /* byte addr in buffer ram of inc pkt */ 73 int ns_cur; /* current page being filled */ 74 struct prhdr ns_ph; /* hardware header of incoming packet*/ 75 struct ether_header ns_eh; /* header of incoming packet */ 76 u_char ns_pb[2048 /*ETHERMTU+sizeof(long)*/]; 77 } ne_softc[NNE] ; 78 #define ENBUFSIZE (sizeof(struct ether_header) + ETHERMTU + 2 + 64) 79 80 int nec; 81 82 u_short boarddata[16]; 83 84 neprobe(dvp) 85 struct isa_device *dvp; 86 { 87 int val,i,s; 88 register struct ne_softc *ns = &ne_softc[0]; 89 90 #ifdef lint 91 neintr(0); 92 #endif 93 94 nec = dvp->id_iobase; 95 s = splimp(); 96 97 /* reset the bastard */ 98 val = inb(nec+ne_reset); 99 DELAY(2000000); 100 outb(nec+ne_reset,val); 101 102 outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA); 103 104 i = 1000000; 105 while ((inb(nec+ds0_isr)&DSIS_RESET) == 0 && i-- > 0); 106 if (i < 0) return (0); 107 108 outb(nec+ds0_isr, 0xff); 109 110 /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */ 111 outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1); 112 113 outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); 114 DELAY(10000); 115 116 /* check cmd reg and fail if not right */ 117 if ((i=inb(nec+ds_cmd)) != (DSCM_NODMA|DSCM_PG0|DSCM_STOP)) 118 return(0); 119 120 outb(nec+ds0_tcr, 0); 121 outb(nec+ds0_rcr, DSRC_MON); 122 outb(nec+ds0_pstart, RBUF/DS_PGSIZE); 123 outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE); 124 outb(nec+ds0_bnry, RBUFEND/DS_PGSIZE); 125 outb(nec+ds0_imr, 0); 126 outb(nec+ds0_isr, 0); 127 outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP); 128 outb(nec+ds1_curr, RBUF/DS_PGSIZE); 129 outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); 130 fetchrom (boarddata, 0, sizeof(boarddata)); 131 #ifdef NEDEBUG 132 /*{ int i,rom; 133 rom=1; 134 printf("ne ram "); 135 for (i = 0; i < 0xfff0; i+=4) { 136 int pat; 137 pat = 0xa55a+i*37; 138 putram(&pat,i,4); 139 fetchram(&pat,i,4); 140 if (pat == 0xa55a+i*37) { 141 if (rom) { rom=0; printf(" %x", i); } 142 } else { 143 if (!rom) { rom=1; printf("..%x ", i); } 144 } 145 pat=0; 146 putram(&pat,i,4); 147 } 148 printf("\n"); 149 }*/ 150 #endif 151 /* checksum data? */ 152 /* extract board address */ 153 for(i=0; i < 6; i++) ns->ns_addr[i] = boarddata[i]; 154 splx(s); 155 return (1); 156 } 157 158 fetchrom (up, ad, len) u_short *up; { 159 u_char cmd; 160 161 cmd = inb(nec+ds_cmd); 162 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); 163 outb (nec+ds0_isr, DSIS_RDC); 164 outb (nec+ds0_rbcr0, len&0xff); 165 outb (nec+ds0_rbcr1, (len>>8)&0xff); 166 outb (nec+ds0_rsar0, ad&0xff); 167 outb (nec+ds0_rsar1, (ad>>8)&0xff); 168 outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START); 169 insw (nec+ne_data, up, len/2); 170 pausestr ("x",1); 171 while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) pausestr("fetchrom",0); 172 outb (nec+ds0_isr, DSIS_RDC); 173 outb (nec+ds_cmd, cmd); 174 } 175 176 static recur; 177 fetchram (up, ad, len) caddr_t up; { 178 u_char cmd; 179 180 recur++; 181 cmd = inb(nec+ds_cmd); 182 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); 183 outb (nec+ds0_isr, DSIS_RDC); 184 outb (nec+ds0_rbcr0, len&0xff); 185 outb (nec+ds0_rbcr1, (len>>8)&0xff); 186 outb (nec+ds0_rsar0, ad&0xff); 187 outb (nec+ds0_rsar1, (ad>>8)&0xff); 188 outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START); 189 insw (nec+ne_data, up, len/2); 190 pausestr ("x",1); 191 while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) pausestr("fetchram",0); 192 outb (nec+ds0_isr, DSIS_RDC); 193 outb (nec+ds_cmd, cmd); 194 recur--; 195 } 196 197 putram (up, ad, len) caddr_t up; { 198 u_char cmd; 199 200 recur++; 201 cmd = inb(nec+ds_cmd); 202 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); 203 outb (nec+ds0_isr, DSIS_RDC); 204 if(len&1) len++; 205 outb (nec+ds0_rbcr0, len&0xff); 206 outb (nec+ds0_rbcr1, (len>>8)&0xff); 207 outb (nec+ds0_rsar0, ad&0xff); 208 outb (nec+ds0_rsar1, (ad>>8)&0xff); 209 outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START); 210 outsw (nec+ne_data, up, len/2); 211 pausestr ("x",1); 212 while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) 213 if(pausestr("putram",0)<0) break; 214 outb (nec+ds0_isr, DSIS_RDC); 215 outb (nec+ds_cmd, cmd); 216 recur--; 217 } 218 219 /* 220 * Reset of interface. 221 */ 222 nereset(unit, uban) 223 int unit, uban; 224 { 225 if (unit >= NNE) 226 return; 227 printf("ne%d: reset\n", unit); 228 ne_softc[unit].ns_flags &= ~DSF_LOCK; 229 neinit(unit); 230 } 231 232 /* 233 * Interface exists: make available by filling in network interface 234 * record. System will initialize the interface when it is ready 235 * to accept packets. We get the ethernet address here. 236 */ 237 neattach(dvp) 238 struct isa_device *dvp; 239 { 240 int unit = dvp->id_unit; 241 register struct ne_softc *ns = &ne_softc[unit]; 242 register struct ifnet *ifp = &ns->ns_if; 243 244 ifp->if_unit = unit; 245 ifp->if_name = nedriver.name ; 246 ifp->if_mtu = ETHERMTU; 247 printf (" ethernet address %s", ether_sprintf(ns->ns_addr)) ; 248 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; 249 ifp->if_init = neinit; 250 ifp->if_output = ether_output; 251 ifp->if_start = nestart; 252 ifp->if_ioctl = neioctl; 253 ifp->if_reset = nereset; 254 ifp->if_watchdog = 0; 255 if_attach(ifp); 256 } 257 258 /* 259 * Initialization of interface; set up initialization block 260 * and transmit/receive descriptor rings. 261 */ 262 neinit(unit) 263 int unit; 264 { 265 register struct ne_softc *ns = &ne_softc[unit]; 266 struct ifnet *ifp = &ns->ns_if; 267 int s; 268 register i; char *cp; 269 270 if (ifp->if_addrlist == (struct ifaddr *)0) return; 271 if (ifp->if_flags & IFF_RUNNING) return; 272 273 s = splimp(); 274 275 /* set physical address on ethernet */ 276 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP); 277 for (i=0 ; i < 6 ; i++) outb(nec+ds1_par0+i,ns->ns_addr[i]); 278 279 /* clr logical address hash filter for now */ 280 for (i=0 ; i < 8 ; i++) outb(nec+ds1_mar0+i,0xff); 281 282 /* init regs */ 283 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); 284 outb (nec+ds0_rbcr0, 0); 285 outb (nec+ds0_rbcr1, 0); 286 outb (nec+ds0_imr, 0); 287 outb (nec+ds0_isr, 0xff); 288 /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */ 289 outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1); 290 outb(nec+ds0_tcr, 0); 291 outb (nec+ds0_rcr, DSRC_MON); 292 outb (nec+ds0_tpsr, 0); 293 outb(nec+ds0_pstart, RBUF/DS_PGSIZE); 294 outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE); 295 outb(nec+ds0_bnry, RBUF/DS_PGSIZE); 296 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP); 297 outb(nec+ds1_curr, RBUF/DS_PGSIZE); 298 ns->ns_cur = RBUF/DS_PGSIZE; 299 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); 300 outb (nec+ds0_rcr, DSRC_AB); 301 outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1); 302 outb (nec+ds0_imr, 0xff); 303 304 ns->ns_if.if_flags |= IFF_RUNNING; 305 ns->ns_oactive = 0; ns->ns_mask = ~0; 306 nestart(ifp); 307 splx(s); 308 } 309 310 /* 311 * Setup output on interface. 312 * Get another datagram to send off of the interface queue, 313 * and map it to the interface before starting the output. 314 * called only at splimp or interrupt level. 315 */ 316 nestart(ifp) 317 struct ifnet *ifp; 318 { 319 register struct ne_softc *ns = &ne_softc[ifp->if_unit]; 320 struct mbuf *m0, *m; 321 int buffer; 322 int len = 0, i, total,t; 323 324 /* 325 * The DS8390 has only one transmit buffer, if it is busy we 326 * must wait until the transmit interrupt completes. 327 */ 328 outb(nec+ds_cmd,DSCM_NODMA|DSCM_START); 329 330 if (ns->ns_flags & DSF_LOCK) 331 return; 332 333 if (inb(nec+ds_cmd) & DSCM_TRANS) 334 return; 335 336 if ((ns->ns_if.if_flags & IFF_RUNNING) == 0) 337 return; 338 339 IF_DEQUEUE(&ns->ns_if.if_snd, m); 340 341 if (m == 0) 342 return; 343 344 if ((m->m_flags & M_PKTHDR) == 0) 345 printf("should panic: no packet header\n"); 346 /* 347 * Copy the mbuf chain into the transmit buffer 348 */ 349 350 ns->ns_flags |= DSF_LOCK; /* prevent entering nestart */ 351 buffer = TBUF; len = i = 0; 352 t = 0; 353 #include "machine/dbg.h" 354 dprintf(DPAGIN,"\n before: "); 355 for (m0 = m; m != 0; m = m->m_next) { 356 t += m->m_len; 357 dprintf(DPAGIN,"%d ", m->m_len); 358 } 359 360 m = m0; 361 total = t; 362 if (m->m_flags & M_PKTHDR && total != m->m_pkthdr.len) 363 printf("hdr fucked, len %d should be %d\n", total, m->m_pkthdr.len); 364 dprintf(DPAGIN,"\n after: "); 365 for (m0 = m; m != 0; ) { 366 367 /*int j;*/ 368 if (m->m_len&1 && t > m->m_len) { 369 dprintf(DPAGIN|DPAUSE,"+%d:%d ", m->m_len, m->m_next->m_len); 370 putram(mtod(m, caddr_t), buffer, m->m_len - 1); 371 t -= m->m_len - 1; 372 buffer += m->m_len - 1; 373 m->m_data += m->m_len - 1; 374 m->m_len = 1; 375 m = m_pullup(m, 2); 376 if(m == 0) panic("bloowie!"); 377 { struct mbuf *mp; 378 dprintf(DPAGIN|DPAUSE, "\n rewritten as: "); 379 for (mp = m; mp != 0; mp = mp->m_next) 380 dprintf(DPAGIN,"%d ", mp->m_len); 381 } 382 dprintf(DPAGIN,"\n"); 383 } else { 384 dprintf(DPAGIN|DPAUSE,"%d ", m->m_len); 385 putram(mtod(m, caddr_t), buffer, m->m_len); 386 buffer += m->m_len; 387 t -= m->m_len; 388 MFREE(m, m0); 389 m = m0; 390 } 391 /*for(j=0; i < len;i++,j++) puthex(mtod(m,u_char *)[j]); 392 printf("|"); */ 393 } 394 dprintf(DPAGIN|DPAUSE,"send %d\n", total); 395 396 /* 397 * Init transmit length registers, and set transmit start flag. 398 */ 399 400 #ifdef NEDEBUGx 401 if(len < 0 || len > 1536) 402 pg("T Bogus Length %d\n", len); 403 dprintf(DEXPAND,"snd %d ", len); 404 #endif 405 len = total; 406 if (len < 64) len = 64; 407 outb(nec+ds0_tbcr0,len&0xff); 408 outb(nec+ds0_tbcr1,(len>>8)&0xff); 409 outb(nec+ds0_tpsr, TBUF/DS_PGSIZE); 410 outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START); 411 } 412 413 #define succ(n) (((n)+1 >= RBUFEND/DS_PGSIZE) ? RBUF/DS_PGSIZE : (n)+1) 414 #define pred(n) (((n)-1 < RBUF/DS_PGSIZE) ? RBUFEND/DS_PGSIZE-1 : (n)-1) 415 /* 416 * Controller interrupt. 417 */ 418 neintr(unit) 419 { 420 register struct ne_softc *ns = &ne_softc[unit]; 421 u_char cmd,isr; 422 static cnt; 423 424 /* save cmd, clear interrupt */ 425 cmd = inb (nec+ds_cmd); 426 loop: 427 isr = inb (nec+ds0_isr); 428 #ifdef NEDEBUGx 429 dprintf(DEXPAND,"|ppl %x isr %x ", ppl, isr); 430 #endif 431 432 outb(nec+ds_cmd,DSCM_NODMA|DSCM_START); 433 outb(nec+ds0_isr, isr); 434 435 436 if (isr & (/*DSIS_RXE|DSIS_TXE|*/DSIS_ROVRN)) 437 log(LOG_ERR, "ne%d: error: isr %x\n", ns-ne_softc, isr/*, DSIS_BITS*/); 438 439 #ifdef notdef 440 /* receiver ovverun? */ 441 if (isr & DSIS_ROVRN) { 442 u_char pend,lastfree; 443 444 outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA); 445 outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA|DSCM_PG1); 446 pend = inb(nec+ds1_curr); 447 outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA|DSCM_PG0); 448 lastfree = inb(nec+ds0_bnry); 449 #ifdef NEDEBUG 450 printf("Cur %x pend %x lastfree %x ", ns->ns_cur, pend, lastfree); 451 #endif 452 /* have we wrapped */ 453 if (lastfree >= RBUFEND/DS_PGSIZE) 454 lastfree = RBUF/DS_PGSIZE; 455 /* something in the buffer? */ 456 if (pend != succ(lastfree)) { 457 u_char nxt; 458 459 fetchram(&ns->ns_ph,ns->ns_cur*DS_PGSIZE, sizeof(ns->ns_ph)); 460 ns->ns_ba = ns->ns_cur*DS_PGSIZE+sizeof(ns->ns_ph); 461 462 if (ns->ns_ph.pr_status & DSRS_RPC) 463 nerecv (ns); 464 465 nxt = ns->ns_ph.pr_nxtpg ; 466 #ifdef NEDEBUG 467 printf("nxt %x ", nxt); 468 #endif 469 /* sanity check */ 470 if ( nxt >= RBUF/DS_PGSIZE 471 && nxt <= RBUFEND/DS_PGSIZE && nxt <= pend) 472 ns->ns_cur = nxt; 473 else ns->ns_cur = nxt = pend; 474 lastfree = pred(nxt); 475 outb(nec+ds0_bnry, lastfree); 476 } else ns->ns_cur = pend; 477 478 outb(nec+ds0_rbcr0,0); 479 outb(nec+ds0_rbcr1,0); 480 outb(nec+ds0_tcr,DSTC_LB0); 481 outb(nec+ds0_rcr, DSRC_MON); 482 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA); 483 outb (nec+ds0_rcr, DSRC_AB); 484 outb(nec+ds0_tcr,0); 485 } 486 #endif 487 488 /* receiver error */ 489 if (isr & DSIS_RXE) { 490 /* need to read these registers to clear status */ 491 (void) inb(nec+ ds0_rsr); 492 (void) inb(nec+ 0xD); 493 (void) inb(nec + 0xE); 494 (void) inb(nec + 0xF); 495 ns->ns_if.if_ierrors++; 496 } 497 498 if (isr & (DSIS_RX|DSIS_RXE|DSIS_ROVRN)) { 499 u_char pend,lastfree; 500 501 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1); 502 pend = inb(nec+ds1_curr); 503 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0); 504 lastfree = inb(nec+ds0_bnry); 505 #ifdef NEDEBUG 506 dprintf(DEXPAND,"cur %x pnd %x lfr %x ", ns->ns_cur, pend, lastfree); 507 #endif 508 /* have we wrapped */ 509 if (lastfree >= RBUFEND/DS_PGSIZE) 510 lastfree = RBUF/DS_PGSIZE; 511 if (pend < lastfree && ns->ns_cur < pend) 512 lastfree = ns->ns_cur; 513 else if (ns->ns_cur > lastfree) 514 lastfree = ns->ns_cur; 515 516 /* something in the buffer? */ 517 while (pend != lastfree) { 518 u_char nxt; 519 520 fetchram(&ns->ns_ph,lastfree*DS_PGSIZE, 521 sizeof(ns->ns_ph)); 522 ns->ns_ba = lastfree*DS_PGSIZE+sizeof(ns->ns_ph); 523 524 /* paranoia */ 525 if (ns->ns_ph.pr_status == DSRS_RPC || 526 ns->ns_ph.pr_status == 0x21) 527 nerecv (ns); 528 #ifdef NEDEBUG 529 else { 530 printf("cur %x pnd %x lfr %x ", ns->ns_cur, pend, lastfree); 531 printf("nxt %x len %x ", ns->ns_ph.pr_nxtpg, (ns->ns_ph.pr_sz1<<8)+ 532 ns->ns_ph.pr_sz0); 533 pg("Bogus Sts %x ", ns->ns_ph.pr_status); 534 } 535 #endif 536 537 nxt = ns->ns_ph.pr_nxtpg ; 538 #ifdef NEDEBUG 539 dprintf(DEXPAND,"nxt %x ", nxt); 540 #endif 541 /* sanity check */ 542 if ( nxt >= RBUF/DS_PGSIZE 543 && nxt <= RBUFEND/DS_PGSIZE && nxt <= pend) 544 ns->ns_cur = nxt; 545 else ns->ns_cur = nxt = pend; 546 lastfree = nxt; 547 outb(nec+ds0_bnry, pred(nxt)); 548 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1); 549 pend = inb(nec+ds1_curr); 550 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0); 551 } /*else ns->ns_cur = pend;*/ 552 #ifdef NEDEBUG 553 dprintf(DEXPAND,"cur %x pnd %x lfR %x ", ns->ns_cur, pend, lastfree); 554 #endif 555 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA); 556 } 557 if (isr & DSIS_TXE) { 558 ns->ns_flags &= ~DSF_LOCK; 559 #ifdef NEDEBUG 560 dprintf(DEXPAND," clsn"); 561 #endif 562 /* need to read these registers to clear status */ 563 ns->ns_if.if_collisions += inb(nec+ds0_tbcr0); 564 ns->ns_if.if_oerrors++; 565 } 566 if (isr & DSIS_TX) { 567 #ifdef NEDEBUGx 568 dprintf(DEXPAND,"tx "); 569 #endif 570 ns->ns_flags &= ~DSF_LOCK; 571 ++ns->ns_if.if_opackets; 572 ns->ns_if.if_collisions += inb(nec+ds0_tbcr0); 573 } 574 575 /* receiver ovverun? */ 576 if (isr & DSIS_ROVRN) { 577 outb(nec+ds0_rbcr0, 0); 578 outb(nec+ds0_rbcr1, 0); 579 outb(nec+ds0_tcr, DSTC_LB0); 580 outb(nec+ds0_rcr, DSRC_MON); 581 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA); 582 outb(nec+ds0_rcr, DSRC_AB); 583 outb(nec+ds0_tcr, 0); 584 } 585 586 outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); 587 nestart(&ns->ns_if); 588 outb (nec+ds_cmd, cmd); 589 outb (nec+ds0_imr, 0xff); 590 isr = inb (nec+ds0_isr); 591 if(isr) goto loop; 592 593 #ifdef NEDEBUG 594 if(++cnt % 10 == 0) dprintf(DEXPAND,"\n"); 595 #endif 596 } 597 598 /* 599 * Ethernet interface receiver interface. 600 * If input error just drop packet. 601 * Otherwise examine packet to determine type. If can't determine length 602 * from type, then have to drop packet. Othewise decapsulate 603 * packet based on type and pass to type specific higher-level 604 * input routine. 605 */ 606 nerecv(ns) 607 register struct ne_softc *ns; 608 { 609 int len,i; 610 611 ns->ns_if.if_ipackets++; 612 len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8); 613 if(len < 60 || len > 1536) { 614 #ifdef NEDEBUG 615 pg(DEXPAND,"R Bogus Length %d", len); 616 #endif 617 return; 618 } 619 fetchram(ns->ns_pb,ns->ns_ba,min(len,DS_PGSIZE-sizeof(ns->ns_ph))); 620 #ifdef NEDEBUG 621 if (!bcmp((caddr_t)ns->ns_pb, (caddr_t)ns->ns_addr, 6) 622 && !bcmp((caddr_t)ns->ns_pb, (caddr_t)etherbroadcastaddr, 6)) { 623 printf("G%x ", ns->ns_cur); 624 return; 625 }/* else 626 printf("P%x ", ns->ns_cur);*/ 627 #endif 628 if(len > DS_PGSIZE-sizeof(ns->ns_ph)) { 629 int l = len - (DS_PGSIZE-sizeof(ns->ns_ph)), b ; 630 u_char *p = ns->ns_pb + (DS_PGSIZE-sizeof(ns->ns_ph)); 631 632 #ifdef NEDEBUG 633 dprintf(DEXPAND,"len %d(%d|", len, p - ns->ns_pb); 634 #endif 635 if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46; 636 b = ns->ns_cur*DS_PGSIZE; 637 638 while (l >= DS_PGSIZE) { 639 fetchram(p,b,DS_PGSIZE); 640 p += DS_PGSIZE; l -= DS_PGSIZE; 641 if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46; 642 b = ns->ns_cur*DS_PGSIZE; 643 #ifdef NEDEBUG 644 dprintf(DEXPAND,"%d|", p - ns->ns_pb); 645 #endif 646 } 647 #ifdef NEDEBUG 648 dprintf(DEXPAND,"%d) ", l); 649 #endif 650 if (l > 0) 651 fetchram(p,b,l); 652 } 653 len -= 654 sizeof(struct ether_header) 655 + sizeof(long); /* don't forget checksum! */ 656 657 658 neread(ns,(caddr_t)(ns->ns_pb), len); 659 } 660 661 pausestr(s,n) char *s; { 662 static downcnt; 663 664 if(n) { downcnt = 0xffff; return(0); } 665 if(--downcnt > 0) return(0); 666 #ifdef NEDEBUG 667 pg(" <%s> recur %d sts %x ", s, recur, inb (nec+ds0_isr)); 668 #endif 669 return(-1); 670 } 671 672 673 /* 674 * Pass a packet to the higher levels. 675 * We deal with the trailer protocol here. 676 */ 677 neread(ns, buf, len) 678 register struct ne_softc *ns; 679 char *buf; 680 int len; 681 { 682 register struct ether_header *eh; 683 struct mbuf *m; 684 int off, resid; 685 register struct ifqueue *inq; 686 687 /* 688 * Deal with trailer protocol: if type is trailer type 689 * get true type from first 16-bit word past data. 690 * Remember that type was trailer by setting off. 691 */ 692 eh = (struct ether_header *)buf; 693 eh->ether_type = ntohs((u_short)eh->ether_type); 694 #define nedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) 695 if (eh->ether_type >= ETHERTYPE_TRAIL && 696 eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 697 off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; 698 if (off >= ETHERMTU) return; /* sanity */ 699 eh->ether_type = ntohs(*nedataaddr(eh, off, u_short *)); 700 resid = ntohs(*(nedataaddr(eh, off+2, u_short *))); 701 if (off + resid > len) return; /* sanity */ 702 len = off + resid; 703 } else off = 0; 704 705 if (len == 0) return; 706 707 /* 708 * Pull packet off interface. Off is nonzero if packet 709 * has trailing header; neget will then force this header 710 * information to be at the front, but we still have to drop 711 * the type and length which are at the front of any trailer data. 712 */ 713 m = neget(buf, len, off, &ns->ns_if); 714 if (m == 0) return; 715 716 ether_input(&ns->ns_if, eh, m); 717 } 718 719 /* 720 * Supporting routines 721 */ 722 723 /* 724 * Pull read data off a interface. 725 * Len is length of data, with local net header stripped. 726 * Off is non-zero if a trailer protocol was used, and 727 * gives the offset of the trailer information. 728 * We copy the trailer information and then all the normal 729 * data into mbufs. When full cluster sized units are present 730 * we copy into clusters. 731 */ 732 struct mbuf * 733 neget(buf, totlen, off0, ifp) 734 caddr_t buf; 735 int totlen, off0; 736 struct ifnet *ifp; 737 { 738 struct mbuf *top, **mp, *m, *p; 739 int off = off0, len; 740 register caddr_t cp = buf; 741 char *epkt; 742 743 buf += sizeof(struct ether_header); 744 cp = buf; 745 epkt = cp + totlen; 746 747 748 if (off) { 749 cp += off + 2 * sizeof(u_short); 750 totlen -= 2 * sizeof(u_short); 751 } 752 753 MGETHDR(m, M_DONTWAIT, MT_DATA); 754 if (m == 0) 755 return (0); 756 m->m_pkthdr.rcvif = ifp; 757 m->m_pkthdr.len = totlen; 758 m->m_len = MHLEN; 759 760 top = 0; 761 mp = ⊤ 762 while (totlen > 0) { 763 if (top) { 764 MGET(m, M_DONTWAIT, MT_DATA); 765 if (m == 0) { 766 m_freem(top); 767 return (0); 768 } 769 m->m_len = MLEN; 770 } 771 len = min(totlen, epkt - cp); 772 if (len >= MINCLSIZE) { 773 MCLGET(m, M_DONTWAIT); 774 if (m->m_flags & M_EXT) 775 m->m_len = len = min(len, MCLBYTES); 776 else 777 len = m->m_len; 778 } else { 779 /* 780 * Place initial small packet/header at end of mbuf. 781 */ 782 if (len < m->m_len) { 783 if (top == 0 && len + max_linkhdr <= m->m_len) 784 m->m_data += max_linkhdr; 785 m->m_len = len; 786 } else 787 len = m->m_len; 788 } 789 bcopy(cp, mtod(m, caddr_t), (unsigned)len); 790 cp += len; 791 *mp = m; 792 mp = &m->m_next; 793 totlen -= len; 794 if (cp == epkt) 795 cp = buf; 796 } 797 return (top); 798 } 799 800 /* 801 * Process an ioctl request. 802 */ 803 neioctl(ifp, cmd, data) 804 register struct ifnet *ifp; 805 int cmd; 806 caddr_t data; 807 { 808 register struct ifaddr *ifa = (struct ifaddr *)data; 809 struct ne_softc *ns = &ne_softc[ifp->if_unit]; 810 struct ifreq *ifr = (struct ifreq *)data; 811 int s = splimp(), error = 0; 812 813 814 switch (cmd) { 815 816 case SIOCSIFADDR: 817 ifp->if_flags |= IFF_UP; 818 819 switch (ifa->ifa_addr->sa_family) { 820 #ifdef INET 821 case AF_INET: 822 neinit(ifp->if_unit); /* before arpwhohas */ 823 ((struct arpcom *)ifp)->ac_ipaddr = 824 IA_SIN(ifa)->sin_addr; 825 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 826 break; 827 #endif 828 #ifdef NS 829 case AF_NS: 830 { 831 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 832 833 if (ns_nullhost(*ina)) 834 ina->x_host = *(union ns_host *)(ns->ns_addr); 835 else { 836 /* 837 * The manual says we can't change the address 838 * while the receiver is armed, 839 * so reset everything 840 */ 841 ifp->if_flags &= ~IFF_RUNNING; 842 bcopy((caddr_t)ina->x_host.c_host, 843 (caddr_t)ns->ns_addr, sizeof(ns->ns_addr)); 844 } 845 neinit(ifp->if_unit); /* does ne_setaddr() */ 846 break; 847 } 848 #endif 849 default: 850 neinit(ifp->if_unit); 851 break; 852 } 853 break; 854 855 case SIOCSIFFLAGS: 856 if ((ifp->if_flags & IFF_UP) == 0 && 857 ifp->if_flags & IFF_RUNNING) { 858 ifp->if_flags &= ~IFF_RUNNING; 859 outb(nec+ds_cmd,DSCM_STOP|DSCM_NODMA); 860 } else if (ifp->if_flags & IFF_UP && 861 (ifp->if_flags & IFF_RUNNING) == 0) 862 neinit(ifp->if_unit); 863 break; 864 865 #ifdef notdef 866 case SIOCGHWADDR: 867 bcopy((caddr_t)ns->ns_addr, (caddr_t) &ifr->ifr_data, 868 sizeof(ns->ns_addr)); 869 break; 870 #endif 871 872 default: 873 error = EINVAL; 874 } 875 splx(s); 876 return (error); 877 } 878 879 nesetaddr(ifp, sin) 880 register struct ifnet *ifp; 881 register struct sockaddr_in *sin; 882 { 883 #ifdef notdef 884 ifp->if_addr = *(struct sockaddr *)sin; 885 ifp->if_net = in_netof(sin->sin_addr); 886 ifp->if_host[0] = in_lnaof(sin->sin_addr); 887 if (nepaddr[ifp->if_unit][0] == '3') 888 nepaddr[ifp->if_unit][0] = ifp->if_host[0] << 1; 889 sin = (struct sockaddr_in *)&ifp->if_broadaddr; 890 sin->sin_family = AF_INET; 891 sin->sin_addr = in_makeaddr(ifp->if_net, INADDR_ANY); 892 ifp->if_flags |= IFF_BROADCAST; 893 #endif 894 } 895 #endif 896