1: /* 2: * SCCSID: @(#)if_de.c 1.1 (2.11BSD GTE) 12/31/93 3: * 2.11BSD - Remove dereset since 1) it was never called, and 2) 4: * wouldn't work if it were called. Also uballoc and 5: * ubmalloc calling convention changed. - sms 6: */ 7: #include "de.h" 8: #if NDE > 0 9: /* 10: * DEC DEUNA interface 11: * 12: * Lou Salkind 13: * New York University 14: * 15: * TODO: 16: * timeout routine (get statistics) 17: */ 18: 19: #include "param.h" 20: #include "../machine/seg.h" 21: #include "systm.h" 22: #include "mbuf.h" 23: #include "domain.h" 24: #include "protosw.h" 25: #include "ioctl.h" 26: #include "errno.h" 27: #include "time.h" 28: 29: /* 30: * Define DE_DO_BCTRS to get the DEUNA/DELUA to add code to allow 31: * ioctl() for clearing/getting I/O stats from the board. 32: #define DE_DO_BCTRS 33: */ 34: 35: /* 36: * Define DE_DO_PHYSADDR to get the DEUNA/DELUA to add code to allow 37: * ioctl() for setting/getting physical hardware address. 38: #define DE_DO_PHYSADDR 39: */ 40: 41: /* 42: * Define DE_DO_MULTI to get the DEUNA/DELUA to handle multi-cast addresses 43: #define DE_DO_MULTI 44: */ 45: 46: /* 47: * Define DE_INT_LOOPBACK to get the DEUNA/DELUA internal loopback code turned on 48: #define DE_INT_LOOPBACK 49: */ 50: 51: /* 52: * Define DE_DEBUG to get the DEUNA/DELUA debug code turned on 53: #define DE_DEBUG 54: */ 55: 56: #include "../pdpif/if_de.h" 57: 58: #ifndef YES 59: #define YES 1 60: #else /* YES */ 61: #undef YES 62: #define YES 1 63: #endif /* YES */ 64: #ifndef NO 65: #define NO 0 66: #else /* NO */ 67: #undef NO 68: #define NO 0 69: #endif /* NO */ 70: 71: #define MAPBUFDESC (((btoc(ETHERMTU+sizeof(struct ether_header)) - 1) << 8 ) | RW) 72: #define CRC_LEN 4 /* Length of CRC added to packet by board */ 73: 74: struct de_softc de_softc[NDE]; 75: 76: #ifdef DE_DEBUG 77: /* 78: * Setting dedebug turns on the level of debugging, iff DE_DEBUG 79: * was defined at compile time. The current levels are: 80: * 1 - added informative messages and error messages 81: * 2 - more added messages 82: * 3 - still more messages, like one for every loop packet seen, etc. 83: */ 84: #define DE_DEBUG_LEVEL 1 85: int dedebug = DE_DEBUG_LEVEL; 86: #endif /* DE_DEBUG */ 87: 88: #ifdef DE_DO_MULTI 89: u_char unused_multi[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 90: #endif /* DE_DO_MULTI */ 91: #ifdef not_on_pdp 92: extern struct protosw *iftype_to_proto(), *iffamily_to_proto(); 93: #endif /* not_on_pdp */ 94: 95: int deprobe(), deattach(), deintr(), deinit(), deoutput(), deioctl(); 96: 97: struct mbuf *deget(); 98: 99: u_short destd[] = { 0174510 }; 100: 101: struct uba_device *deinfo[NDE]; 102: 103: struct uba_driver dedriver = 104: { deprobe, 0, deattach, 0, destd, "de", deinfo }; 105: 106: #ifdef DE_INT_LOOPBACK 107: #define DELUA_LOOP_LEN (32 - sizeof(struct ether_header)) 108: #endif /* DE_INT_LOOPBACK */ 109: 110: #ifdef DE_DO_BCTRS 111: extern struct timeval time; 112: struct timeval atv; 113: #endif /* DE_DO_BCTRS */ 114: 115: deprobe(reg) 116: caddr_t reg; 117: { 118: #ifdef not_on_pdp 119: register int br, cvec; /* r11, r10 value-result */ 120: register struct dedevice *addr = (struct dedevice *)reg; 121: register i; 122: 123: #ifdef lint 124: br = 0; cvec = br; br = cvec; 125: i = 0; derint(i); deintr(i); 126: #endif /* lint */ 127: 128: /* 129: * Make sure self-test is finished 130: * Self-test on a DELUA can take 15 seconds. 131: */ 132: for (i = 0; i < 160 && 133: (addr->pcsr0 & PCSR0_FATI) == 0 && 134: (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET; 135: ++i) 136: DELAY(100000); 137: if ((addr->pcsr0 & PCSR0_FATI) != 0 || 138: (addr->pcsr1 & PCSR1_STMASK) != STAT_READY) 139: return(0); 140: 141: addr->pcsr0 = 0; 142: 143: 144: addr->pcsr0 = PCSR0_RSET; 145: 146: /* 147: * just in case this is not a deuna or delua 148: * dont wait for more than 30 secs 149: */ 150: for (i = 0; i < 300 && (addr->pcsr0 & PCSR0_INTR) == 0; i++) 151: DELAY(100000); 152: if ((addr->pcsr0 & PCSR0_INTR) == 0) 153: return(0); 154: 155: /* make board interrupt by executing a GETPCBB command */ 156: addr->pcsr0 = PCSR0_INTE; 157: addr->pcsr2 = 0; 158: addr->pcsr3 = 0; 159: addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB; 160: DELAY(100000); 161: #endif /* not_on_pdp */ 162: return(1); 163: } 164: 165: /* 166: * Interface exists: make available by filling in network interface 167: * record. System will initialize the interface when it is ready 168: * to accept packets. We get the ethernet address here. 169: */ 170: deattach(ui) 171: struct uba_device *ui; 172: { 173: register struct de_softc *ds = &de_softc[ui->ui_unit]; 174: register struct ifnet *ifp = &ds->ds_if; 175: register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 176: int i; 177: u_short csr1; 178: 179: /* 180: * Is it a DEUNA or a DELULA? Save the device id. 181: */ 182: csr1 = addr->pcsr1; 183: ds->ds_devid = (csr1 & PCSR1_DEVID) >> 4; 184: 185: #ifdef DE_DEBUG 186: if (dedebug >= 1) 187: printf("de%d: Device Type: %s\n", ui->ui_unit, 188: (ds->ds_devid == DEUNA) ? "DEUNA" : "DELUA"); 189: #endif /* DE_DEBUG */ 190: /* 191: * Board Status Check 192: */ 193: if (csr1 & 0xff80) { 194: if (ds->ds_devid == DEUNA) 195: printf("de%d: hardware error, pcsr1=%b\n", 196: ui->ui_unit, csr1, PCSR1_BITS); 197: else 198: printf("de%d: hardware error, pcsr1=%b\n", 199: ui->ui_unit, csr1, PCSR1_BITS_DELUA); 200: } 201: 202: ifp->if_unit = ui->ui_unit; 203: ifp->if_name = "de"; 204: ifp->if_mtu = ETHERMTU; 205: ifp->if_flags |= IFF_BROADCAST; 206: #ifdef DE_DEBUG 207: ifp->if_flags |= IFF_DEBUG; 208: printf("de%d: DEBUG enabled level=%d\n",ifp->if_unit,dedebug); 209: #endif /* DE_DEBUG */ 210: 211: #ifdef DE_DO_MULTI 212: /* 213: * Fill the multicast address table with unused entries (broadcast 214: * address) so that we can always give the full table to the device 215: * and we don't have to worry about gaps. 216: */ 217: for (i=0; i < NMULTI; i++) 218: bcopy(unused_multi,(u_char *)&ds->ds_multicast[i],MULTISIZE); 219: 220: #endif /* DE_DO_MULTI */ 221: /* 222: * Reset the board and map the pcbb buffer onto the Unibus. 223: */ 224: addr->pcsr0 = PCSR0_RSET; 225: (void) dewait(ui, "board reset", YES, NO); 226: 227: ds->ds_ubaddr = uballoc(INCORE_BASE(ds), INCORE_SIZE); 228: addr->pcsr2 = ds->ds_ubaddr & 0xffff; 229: addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; 230: addr->pclow = CMD_GETPCBB; 231: (void) dewait(ui, "get pcbb", YES, NO); 232: 233: ds->ds_pcbb.pcbb0 = FC_RDPHYAD; 234: addr->pclow = CMD_GETCMD; 235: (void) dewait(ui, "read addr", YES, NO); 236: 237: bcopy((caddr_t)&ds->ds_pcbb.pcbb2,(caddr_t)ds->ds_addr, 238: sizeof (ds->ds_addr)); 239: #ifdef DE_DEBUG 240: if (dedebug >= 1) 241: printf("de%d: hardware address %s\n", 242: ui->ui_unit, ether_sprintf(ds->ds_addr)); 243: #endif /* DE_DEBUG */ 244: ifp->if_init = deinit; 245: ifp->if_output = deoutput; 246: ifp->if_ioctl = deioctl; 247: ifp->if_reset = 0; 248: ds->ds_deuba.difu_flags = UBA_CANTWAIT; 249: 250: if_attach(ifp); 251: } 252: 253: /* 254: * Initialization of interface; clear recorded pending 255: * operations, and reinitialize UNIBUS usage. 256: */ 257: deinit(unit) 258: int unit; 259: { 260: register struct de_softc *ds = &de_softc[unit]; 261: register struct uba_device *ui = deinfo[unit]; 262: register struct dedevice *addr; 263: register struct ifrw *ifrw; 264: struct ifnet *ifp = &ds->ds_if; 265: int s; 266: struct de_ring *rp; 267: ubadr_t incaddr; 268: 269: /* not yet, if address still unknown */ 270: /* DECnet must set this somewhere to make device happy */ 271: if (ifp->if_addrlist == (struct ifaddr *)0) 272: return; 273: 274: if (ds->ds_flags & DSF_RUNNING) 275: return; 276: 277: if ((ifp->if_flags & IFF_RUNNING) == 0) { /* First time */ 278: /* 279: * Only allocate the resources ONCE. 280: * ~IFF_RUNNING && ~DSF_RUNNING 281: */ 282: if (de_ubainit(&ds->ds_deuba, ui->ui_ubanum, 283: sizeof (struct ether_header), 284: (int) btoc(ETHERMTU)) == 0) { 285: printf("de%d: can't initialize\n", unit); 286: ds->ds_if.if_flags &= ~IFF_UP; 287: return; 288: } 289: } 290: addr = (struct dedevice *)ui->ui_addr; 291: 292: /* 293: * Set up the PCBB - this is done in deattach() also, but 294: * has to be redone here in case the board is reset (PCSR0_RSET) 295: * and this routine is called. Note that ds->ds_ubaddr is set 296: * in deattach() and all we do here is tell the 297: * DEUNA/DELUA where it can find its PCBB. 298: */ 299: addr->pcsr2 = ds->ds_ubaddr & 0xffff; 300: addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; 301: addr->pclow = CMD_GETPCBB; 302: (void) dewait(ui, "get pcbb", YES, NO); 303: 304: /* 305: * Set the transmit and receive ring header addresses 306: */ 307: incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; 308: ds->ds_pcbb.pcbb0 = FC_WTRING; 309: ds->ds_pcbb.pcbb2 = incaddr & 0xffff; 310: ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; 311: 312: incaddr = ds->ds_ubaddr + XRENT_OFFSET; 313: ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; 314: ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; 315: ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); 316: ds->ds_udbbuf.b_trlen = NXMT; 317: incaddr = ds->ds_ubaddr + RRENT_OFFSET; 318: ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; 319: ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; 320: ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); 321: ds->ds_udbbuf.b_rrlen = NRCV; 322: 323: addr->pclow = CMD_GETCMD; 324: (void) dewait(ui, "wtring", NO, NO); 325: 326: /* 327: * Initialize the board's mode 328: */ 329: ds->ds_pcbb.pcbb0 = FC_WTMODE; 330: /* 331: * Let hardware do padding & set MTCH bit on broadcast 332: */ 333: ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; 334: addr->pclow = CMD_GETCMD; 335: (void) dewait(ui, "wtmode", NO, NO); 336: 337: /* 338: * Set up the receive and transmit ring entries 339: */ 340: ifrw = &ds->ds_deuba.difu_w[0]; 341: for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { 342: rp->r_segbl = ifrw->ifrw_info & 0xffff; 343: rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; 344: rp->r_flags = 0; 345: ifrw++; 346: } 347: ifrw = &ds->ds_deuba.difu_r[0]; 348: for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) { 349: rp->r_slen = sizeof (struct de_buf); 350: rp->r_segbl = ifrw->ifrw_info & 0xffff; 351: rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; 352: rp->r_flags = RFLG_OWN; /* hang receive */ 353: ifrw++; 354: } 355: 356: /* 357: * Start up the board (rah rah) 358: */ 359: s = splimp(); 360: ds->ds_nxmit = ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = 0; 361: ds->ds_if.if_flags |= IFF_RUNNING; 362: destart(unit); /* queue output packets */ 363: addr->pclow = PCSR0_INTE; /* avoid interlock */ 364: ds->ds_flags |= DSF_RUNNING; 365: #ifdef NS 366: if (ds->ds_flags & DSF_SETADDR) 367: de_setaddr(ds->ds_addr, unit); 368: #endif /* NS */ 369: addr->pclow = CMD_START | PCSR0_INTE; 370: splx(s); 371: #ifdef DE_DO_BCTRS 372: cpfromkern(&time, &atv, sizeof(struct timeval)); 373: ds->ds_ztime = atv.tv_sec; 374: #endif /* DE_DO_BCTRS */ 375: } 376: 377: /* 378: * Setup output on interface. 379: * Get another datagram to send off of the interface queue, 380: * and map it to the interface before starting the output. 381: */ 382: static 383: destart(unit) 384: int unit; 385: { 386: int len; 387: register struct uba_device *ui = deinfo[unit]; 388: struct dedevice *addr = (struct dedevice *)ui->ui_addr; 389: register struct de_softc *ds = &de_softc[unit]; 390: register struct de_ring *rp; 391: struct mbuf *m; 392: register int nxmit; 393: 394: if (ds->ds_flags & DSF_LOCK) 395: return; 396: 397: for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) { 398: IF_DEQUEUE(&ds->ds_if.if_snd, m); 399: if (m == 0) 400: break; 401: rp = &ds->ds_xrent[ds->ds_xfree]; 402: if (rp->r_flags & XFLG_OWN) 403: panic("deuna xmit in progress"); 404: len = deput(&ds->ds_deuba, ds->ds_xfree, m); 405: rp->r_slen = len; 406: rp->r_tdrerr = 0; 407: rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; 408: 409: ds->ds_xfree++; 410: if (ds->ds_xfree == NXMT) 411: ds->ds_xfree = 0; 412: } 413: if (ds->ds_nxmit != nxmit) { 414: ds->ds_nxmit = nxmit; 415: if (ds->ds_flags & DSF_RUNNING) 416: addr->pclow = PCSR0_INTE|CMD_PDMD; 417: } else if (ds->ds_nxmit == NXMT) { 418: /* 419: * poke device if we have something to send and 420: * transmit ring is full. 421: */ 422: #ifdef DE_DEBUG 423: if (dedebug >= 1) { 424: rp = &ds->ds_xrent[0]; 425: printf("de%d: did not transmit: %d, %d, %d, flag0=%x, flag1=%x\n", 426: unit, ds->ds_xindex, ds->ds_nxmit, ds->ds_xfree, 427: rp->r_flags, (rp+1)->r_flags); 428: } 429: #endif /* DE_DEBUG */ 430: if (ds->ds_flags & DSF_RUNNING) 431: addr->pclow = PCSR0_INTE|CMD_PDMD; 432: } 433: } 434: 435: /* 436: * Command done interrupt. 437: */ 438: deintr(unit) 439: int unit; 440: { 441: struct uba_device *ui = deinfo[unit]; 442: register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 443: register struct de_softc *ds = &de_softc[unit]; 444: register struct de_ring *rp; 445: register struct ifrw *ifrw; 446: short csr0; 447: 448: /* save flags right away - clear out interrupt bits */ 449: csr0 = addr->pcsr0; 450: addr->pchigh = csr0 >> 8; 451: 452: if (csr0 & PCSR0_FATI) { 453: if (ds->ds_devid == DEUNA) 454: printf( 455: "de%d: unsolicited state change, csr0=%b, csr1=%b\n", 456: unit, csr0, PCSR0_BITS, 457: addr->pcsr1, PCSR1_BITS); 458: else 459: printf( 460: "de%d: unsolicited state change, csr0=%b, csr1=%b\n", 461: unit, csr0, PCSR0_BITS, 462: addr->pcsr1, PCSR1_BITS_DELUA); 463: } 464: 465: if (csr0 & PCSR0_SERI) { 466: if (ds->ds_devid == DEUNA) 467: printf("de%d: status error, csr0=%b, csr1=%b\n", 468: unit, csr0, PCSR0_BITS, 469: addr->pcsr1, PCSR1_BITS); 470: else 471: printf("de%d: status error, csr0=%b, csr1=%b\n", 472: unit, csr0, PCSR0_BITS, 473: addr->pcsr1, PCSR1_BITS_DELUA); 474: } 475: 476: ds->ds_flags |= DSF_LOCK; 477: 478: /* 479: * if receive, put receive buffer on mbuf 480: * and hang the request again 481: */ 482: rp = &ds->ds_rrent[ds->ds_rindex]; 483: if ((rp->r_flags & RFLG_OWN) == 0) 484: derecv(unit); 485: 486: /* 487: * Poll transmit ring and check status. 488: * Be careful about loopback requests. 489: * Then free buffer space and check for 490: * more transmit requests. 491: */ 492: for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) { 493: rp = &ds->ds_xrent[ds->ds_xindex]; 494: if (rp->r_flags & XFLG_OWN) 495: break; 496: ds->ds_if.if_opackets++; 497: ifrw = &ds->ds_deuba.difu_w[ds->ds_xindex]; 498: /* check for unusual conditions */ 499: if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { 500: if (rp->r_flags & XFLG_ERRS) { 501: /* output error */ 502: ds->ds_if.if_oerrors++; 503: #ifdef DE_DEBUG 504: if (dedebug >= 1) 505: printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", 506: unit, rp->r_flags, XFLG_BITS, 507: rp->r_tdrerr, XERR_BITS, 508: rp->r_slen); 509: #endif /* DE_DEBUG */ 510: } else { 511: if (rp->r_flags & XFLG_ONE) { 512: /* one collision */ 513: ds->ds_if.if_collisions++; 514: } else if (rp->r_flags & XFLG_MORE) { 515: /* more than one collision */ 516: ds->ds_if.if_collisions += 2; /*guess*/ 517: } 518: if ((rp->r_flags & XFLG_MTCH) && 519: !(ds->ds_if.if_flags & IFF_LOOPBACK)) { 520: /* received our own packet */ 521: ds->ds_if.if_ipackets++; 522: #ifdef DE_DEBUG 523: if (dedebug >= 3) 524: printf("de%d: loopback packet\n", 525: unit); 526: #endif /* DE_DEBUG */ 527: deread(ds, ifrw, 528: rp->r_slen - sizeof (struct ether_header)); 529: } 530: } 531: } 532: /* check if next transmit buffer also finished */ 533: ds->ds_xindex++; 534: if (ds->ds_xindex >= NXMT) 535: ds->ds_xindex = 0; 536: } 537: ds->ds_flags &= ~DSF_LOCK; 538: destart(unit); 539: 540: if (csr0 & PCSR0_RCBI) { 541: ds->ds_if.if_ierrors++; 542: #ifdef DE_DEBUG 543: if (dedebug >= 1) 544: printf("de%d: buffer unavailable\n", ui->ui_unit); 545: #endif /* DE_DEBUG */ 546: addr->pclow = PCSR0_INTE|CMD_PDMD; 547: } 548: } 549: 550: /* 551: * Ethernet interface receiver interface. 552: * If input error just drop packet. 553: * Otherwise purge input buffered data path and examine 554: * packet to determine type. If can't determine length 555: * from type, then have to drop packet. Othewise decapsulate 556: * packet based on type and pass to type specific higher-level 557: * input routine. 558: */ 559: static 560: derecv(unit) 561: int unit; 562: { 563: register struct de_softc *ds = &de_softc[unit]; 564: register struct de_ring *rp; 565: register int len; 566: struct ether_header *eh; 567: 568: rp = &ds->ds_rrent[ds->ds_rindex]; 569: while ((rp->r_flags & RFLG_OWN) == 0) { 570: ds->ds_if.if_ipackets++; 571: len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) 572: - CRC_LEN; /* don't forget checksum! */ 573: if( ! (ds->ds_if.if_flags & IFF_LOOPBACK) ) { 574: /* check for errors */ 575: if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || 576: (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) || 577: (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || 578: len < ETHERMIN || len > ETHERMTU) { 579: ds->ds_if.if_ierrors++; 580: #ifdef DE_DEBUG 581: if (dedebug >= 1) 582: printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", 583: unit, rp->r_flags, RFLG_BITS, 584: rp->r_lenerr, RERR_BITS, len); 585: #endif /* DE_DEBUG */ 586: } else 587: deread(ds, &ds->ds_deuba.difu_r[ds->ds_rindex], len); 588: } else { 589: int ret; 590: segm sav5; 591: 592: saveseg5(sav5); 593: mapseg5(ds->ds_deuba.difu_r[ds->ds_rindex].ifrw_click, MAPBUFDESC); 594: eh = (struct ether_header *) SEG5; 595: ret = bcmp(eh->ether_dhost, ds->ds_addr, 6); 596: restorseg5(sav5); 597: if (ret == NULL) 598: deread(ds, &ds->ds_deuba.difu_r[ds->ds_rindex], len); 599: } 600: 601: /* hang the receive buffer again */ 602: rp->r_lenerr = 0; 603: rp->r_flags = RFLG_OWN; 604: 605: /* check next receive buffer */ 606: ds->ds_rindex++; 607: if (ds->ds_rindex >= NRCV) 608: ds->ds_rindex = 0; 609: rp = &ds->ds_rrent[ds->ds_rindex]; 610: } 611: } 612: 613: /* 614: * Pass a packet to the higher levels. 615: * We deal with the trailer protocol here. 616: */ 617: static 618: deread(ds, ifrw, len) 619: register struct de_softc *ds; 620: struct ifrw *ifrw; 621: int len; 622: { 623: struct ether_header *eh; 624: struct mbuf *m; 625: struct protosw *pr; 626: int off, resid, s; 627: struct ifqueue *inq; 628: segm sav5; 629: int type; 630: 631: /* 632: * Deal with trailer protocol: if type is trailer 633: * get true type from first 16-bit word past data. 634: * Remember that type was trailer by setting off. 635: */ 636: saveseg5(sav5); 637: mapseg5(ifrw->ifrw_click, MAPBUFDESC); 638: eh = (struct ether_header *) SEG5; 639: 640: type = eh->ether_type = ntohs((u_short)eh->ether_type); 641: 642: #define dedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) 643: if (type >= ETHERTYPE_TRAIL && 644: type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 645: off = (type - ETHERTYPE_TRAIL) * 512; 646: if (off >= ETHERMTU) { 647: restorseg5(sav5); 648: return; /* sanity */ 649: } 650: type = ntohs(*dedataaddr(eh, off, u_short *)); 651: resid = ntohs(*(dedataaddr(eh, off+2, u_short *))); 652: 653: if (off + resid > len) { 654: restorseg5(sav5); 655: return; /* sanity */ 656: } 657: len = off + resid; 658: } else 659: off = 0; 660: 661: if (len == 0) { 662: restorseg5(sav5); 663: return; 664: } 665: 666: restorseg5(sav5); 667: 668: /* 669: * Pull packet off interface. Off is nonzero if packet 670: * has trailing header; deget will then force this header 671: * information to be at the front, but we still have to drop 672: * the type and length which are at the front of any trailer data. 673: */ 674: 675: m = deget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if); 676: 677: if (m == 0) 678: return; 679: if (off) { 680: struct ifnet *ifp; 681: 682: ifp = *(mtod(m, struct ifnet **)); 683: m->m_off += 2 * sizeof (u_short); 684: m->m_len -= 2 * sizeof (u_short); 685: *(mtod(m, struct ifnet **)) = ifp; 686: } 687: 688: switch (type) { 689: 690: #ifdef INET 691: case ETHERTYPE_IP: 692: schednetisr(NETISR_IP); 693: inq = &ipintrq; 694: break; 695: 696: case ETHERTYPE_ARP: 697: arpinput(&ds->ds_ac, m); 698: return; 699: #endif /* INET */ 700: default: 701: #ifdef not_on_pdp 702: /* 703: * see if other protocol families defined 704: * and call protocol specific routines. 705: * If no other protocols defined then dump message. 706: */ 707: 708: if (pr=iftype_to_proto(type)) { 709: if ((m = (struct mbuf *)(*pr->pr_ifinput)(m, &ds->ds_if, &inq)) == 0) 710: return; 711: } else { 712: #endif /* not_on_pdp */ 713: #ifdef DE_DEBUG 714: if(dedebug >= 1) 715: printf("de%d: Unknow Packet Type 0%o(%d)\n", 716: ds->ds_if.if_unit, type, type); 717: #endif /* DE_DEBUG */ 718: #ifdef DE_DO_BCTRS 719: if (ds->ds_unrecog != 0xffff) 720: ds->ds_unrecog++; 721: #endif /* DE_DO_BCTRS */ 722: m_freem(m); 723: return; 724: #ifdef not_on_pdp 725: } 726: #endif /* not_on_pdp */ 727: } 728: 729: s = splimp(); 730: if (IF_QFULL(inq)) { 731: IF_DROP(inq); 732: splx(s); 733: #ifdef DE_DEBUG 734: if (dedebug >= 1) 735: printf("de%d: Packet Dropped(deread)\n", 736: ds->ds_if.if_unit); 737: #endif /* DE_DEBUG */ 738: m_freem(m); 739: return; 740: } 741: IF_ENQUEUE(inq, m); 742: splx(s); 743: } 744: 745: /* 746: * Ethernet output routine. 747: * Encapsulate a packet of type family for the local net. 748: * Use trailer local net encapsulation if enough data in first 749: * packet leaves a multiple of 512 bytes of data in remainder. 750: */ 751: deoutput(ifp, m0, dst) 752: struct ifnet *ifp; 753: struct mbuf *m0; 754: struct sockaddr *dst; 755: { 756: int type, s, error; 757: u_char edst[6]; 758: struct in_addr idst; 759: struct protosw *pr; 760: register struct de_softc *ds = &de_softc[ifp->if_unit]; 761: register struct mbuf *m = m0; 762: register struct ether_header *eh; 763: register int off; 764: int usetrailers; 765: 766: if((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 767: error = ENETDOWN; 768: goto bad; 769: } 770: 771: switch (dst->sa_family) { 772: 773: #ifdef INET 774: case AF_INET: 775: idst = ((struct sockaddr_in *)dst)->sin_addr; 776: if (!arpresolve(&ds->ds_ac, m, &idst, edst, &usetrailers)) 777: return (0); /* if not yet resolved */ 778: 779: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 780: 781: /* need per host negotiation */ 782: if (usetrailers && off > 0 && (off & 0x1ff) == 0 && 783: m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 784: type = ETHERTYPE_TRAIL + (off>>9); 785: m->m_off -= 2 * sizeof (u_short); 786: m->m_len += 2 * sizeof (u_short); 787: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); 788: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 789: goto gottrailertype; 790: } 791: type = ETHERTYPE_IP; 792: off = 0; 793: goto gottype; 794: #endif /* INET */ 795: #ifdef NS 796: case AF_NS: 797: type = ETHERTYPE_NS; 798: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 799: (caddr_t)edst, sizeof (edst)); 800: off = 0; 801: goto gottype; 802: #endif /* NS */ 803: 804: case AF_UNSPEC: 805: eh = (struct ether_header *)dst->sa_data; 806: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); 807: type = eh->ether_type; 808: goto gottype; 809: 810: default: 811: #ifdef DE_INT_LOOPBACK 812: /* 813: * If we are in loopback mode check the length and 814: * device type. DELUA can only loopback frames of 36 bytes 815: * or less including crc. 816: */ 817: if ((ifp->if_flags & IFF_LOOPBACK) && 818: (m->m_len > DELUA_LOOP_LEN) && (ds->ds_devid == DELUA)) 819: return(EINVAL); 820: #endif /* DE_INT_LOOPBACK */ 821: #ifdef not_on_pdp 822: /* 823: * try to find other address families and call protocol 824: * specific output routine. 825: */ 826: if (pr=iffamily_to_proto(dst->sa_family)) { 827: (*pr->pr_ifoutput)(ifp, m0, dst, &type, (char *)edst); 828: goto gottype; 829: } else { 830: #endif /* not_on_pdp */ 831: printf("de%d: can't handle af%d", ifp->if_unit, dst->sa_family); 832: error = EAFNOSUPPORT; 833: goto bad; 834: #ifdef not_on_pdp 835: } 836: #endif /* not_on_pdp */ 837: } 838: 839: gottrailertype: 840: /* 841: * Packet to be sent as trailer: move first packet 842: * (control information) to end of chain. 843: */ 844: while (m->m_next) 845: m = m->m_next; 846: m->m_next = m0; 847: m = m0->m_next; 848: m0->m_next = 0; 849: m0 = m; 850: 851: gottype: 852: /* 853: * Add local net header. If no space in first mbuf, 854: * allocate another. 855: */ 856: if (m->m_off > MMAXOFF || 857: MMINOFF + sizeof (struct ether_header) > m->m_off) { 858: m = m_get(M_DONTWAIT, MT_HEADER); 859: if (m == 0) { 860: error = ENOBUFS; 861: goto bad; 862: } 863: m->m_next = m0; 864: m->m_off = MMINOFF; 865: m->m_len = sizeof (struct ether_header); 866: } else { 867: m->m_off -= sizeof (struct ether_header); 868: m->m_len += sizeof (struct ether_header); 869: } 870: eh = mtod(m, struct ether_header *); 871: eh->ether_type = htons((u_short)type); 872: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 873: /* DEUNA fills in source address */ 874: bcopy((caddr_t)ds->ds_addr, 875: (caddr_t)eh->ether_shost, sizeof(ds->ds_addr)); 876: 877: /* 878: * Queue message on interface, and start output if interface 879: * not yet active. 880: */ 881: s = splimp(); 882: if (IF_QFULL(&ifp->if_snd)) { 883: IF_DROP(&ifp->if_snd); 884: splx(s); 885: #ifdef DE_DEBUG 886: if (dedebug >= 1) 887: printf("de%d: Packet Dropped(deoutput)\n", 888: ifp->if_unit); 889: #endif /* DE_DEBUG */ 890: m_freem(m); 891: return (ENOBUFS); 892: } 893: IF_ENQUEUE(&ifp->if_snd, m); 894: destart(ifp->if_unit); 895: splx(s); 896: return (0); 897: 898: bad: 899: m_freem(m0); 900: return (error); 901: } 902: 903: /* 904: * Routines supporting UNIBUS network interfaces. 905: */ 906: /* 907: * Init UNIBUS for interface. We map the i/o area 908: * onto the UNIBUS. We then split up the i/o area among 909: * all the receive and transmit buffers. 910: */ 911: 912: static 913: de_ubainit(ifu, uban, hlen, nmr) 914: register struct deuba *ifu; 915: int uban, hlen, nmr; 916: { 917: register caddr_t cp, dp; 918: register struct ifrw *ifrw; 919: int i, ncl; 920: 921: /* 922: * If the ring already has core allocated, quit now. 923: */ 924: if (ifu->difu_r[0].ifrw_click) 925: return(1); 926: 927: nmr = ctob(nmr); 928: nmr += hlen; 929: for (i = 0; i < NRCV; i++) { 930: ifu->difu_r[i].ifrw_click = m_ioget(nmr); 931: if (ifu->difu_r[i].ifrw_click == 0) { 932: ifu->difu_r[0].ifrw_click = 0; 933: if (i) 934: printf("de: lost some space\n"); 935: return(0); 936: } 937: } 938: for (i = 0; i < NXMT; i++) { 939: ifu->difu_w[i].ifrw_click = m_ioget(nmr); 940: if (ifu->difu_w[i].ifrw_click == 0) { 941: ifu->difu_w[0].ifrw_click = 0; 942: ifu->difu_r[0].ifrw_click = 0; 943: if (i) 944: printf("de: lost some space\n"); 945: return(0); 946: } 947: } 948: for (i = 0; i < NRCV; i++) 949: ifu->difu_r[i].ifrw_info = 950: ubmalloc(ifu->difu_r[i].ifrw_click); 951: for (i = 0; i < NXMT; i++) 952: ifu->difu_w[i].ifrw_info = 953: ubmalloc(ifu->difu_w[i].ifrw_click); 954: ifu->ifu_hlen = hlen; 955: return (1); 956: } 957: 958: /* 959: * Pull read data off a interface. 960: * Len is length of data, with local net header stripped. 961: * Off is non-zero if a trailer protocol was used, and 962: * gives the offset of the trailer information. 963: * We copy the trailer information and then all the normal 964: * data into mbufs. 965: */ 966: static struct mbuf * 967: deget(ifu, ifrw, totlen, off0, ifp) 968: register struct deuba *ifu; 969: register struct ifrw *ifrw; 970: int totlen, off0; 971: struct ifnet *ifp; 972: { 973: struct mbuf *top, **mp, *m; 974: int off = off0, len; 975: register caddr_t cp = (caddr_t) ifu->ifu_hlen; 976: u_int click; 977: 978: top = 0; 979: mp = ⊤ 980: click = ifrw->ifrw_click; 981: while (totlen > 0) { 982: MGET(m, M_DONTWAIT, MT_DATA); 983: if (m == 0) 984: goto bad; 985: if (off) { 986: len = totlen - off; 987: cp = (caddr_t)(ifu->ifu_hlen + off); 988: } else 989: len = totlen; 990: m->m_off = MMINOFF; 991: if (ifp) { 992: /* 993: * Leave Room for the ifp 994: */ 995: m->m_len = MIN(MLEN - sizeof(ifp), len); 996: m->m_off += sizeof(ifp); 997: } else 998: m->m_len = MIN(MLEN, len); 999: 1000: mbcopyin(click, cp, mtod(m, char *), (u_int) m->m_len); 1001: cp += m->m_len; 1002: *mp = m; 1003: mp = &m->m_next; 1004: if (off) { 1005: /* sort of an ALGOL-W style for statement... */ 1006: off += m->m_len; 1007: if (off == totlen) { 1008: cp = (caddr_t) ifu->ifu_hlen; 1009: off = 0; 1010: totlen = off0; 1011: } 1012: } else 1013: totlen -= m->m_len; 1014: if (ifp) { 1015: /* 1016: * Prepend interface pointer to first mbuf 1017: */ 1018: m->m_len += sizeof(ifp); 1019: m->m_off -= sizeof(ifp); 1020: *(mtod(m, struct ifnet **)) = ifp; 1021: ifp = (struct ifnet *) 0; 1022: } 1023: } 1024: return (top); 1025: bad: 1026: m_freem(top); 1027: return (0); 1028: } 1029: 1030: /* 1031: * Map a chain of mbufs onto a network interface 1032: * in preparation for an i/o operation. 1033: * The argument chain of mbufs includes the local network 1034: * header which is copied to be in the mapped, aligned 1035: * i/o space. 1036: */ 1037: static 1038: deput(ifu, n, m) 1039: struct deuba *ifu; 1040: int n; 1041: register struct mbuf *m; 1042: { 1043: register struct mbuf *mp; 1044: register u_short off, click; 1045: 1046: click = ifu->difu_w[n].ifrw_click; 1047: off = 0; 1048: while (m) { 1049: mbcopyout(mtod(m, char *), click, off, (u_int) m->m_len); 1050: off += m->m_len; 1051: MFREE(m, mp); 1052: m = mp; 1053: } 1054: 1055: return (off); 1056: } 1057: 1058: /* 1059: * Process an ioctl request. 1060: */ 1061: deioctl(ifp, cmd, data) 1062: register struct ifnet *ifp; 1063: int cmd; 1064: caddr_t data; 1065: { 1066: register struct de_softc *ds = &de_softc[ifp->if_unit]; 1067: register struct uba_device *ui = deinfo[ifp->if_unit]; 1068: register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 1069: struct protosw *pr; 1070: struct sockaddr *sa; 1071: struct ifreq *ifr = (struct ifreq *)data; 1072: struct ifdevea *ifd = (struct ifdevea *)data; 1073: register struct ifaddr *ifa = (struct ifaddr *)data; 1074: int s = splimp(), error = 0; 1075: 1076: switch (cmd) { 1077: 1078: #ifdef DE_INT_LOOPBACK 1079: case SIOCENABLBACK: 1080: printf("de%d: internal loopback enable requested\n", ifp->if_unit); 1081: if ( (error = deloopback(ifp, ds, addr, YES)) != NULL ) 1082: break; 1083: ifp->if_flags |= IFF_LOOPBACK; 1084: break; 1085: 1086: case SIOCDISABLBACK: 1087: printf("de%d: internal loopback disable requested\n", ifp->if_unit); 1088: if ( (error = deloopback(ifp, ds, addr, NO)) != NULL ) 1089: break; 1090: ifp->if_flags &= ~IFF_LOOPBACK; 1091: deinit(ifp->if_unit); 1092: break; 1093: #endif /* DE_INT_LOOPBACK */ 1094: 1095: #ifdef DE_DO_PHYSADDR 1096: case SIOCRPHYSADDR: 1097: /* 1098: * read default hardware address. 1099: */ 1100: ds->ds_pcbb.pcbb0 = FC_RDDEFAULT; 1101: addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); 1102: if (dewait(ui, "read default hardware address", NO, YES)) { 1103: error = EIO; 1104: break; 1105: } 1106: /* 1107: * copy current physical address and default hardware address 1108: * for requestor. 1109: */ 1110: bcopy(&ds->ds_pcbb.pcbb2, ifd->default_pa, 6); 1111: bcopy(ds->ds_addr, ifd->current_pa, 6); 1112: break; 1113: 1114: 1115: case SIOCSPHYSADDR: 1116: /* Set the DNA address as the de's physical address */ 1117: ds->ds_pcbb.pcbb0 = FC_WTPHYAD; 1118: bcopy (ifr->ifr_addr.sa_data, &ds->ds_pcbb.pcbb2, 6); 1119: addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); 1120: (void) dewait(ui, "write physical address", NO, YES); 1121: bcopy((caddr_t)&ds->ds_pcbb.pcbb2,(caddr_t)ds->ds_addr, 1122: sizeof (ds->ds_addr)); 1123: deinit(ifp->if_unit); 1124: break; 1125: #endif /* DE_DO_PHYSADDR */ 1126: 1127: #ifdef DE_DO_MULTI 1128: case SIOCDELMULTI: 1129: case SIOCADDMULTI: 1130: { 1131: int i,j = -1,incaddr = ds->ds_ubaddr + MULTI_OFFSET; 1132: 1133: if (cmd==SIOCDELMULTI) { 1134: for (i = 0; i < NMULTI; i++) 1135: if (bcmp(&ds->ds_multicast[i],ifr->ifr_addr.sa_data,MULTISIZE) == 0) { 1136: if (--ds->ds_muse[i] == 0) 1137: bcopy(unused_multi,&ds->ds_multicast[i],MULTISIZE); 1138: } 1139: } else { 1140: for (i = 0; i < NMULTI; i++) { 1141: if (bcmp(&ds->ds_multicast[i],ifr->ifr_addr.sa_data,MULTISIZE) == 0) { 1142: ds->ds_muse[i]++; 1143: goto done; 1144: } 1145: if (bcmp(&ds->ds_multicast[i],unused_multi,MULTISIZE) == 0) 1146: j = i; 1147: } 1148: if (j == -1) { 1149: printf("de%d: mtmulti failed, multicast list full: %d\n", 1150: ui->ui_unit, NMULTI); 1151: error = ENOBUFS; 1152: goto done; 1153: } 1154: bcopy(ifr->ifr_addr.sa_data, &ds->ds_multicast[j], MULTISIZE); 1155: ds->ds_muse[j]++; 1156: } 1157: 1158: ds->ds_pcbb.pcbb0 = FC_WTMULTI; 1159: ds->ds_pcbb.pcbb2 = incaddr & 0xffff; 1160: ds->ds_pcbb.pcbb4 = (NMULTI << 8) | ((incaddr >> 16) & 03); 1161: addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); 1162: (void) dewait(ui, "set multicast address", NO, YES); 1163: break; 1164: 1165: } 1166: 1167: #endif /* DE_DO_MULTI */ 1168: 1169: #ifdef DE_DO_BCTRS 1170: case SIOCRDCTRS: 1171: case SIOCRDZCTRS: 1172: { 1173: register struct ctrreq *ctr = (struct ctrreq *)data; 1174: ubadr_t incaddr; 1175: 1176: ds->ds_pcbb.pcbb0 = cmd == SIOCRDCTRS ? FC_RDCNTS : FC_RCCNTS; 1177: incaddr = ds->ds_ubaddr + COUNTER_OFFSET; 1178: ds->ds_pcbb.pcbb2 = incaddr & 0xffff; 1179: ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; 1180: ds->ds_pcbb.pcbb6 = sizeof(struct de_counters) / sizeof (short); 1181: addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); 1182: if (dewait(ui, "read counts", NO, YES)) { 1183: error = ENOBUFS; 1184: break; 1185: } 1186: bzero(&ctr->ctr_ether, sizeof(struct estat)); 1187: ctr->ctr_type = CTR_ETHER; 1188: cpfromkern(&time, &atv, sizeof(struct timeval)); 1189: ctr->ctr_ether.est_seconds = (atv.tv_sec - ds->ds_ztime) > 0xfffe ? 0xffff : (atv.tv_sec - ds->ds_ztime); 1190: ctr->ctr_ether.est_byrcvd = *(long *)ds->ds_counters.c_brcvd; 1191: ctr->ctr_ether.est_bysent = *(long *)ds->ds_counters.c_bsent; 1192: ctr->ctr_ether.est_mbyrcvd = *(long *)ds->ds_counters.c_mbrcvd; 1193: ctr->ctr_ether.est_blrcvd = *(long *)ds->ds_counters.c_prcvd; 1194: ctr->ctr_ether.est_blsent = *(long *)ds->ds_counters.c_psent; 1195: ctr->ctr_ether.est_mblrcvd = *(long *)ds->ds_counters.c_mprcvd; 1196: ctr->ctr_ether.est_deferred = *(long *)ds->ds_counters.c_defer; 1197: ctr->ctr_ether.est_single = *(long *)ds->ds_counters.c_single; 1198: ctr->ctr_ether.est_multiple = *(long *)ds->ds_counters.c_multiple; 1199: ctr->ctr_ether.est_sf = ds->ds_counters.c_snderr; 1200: ctr->ctr_ether.est_sfbm = ds->ds_counters.c_sbm & 0xff; 1201: ctr->ctr_ether.est_collis = ds->ds_counters.c_collis; 1202: ctr->ctr_ether.est_rf = ds->ds_counters.c_rcverr; 1203: ctr->ctr_ether.est_rfbm = ds->ds_counters.c_rbm & 0xff; 1204: ctr->ctr_ether.est_unrecog = ds->ds_unrecog; 1205: ctr->ctr_ether.est_sysbuf = ds->ds_counters.c_ibuferr; 1206: ctr->ctr_ether.est_userbuf = ds->ds_counters.c_lbuferr; 1207: if (cmd == SIOCRDZCTRS) { 1208: cpfromkern(&time, &atv, sizeof(struct timeval)); 1209: ds->ds_ztime = atv.tv_sec; 1210: ds->ds_unrecog = 0; 1211: } 1212: break; 1213: } 1214: #endif /* DE_DO_BCTRS */ 1215: 1216: case SIOCSIFADDR: 1217: ifp->if_flags |= IFF_UP; 1218: deinit(ifp->if_unit); 1219: switch (ifa->ifa_addr.sa_family) { 1220: #ifdef INET 1221: case AF_INET: 1222: ((struct arpcom *)ifp)->ac_ipaddr = 1223: IA_SIN(ifa)->sin_addr; 1224: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 1225: break; 1226: #endif /* INET */ 1227: #ifdef NS 1228: case AF_NS: 1229: { 1230: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 1231: 1232: if (ns_nullhost(*ina)) { 1233: ina->x_host = * (union ns_host *) 1234: (de_softc[ifp->if_unit].ds_addr); 1235: } else { 1236: de_setaddr(ina->x_host.c_host,ifp->if_unit); 1237: } 1238: break; 1239: } 1240: #endif /* NS */ 1241: default: 1242: #ifdef not_on_pdp 1243: if (pr=iffamily_to_proto(ifa->ifa_addr.sa_family)) { 1244: error = (*pr->pr_ifioctl)(ifp, cmd, data); 1245: } 1246: #endif /* not_on_pdp */ 1247: #ifdef DE_DEBUG 1248: if (dedebug >= 1) 1249: printf("de%d: SIOCSIFADDR Unknown address family\n", ifp->if_unit); 1250: #endif /* DE_DEBUG */ 1251: error = EAFNOSUPPORT; 1252: break; 1253: } 1254: break; 1255: 1256: case SIOCSIFFLAGS: 1257: if ((ifp->if_flags & IFF_UP) == 0 && 1258: ds->ds_flags & DSF_RUNNING) { 1259: ((struct dedevice *) 1260: (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET; 1261: (void) dewait(deinfo[ifp->if_unit], "board reset(deioctl)", YES, NO); 1262: ds->ds_flags &= ~(DSF_LOCK | DSF_RUNNING); 1263: #ifdef DE_DEBUG 1264: if (dedebug >= 1) 1265: printf("de%d: reset and marked down\n",ifp->if_unit); 1266: #endif /* DE_DEBUG */ 1267: } else if (ifp->if_flags & IFF_UP && 1268: (ds->ds_flags & DSF_RUNNING) == 0) { 1269: deinit(ifp->if_unit); 1270: #ifdef DE_DEBUG 1271: if (dedebug >= 1) 1272: printf("de%d: reinitialized and marked up\n",ifp->if_unit); 1273: #endif /* DE_DEBUG */ 1274: } 1275: #ifdef DE_DEBUG 1276: if ((ifp->if_flags & IFF_DEBUG) == 0) { 1277: if (dedebug != 0) { 1278: dedebug = 0; 1279: printf("de%d: DEBUG disabled\n",ifp->if_unit); 1280: } 1281: } else { 1282: if (dedebug == 0) { 1283: dedebug = DE_DEBUG_LEVEL; 1284: printf("de%d: DEBUG enabled level=%d\n",ifp->if_unit,dedebug); 1285: } 1286: } 1287: #endif /* DE_DEBUG */ 1288: break; 1289: 1290: default: 1291: #ifdef not_on_pdp 1292: if (pr=iffamily_to_proto(ifa->ifa_addr.sa_family)) 1293: error = (*pr->pr_ifioctl)(ifp, cmd, data); 1294: else 1295: #endif /* not_on_pdp */ 1296: error = EINVAL; 1297: } 1298: done: splx(s); 1299: return (error); 1300: } 1301: 1302: #ifdef DE_INT_LOOPBACK 1303: /* 1304: * enable or disable internal loopback 1305: */ 1306: static 1307: deloopback(ifp, ds, addr, lb_ctl ) 1308: register struct ifnet *ifp; 1309: register struct de_softc *ds; 1310: register struct dedevice *addr; 1311: u_char lb_ctl; 1312: { 1313: register struct uba_device *ui = deinfo[ifp->if_unit]; 1314: /* 1315: * read current mode register. 1316: */ 1317: ds->ds_pcbb.pcbb0 = FC_RDMODE; 1318: addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); 1319: if (dewait(ui, "read mode register", NO, YES)) 1320: return(EIO); 1321: 1322: /* 1323: * set or clear the loopback bit as a function of lb_ctl and 1324: * return mode register to driver. 1325: */ 1326: if ( lb_ctl == YES ) { 1327: ds->ds_pcbb.pcbb2 |= MOD_LOOP; 1328: if (ds->ds_devid == DELUA) 1329: ds->ds_pcbb.pcbb2 |= MOD_INTL; 1330: else 1331: ds->ds_pcbb.pcbb2 &= ~MOD_HDX; 1332: } else { 1333: ds->ds_pcbb.pcbb2 &= ~MOD_LOOP; 1334: if (ds->ds_devid == DELUA) 1335: ds->ds_pcbb.pcbb2 &= ~MOD_INTL; 1336: else 1337: ds->ds_pcbb.pcbb2 |= MOD_HDX; 1338: } 1339: ds->ds_pcbb.pcbb0 = FC_WTMODE; 1340: addr->pclow = CMD_GETCMD|((ds->ds_flags & DSF_RUNNING) ? PCSR0_INTE : 0); 1341: if(dewait(ui, "write mode register", NO, YES)) 1342: return(EIO); 1343: 1344: return(NULL); 1345: } 1346: #endif /* DE_INT_LOOPBACK */ 1347: 1348: dewait(ui, fn, no_port, only_dni) 1349: register struct uba_device *ui; 1350: char *fn; 1351: int no_port; 1352: int only_dni; 1353: { 1354: register struct de_softc *ds = &de_softc[ui->ui_unit]; 1355: register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 1356: register csr0; 1357: 1358: if (only_dni) 1359: while ((addr->pcsr0 & PCSR0_DNI) == 0) 1360: ; 1361: else 1362: while ((addr->pcsr0 & PCSR0_INTR) == 0) 1363: ; 1364: csr0 = addr->pcsr0; 1365: addr->pchigh = csr0 >> 8; 1366: if ((csr0 & PCSR0_PCEI) || (no_port && (csr0 & PCSR0_DNI)==0)) { 1367: if (ds->ds_devid == DEUNA) 1368: printf("de%d: %s failed, csr0=%b, csr1=%b\n", 1369: ui->ui_unit, fn, csr0, PCSR0_BITS, 1370: addr->pcsr1, PCSR1_BITS); 1371: else 1372: printf("de%d: %s failed, csr0=%b, csr1=%b\n", 1373: ui->ui_unit, fn, csr0, PCSR0_BITS, 1374: addr->pcsr1, PCSR1_BITS_DELUA); 1375: } 1376: return(csr0 & PCSR0_PCEI); 1377: } 1378: 1379: #ifdef NS 1380: /* 1381: * Set the ethernet address for the unit, this sets the board's 1382: * hardware address to physaddr. This is only used if you have 1383: * NS defined. 1384: */ 1385: de_setaddr(physaddr, unit) 1386: u_char *physaddr; 1387: int unit; 1388: { 1389: register struct de_softc *ds = &de_softc[unit]; 1390: struct uba_device *ui = deinfo[unit]; 1391: register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 1392: 1393: if (! (ds->ds_flags & DSF_RUNNING)) 1394: return; 1395: bcopy(physaddr, &ds->ds_pcbb.pcbb2, 6); 1396: ds->ds_pcbb.pcbb0 = FC_WTPHYAD; 1397: addr->pclow = PCSR0_INTE | CMD_GETCMD; 1398: if (dewait(ui, "address changed", NO, NO) == 0) { 1399: ds->ds_flags |= DSF_SETADDR; 1400: bcopy(physaddr, ds->ds_addr, 6); 1401: } 1402: } 1403: #endif /* NS */ 1404: #endif /* NDE > 0 */