# 2.11BSD#431 - /usr/src/sys/pdpif/if_de.c

##### Functions

    de_setaddr        X
    deattach          X
    deinit            X
    deintr            X
    deioctl           X
    deoutput          X
    deprobe           X
    dewait            X

##### Variables

    atv               X
    de_softc          X
    dedebug           X
    dedriver          X
    deinfo            X
    destd             X
    unused_multi      X

##### Macros

    CRC_LEN           X
    DELUA_LOOP_LEN    X
    DE_DEBUG_LEVEL    X
    MAPBUFDESC        X
    NO                X
    YES               X
    dedataaddr        X

       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

- in line 367, 1236

de_ubainit defined in line 912; used 1 times

- in line 282

deattach defined in line 170; used 2 times

- in line 95, 104

deget defined in line 966; used 2 times

- in line 97, 675

deinit defined in line 257; used 6 times

- in line 95, 244, 1091, 1123, 1218, 1269

deintr defined in line 438; used 2 times

- in line 95, 125

deioctl defined in line 1061; used 2 times

- in line 95, 246

deloopback defined in line 1306; used 2 times

- in line 1081, 1088

deoutput defined in line 751; used 2 times

- in line 95, 245

deprobe defined in line 115; used 2 times

- in line 95, 104

deput defined in line 1037; used 1 times

- in line 404

deread defined in line 617; used 3 times

- in line 527, 587, 598

derecv defined in line 559; used 1 times

- in line 484

destart defined in line 382; used 3 times

- in line 362, 538, 894

dewait defined in line 1348; used 14 times

- in line 225, 231-235(2), 302, 324, 335, 1102, 1120, 1162, 1182, 1261, 1319, 1341, 1398

#### Defined variables

atv defined in line 112; used 7 times

- in line 372-373(2), 1188-1189(3), 1208-1209(2)

de_softc defined in line 74; used 10 times

- in line 173, 260, 389, 443, 563, 760, 1066, 1234, 1354, 1389

dedebug defined in line 85; used 19 times

- in line 186, 208, 240, 423, 504, 523, 543, 581, 714, 734, 886, 1248, 1264, 1271, 1277-1284(5)

dedriver defined in line 103; never used
deinfo defined in line 101; used 9 times

- in line 104, 261, 387, 441, 1067, 1260-1261(2), 1313, 1390

destd defined in line 99; used 1 times

- in line 104

unused_multi defined in line 89; used 3 times

- in line 218, 1137, 1145

#### Defined macros

CRC_LEN defined in line 72; used 1 times

- in line 572

DELUA_LOOP_LEN defined in line 107; used 1 times

- in line 818

DE_DEBUG_LEVEL defined in line 84; used 2 times

- in line 85, 1283

MAPBUFDESC defined in line 71; used 2 times

- in line 593, 637

NO defined in line 68; used 20 times

- in line 64-67(2), 225, 231-235(2), 302, 324(2), 335(2), 1088, 1102, 1120, 1162, 1182, 1261, 1319, 1341, 1398(2)

YES defined in line 62; used 15 times

- in line 58-61(2), 225, 231-235(2), 302, 1081, 1102, 1120, 1162, 1182, 1261, 1319, 1326, 1341

dedataaddr defined in line 642; used 2 times

- in line 650-651(2)

Last modified: 1994-01-01 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2719 |