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 = &top;
 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 */

Defined functions

de_setaddr defined in line 1385; used 2 times
de_ubainit defined in line 912; used 1 times
deattach defined in line 170; used 2 times
deget defined in line 966; used 2 times
deinit defined in line 257; used 6 times
deintr defined in line 438; used 2 times
deioctl defined in line 1061; used 2 times
deloopback defined in line 1306; used 2 times
deoutput defined in line 751; used 2 times
deprobe defined in line 115; used 2 times
deput defined in line 1037; used 1 times
deread defined in line 617; used 3 times
derecv defined in line 559; used 1 times
destart defined in line 382; used 3 times
dewait defined in line 1348; used 14 times

Defined variables

atv defined in line 112; used 7 times
de_softc defined in line 74; used 10 times
dedebug defined in line 85; used 19 times
dedriver defined in line 103; never used
deinfo defined in line 101; used 9 times
destd defined in line 99; used 1 times
unused_multi defined in line 89; used 3 times

Defined macros

CRC_LEN defined in line 72; used 1 times
DELUA_LOOP_LEN defined in line 107; used 1 times
DE_DEBUG_LEVEL defined in line 84; used 2 times
MAPBUFDESC defined in line 71; used 2 times
NO defined in line 68; used 20 times
YES defined in line 62; used 15 times
dedataaddr defined in line 642; used 2 times
Last modified: 1994-01-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 183
Valid CSS Valid XHTML 1.0 Strict