# 2.11BSD#431 - /usr/src/sys/vaxif/if_ex.c

##### Functions

    ex_setaddr        X
    exattach          X
    excdint           X
    exconfig          X
    exgetcbuf         X
    exhangrcv         X
    exinit            X
    exioctl           X
    exoutput          X
    exprobe           X
    exrecv            X
    exreset           X
    exstart           X
    exwatch           X

##### Variables

    ex_cvecs          X
    ex_ncall          X
    ex_softc          X
    exdriver          X
    exinfo            X
    exstd             X

##### Macros

    CM_OFFSET         X
    DEBUG             X
    EXWATCHINTVL      X
    EX_RUNNING        X
    EX_SETADDR        X
    EX_STATPENDING    X
    EX_XPENDING       X
    H2XENT_OFFSET     X
    H2XHDR_OFFSET     X
    INCORE_BASE       X
    INCORE_SIZE       X
    LVAL_OFF          X
    NH2X              X
    NX2H              X
    P_UNIADDR         X
    RVAL_OFF          X
    SA_OFFSET         X
    UNIADDR           X
    X2HENT_OFFSET     X
    X2HHDR_OFFSET     X
    exdataaddr        X
    xs_addr           X
    xs_if             X

##### struct's

    ex_cvecs          X
    ex_softc          X

       1: /*
       2:  * Copyright (c) 1982, 1986 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  *
       6:  *	@(#)if_ex.c	7.2 (Berkeley) 10/13/86
       7:  */
       8:
       9:
      10: #include "ex.h"
      11: #if NEX > 0
      12:
      13: /*
      14:  * Excelan EXOS 204 Interface
      15:  *
      16:  *	George Powers
      17:  *	Excelan Inc.
      18:  */
      19:
      20: #include "../machine/pte.h"
      21:
      22: #include "param.h"
      23: #include "systm.h"
      24: #include "mbuf.h"
      25: #include "buf.h"
      26: #include "protosw.h"
      27: #include "socket.h"
      28: #include "vmmac.h"
      29: #include "ioctl.h"
      30: #include "syslog.h"
      31: #include "errno.h"
      32:
      33: #include "../net/if.h"
      34: #include "../net/netisr.h"
      35: #include "../net/route.h"
      36:
      37: #ifdef  INET
      38: #include "../netinet/in.h"
      39: #include "../netinet/in_systm.h"
      40: #include "../netinet/in_var.h"
      41: #include "../netinet/ip.h"
      42: #include "../netinet/if_ether.h"
      43: #endif
      44:
      45: #ifdef NS
      46: #include "../netns/ns.h"
      47: #include "../netns/ns_if.h"
      48: #endif
      49:
      50: #include "../vax/cpu.h"
      51: #include "../vax/mtpr.h"
      52: #include "if_exreg.h"
      53: #include "if_uba.h"
      54: #include "../vaxuba/ubareg.h"
      55: #include "../vaxuba/ubavar.h"
      56:
      57: #define DEBUG           /* check for "impossible" events */
      58:
      59: #define NH2X 4          /* a sufficient number is critical */
      60: #define NX2H 4          /* this is pretty arbitrary */
      61: #define EXWATCHINTVL 10     /* call exwatch() every 10 seconds */
      62:
      63: int exprobe(), exattach(), excdint();
      64: struct  uba_device *exinfo[NEX];
      65: u_short exstd[] = { 0 };
      66: struct  uba_driver exdriver =
      67:     { exprobe, 0, exattach, 0, exstd, "ex", exinfo };
      68: int exinit(),exoutput(),exioctl(),exreset(),exwatch();
      69: struct ex_msg *exgetcbuf();
      70:
      71: /*
      72:  * Ethernet software status per interface.
      73:  *
      74:  * Each interface is referenced by a network interface structure,
      75:  * xs_if, which the routing code uses to locate the interface.
      76:  * This structure contains the output queue for the interface, its address, ...
      77:  * We also have, for each interface, a UBA interface structure, which
      78:  * contains information about the UNIBUS resources held by the interface:
      79:  * map registers, buffered data paths, etc.  Information is cached in this
      80:  * structure for use by the if_uba.c routines in running the interface
      81:  * efficiently.
      82:  */
      83: struct  ex_softc {
      84:     struct  arpcom xs_ac;       /* Ethernet common part */
      85: #define xs_if   xs_ac.ac_if     /* network-visible interface */
      86: #define xs_addr xs_ac.ac_enaddr     /* hardware Ethernet address */
      87: #ifdef DEBUG
      88:     int xs_wait;
      89: #endif
      90:     struct  ifuba xs_ifuba;     /* UNIBUS resources */
      91:     int xs_flags;       /* private flags */
      92: #define EX_XPENDING 1       /* xmit rqst pending on EXOS */
      93: #define EX_STATPENDING  (1<<1)      /* stats rqst pending on EXOS */
      94: #define EX_RUNNING  (1<<2)      /* board is running */
      95: #define EX_SETADDR  (1<<3)      /* physaddr has been changed */
      96:     struct  ex_msg *xs_h2xnext; /* host pointer to request queue */
      97:     struct  ex_msg *xs_x2hnext; /* host pointer to reply queue */
      98:     int xs_ubaddr;      /* map info for structs below */
      99: #define UNIADDR(x)  ((u_long)(x)&0x3FFFF)
     100: #define P_UNIADDR(x)    ((u_long)(x)&0x3FFF0)
     101:     /* the following structures are always mapped in */
     102:     u_short xs_h2xhdr;      /* EXOS's request queue header */
     103:     u_short xs_x2hhdr;      /* EXOS's reply queue header */
     104:     struct  ex_msg xs_h2xent[NH2X]; /* request msg buffers */
     105:     struct  ex_msg xs_x2hent[NX2H]; /* reply msg buffers */
     106:     struct  confmsg xs_cm;      /* configuration message */
     107:     struct  stat_array xs_xsa;  /* EXOS writes stats here */
     108:     /* end mapped area */
     109: #define INCORE_BASE(p)  ((caddr_t)((u_long)(&(p)->xs_h2xhdr) & 0xFFFFFFF0))
     110: #define RVAL_OFF(unit, n) \
     111:     ((caddr_t)(&(ex_softc[unit].n)) - INCORE_BASE(&ex_softc[unit]))
     112: #define LVAL_OFF(unit, n) \
     113:     ((caddr_t)(ex_softc[unit].n) - INCORE_BASE(&ex_softc[unit]))
     114: #define H2XHDR_OFFSET(unit) RVAL_OFF(unit, xs_h2xhdr)
     115: #define X2HHDR_OFFSET(unit) RVAL_OFF(unit, xs_x2hhdr)
     116: #define H2XENT_OFFSET(unit) LVAL_OFF(unit, xs_h2xent)
     117: #define X2HENT_OFFSET(unit) LVAL_OFF(unit, xs_x2hent)
     118: #define CM_OFFSET(unit)     RVAL_OFF(unit, xs_cm)
     119: #define SA_OFFSET(unit)     RVAL_OFF(unit, xs_xsa)
     120: #define INCORE_SIZE(unit)   RVAL_OFF(unit, xs_end)
     121:     int xs_end;         /* place holder */
     122: } ex_softc[NEX];
     123:
     124: /*
     125:  * The following structure is a kludge to store a cvec value
     126:  * between the time exprobe is called, and exconfig.
     127:  */
     128: struct  ex_cvecs {
     129:     struct  exdevice *xc_csraddr;
     130:     int xc_cvec;
     131: }ex_cvecs[NEX];
     132:
     133: int ex_ncall = 0;           /* counts calls to exprobe */
     134:
     135: exprobe(reg)
     136:     caddr_t reg;
     137: {
     138:     register int br, cvec;      /* r11, r10 value-result */
     139:     register struct exdevice *addr = (struct exdevice *)reg;
     140:     register i;
     141:
     142:     /*
     143: 	 * We program the EXOS interrupt vector, like dmf device.
     144: 	 */
     145:     br = 0x15;
     146:     cvec = (uba_hd[numuba].uh_lastiv -= 4);
     147:     ex_cvecs[ex_ncall].xc_csraddr = addr;
     148:     ex_cvecs[ex_ncall].xc_cvec = cvec;
     149:     /*
     150: 	 * Reset EXOS and run self-test (guaranteed to
     151: 	 * complete within 2 seconds).
     152: 	 */
     153:     addr->xd_porta = EX_RESET;
     154:     i = 2000;
     155:     while (((addr->xd_portb & EX_TESTOK) == 0) && --i)
     156:         DELAY(1000);
     157:     if ((addr->xd_portb & EX_TESTOK) == 0) {
     158:         printf("ex: self-test failed\n");
     159:         return 0;
     160:     }
     161: #ifdef lint
     162:     br = br;
     163:     excdint(0);
     164: #endif
     165:     ex_ncall++;
     166:     return (sizeof(struct exdevice));
     167: }
     168:
     169: /*
     170:  * Interface exists: make available by filling in network interface
     171:  * record.  System will initialize the interface when it is ready
     172:  * to accept packets.  Board is temporarily configured and issues
     173:  * a NET_ADDRS command, only to get the Ethernet address.
     174:  */
     175: exattach(ui)
     176:     struct uba_device *ui;
     177: {
     178:     register struct ex_softc *xs = &ex_softc[ui->ui_unit];
     179:     register struct ifnet *ifp = &xs->xs_if;
     180:     register struct exdevice *addr = (struct exdevice *)ui->ui_addr;
     181:     register struct ex_msg *bp;
     182:     int unit = ui->ui_unit;
     183:     ifp->if_unit = ui->ui_unit;
     184:     ifp->if_name = "ex";
     185:     ifp->if_mtu = ETHERMTU;
     186:
     187:     /*
     188: 	 * Temporarily map queues in order to configure EXOS
     189: 	 */
     190:     xs->xs_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(xs),
     191:         INCORE_SIZE(unit), 0);
     192:     exconfig(ui, 0);            /* without interrupts */
     193:     if (xs->xs_cm.cm_cc) goto badconf;
     194:
     195:     bp = exgetcbuf(xs);
     196:     bp->mb_rqst = LLNET_ADDRS;
     197:     bp->mb_na.na_mask = READ_OBJ;
     198:     bp->mb_na.na_slot = PHYSSLOT;
     199:     bp->mb_status |= MH_EXOS;
     200:     addr->xd_portb = EX_NTRUPT;
     201:     bp = xs->xs_x2hnext;
     202:     while ((bp->mb_status & MH_OWNER) == MH_EXOS)   /* poll for reply */
     203:         ;
     204:     printf("ex%d: HW %c.%c, NX %c.%c, hardware address %s\n",
     205:         ui->ui_unit, xs->xs_cm.cm_vc[2], xs->xs_cm.cm_vc[3],
     206:         xs->xs_cm.cm_vc[0], xs->xs_cm.cm_vc[1],
     207:         ether_sprintf(bp->mb_na.na_addrs));
     208:     bcopy((caddr_t)bp->mb_na.na_addrs, (caddr_t)xs->xs_addr,
     209:         sizeof (xs->xs_addr));
     210:
     211:     ifp->if_init = exinit;
     212:     ifp->if_output = exoutput;
     213:     ifp->if_ioctl = exioctl;
     214:     ifp->if_reset = exreset;
     215:     ifp->if_flags = IFF_BROADCAST;
     216:     xs->xs_ifuba.ifu_flags = UBA_CANTWAIT;
     217:     if_attach(ifp);
     218: badconf:
     219:     ubarelse(ui->ui_ubanum, &xs->xs_ubaddr);
     220: }
     221:
     222: /*
     223:  * Reset of interface after UNIBUS reset.
     224:  * If interface is on specified uba, reset its state.
     225:  */
     226: exreset(unit, uban)
     227:     int unit, uban;
     228: {
     229:     register struct uba_device *ui;
     230:
     231:     if (unit >= NEX || (ui = exinfo[unit]) == 0 || ui->ui_alive == 0 ||
     232:         ui->ui_ubanum != uban)
     233:         return;
     234:     printf(" ex%d", unit);
     235:     ex_softc[unit].xs_if.if_flags &= ~IFF_RUNNING;
     236:     ex_softc[unit].xs_flags &= ~EX_RUNNING;
     237:     exinit(unit);
     238: }
     239:
     240: /*
     241:  * Initialization of interface; clear recorded pending
     242:  * operations, and reinitialize UNIBUS usage.
     243:  * Called at boot time (with interrupts disabled?),
     244:  * and at ifconfig time via exioctl, with interrupts disabled.
     245:  */
     246: exinit(unit)
     247:     int unit;
     248: {
     249:     register struct ex_softc *xs = &ex_softc[unit];
     250:     register struct uba_device *ui = exinfo[unit];
     251:     register struct exdevice *addr = (struct exdevice *)ui->ui_addr;
     252:     register struct ifnet *ifp = &xs->xs_if;
     253:     register struct ex_msg *bp;
     254:     int s;
     255:
     256:     /* not yet, if address still unknown */
     257:     if (ifp->if_addrlist == (struct ifaddr *)0)
     258:         return;
     259:     if (xs->xs_flags & EX_RUNNING)
     260:         return;
     261:
     262:     if ((ifp->if_flags & IFF_RUNNING) == 0) {
     263:         if (if_ubainit(&xs->xs_ifuba, ui->ui_ubanum,
     264:             sizeof (struct ether_header),
     265:             (int)btoc(EXMAXRBUF-sizeof(struct ether_header))) == 0) {
     266:             printf("ex%d: can't initialize\n", unit);
     267:             xs->xs_if.if_flags &= ~IFF_UP;
     268:             return;
     269:         }
     270:         xs->xs_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(xs),
     271:             INCORE_SIZE(unit), 0);
     272:     }
     273:     exconfig(ui, 4);        /* with vectored interrupts*/
     274:     /*
     275: 	 * Put EXOS on the Ethernet, using NET_MODE command
     276: 	 */
     277:     bp = exgetcbuf(xs);
     278:     bp->mb_rqst = LLNET_MODE;
     279:     bp->mb_nm.nm_mask = WRITE_OBJ;
     280:     bp->mb_nm.nm_optn = 0;
     281:     bp->mb_nm.nm_mode = MODE_PERF;
     282:     bp->mb_status |= MH_EXOS;
     283:     addr->xd_portb = EX_NTRUPT;
     284:     bp = xs->xs_x2hnext;
     285:     while ((bp->mb_status & MH_OWNER) == MH_EXOS)   /* poll for reply */
     286:         ;
     287:     bp->mb_length = MBDATALEN;
     288:     bp->mb_status |= MH_EXOS;       /* free up buffer */
     289:     addr->xd_portb = EX_NTRUPT;     /* tell EXOS about it */
     290:     xs->xs_x2hnext = xs->xs_x2hnext->mb_next;
     291:
     292:     ifp->if_watchdog = exwatch;
     293:     ifp->if_timer = EXWATCHINTVL;
     294:     s = splimp();   /* are interrupts always disabled here, anyway? */
     295:     exhangrcv(unit);            /* hang receive request */
     296:     xs->xs_if.if_flags |= IFF_RUNNING;
     297:     xs->xs_flags |= EX_RUNNING;
     298:     if (xs->xs_flags & EX_SETADDR)
     299:         ex_setaddr((u_char *)0, unit);
     300:     exstart(unit);              /* start transmits */
     301:     splx(s);
     302: }
     303:
     304: /*
     305:  * Reset, test, and configure EXOS.  This routine assumes
     306:  * that message queues, etc. have already been mapped into
     307:  * the UBA.  It is called by exinit, and should also be
     308:  * callable by exattach.
     309:  */
     310: exconfig(ui, itype)
     311:     struct  uba_device *ui;
     312:     int itype;
     313: {
     314:     register int unit = ui->ui_unit;
     315:     register struct ex_softc *xs = &ex_softc[unit];
     316:     register struct exdevice *addr = (struct exdevice *) ui->ui_addr;
     317:     register struct confmsg *cm = &xs->xs_cm;
     318:     register struct ex_msg *bp;
     319:     int i;
     320:     u_long shiftreg;
     321:
     322:     xs->xs_flags = 0;
     323:     /*
     324: 	 * Reset EXOS, wait for self-test to complete
     325: 	 */
     326:     addr->xd_porta = EX_RESET;
     327:     while ((addr->xd_portb & EX_TESTOK) == 0)
     328:         ;
     329:     /*
     330: 	 * Set up configuration message.
     331: 	 */
     332:     cm->cm_1rsrv = 1;
     333:     cm->cm_cc = 0xFF;
     334:     cm->cm_opmode = 0;      /* link-level controller mode */
     335:     cm->cm_dfo = 0x0101;        /* enable host data order conversion */
     336:     cm->cm_dcn1 = 1;
     337:     cm->cm_2rsrv[0] =
     338:         cm->cm_2rsrv[1] = 0;
     339:     cm->cm_ham = 3;         /* absolute address mode */
     340:     cm->cm_3rsrv = 0;
     341:     cm->cm_mapsiz = 0;
     342:     cm->cm_byteptrn[0] = 0x01;  /* EXOS deduces data order of host */
     343:     cm->cm_byteptrn[1] = 0x03;  /*  by looking at this pattern */
     344:     cm->cm_byteptrn[2] = 0x07;
     345:     cm->cm_byteptrn[3] = 0x0F;
     346:     cm->cm_wordptrn[0] = 0x0103;
     347:     cm->cm_wordptrn[1] = 0x070F;
     348:     cm->cm_lwordptrn = 0x0103070F;
     349:     for (i=0; i<20; i++) cm->cm_rsrvd[i] = 0;
     350:     cm->cm_mba = 0xFFFFFFFF;
     351:     cm->cm_nproc = 0xFF;
     352:     cm->cm_nmbox = 0xFF;
     353:     cm->cm_nmcast = 0xFF;
     354:     cm->cm_nhost = 1;
     355:     cm->cm_h2xba = P_UNIADDR(xs->xs_ubaddr);
     356:     cm->cm_h2xhdr = H2XHDR_OFFSET(unit);
     357:     cm->cm_h2xtyp = 0;      /* should never wait for rqst buffer */
     358:     cm->cm_x2hba = cm->cm_h2xba;
     359:     cm->cm_x2hhdr = X2HHDR_OFFSET(unit);
     360:     cm->cm_x2htyp = itype;      /* 0 for none, 4 for vectored */
     361:     for (i=0; (addr != ex_cvecs[i].xc_csraddr); i++)
     362: #ifdef DEBUG
     363:     if (i >= NEX)
     364:         panic("ex: matching csr address not found");
     365: #endif
     366:         ;
     367:     cm->cm_x2haddr = ex_cvecs[i].xc_cvec;   /* stashed here by exprobe */
     368:     /*
     369: 	 * Set up message queues and headers.
     370: 	 * First the request queue.
     371: 	 */
     372:     for (bp = &xs->xs_h2xent[0]; bp < &xs->xs_h2xent[NH2X]; bp++) {
     373:         bp->mb_link = (u_short)((char *)(bp+1)-INCORE_BASE(xs));
     374:         bp->mb_rsrv = 0;
     375:         bp->mb_length = MBDATALEN;
     376:         bp->mb_status = MH_HOST;
     377:         bp->mb_next = bp+1;
     378:     }
     379:     xs->xs_h2xhdr =
     380:         xs->xs_h2xent[NH2X-1].mb_link =
     381:         (u_short)H2XENT_OFFSET(unit);
     382:     xs->xs_h2xnext =
     383:         xs->xs_h2xent[NH2X-1].mb_next =
     384:         xs->xs_h2xent;
     385:
     386:     /* Now the reply queue. */
     387:     for (bp = &xs->xs_x2hent[0]; bp < &xs->xs_x2hent[NX2H]; bp++) {
     388:         bp->mb_link = (u_short)((char *)(bp+1)-INCORE_BASE(xs));
     389:         bp->mb_rsrv = 0;
     390:         bp->mb_length = MBDATALEN;
     391:         bp->mb_status = MH_EXOS;
     392:         bp->mb_next = bp+1;
     393:     }
     394:     xs->xs_x2hhdr =
     395:         xs->xs_x2hent[NX2H-1].mb_link =
     396:         (u_short)X2HENT_OFFSET(unit);
     397:     xs->xs_x2hnext =
     398:         xs->xs_x2hent[NX2H-1].mb_next =
     399:         xs->xs_x2hent;
     400:
     401:     /*
     402: 	 * Write config msg address to EXOS and wait for
     403: 	 * configuration to complete (guaranteed response
     404: 	 * within 2 seconds).
     405: 	 */
     406:     shiftreg = (u_long)0x0000FFFF;
     407:     for (i = 0; i < 8; i++) {
     408:         if (i == 4)
     409:             shiftreg = P_UNIADDR(xs->xs_ubaddr) + CM_OFFSET(unit);
     410:         while (addr->xd_portb & EX_UNREADY)
     411:             ;
     412:         addr->xd_portb = (u_char)(shiftreg & 0xFF);
     413:         shiftreg >>= 8;
     414:     }
     415:     for (i = 1000000; (cm->cm_cc == 0xFF) && i; --i);
     416:     if (cm->cm_cc)
     417:         printf("ex%d: configuration failed; cc = %x\n",
     418:             unit, cm->cm_cc);
     419: }
     420:
     421: /*
     422:  * Start or re-start output on interface.
     423:  * Get another datagram to send off of the interface queue,
     424:  * and map it to the interface before starting the output.
     425:  * This routine is called by exinit(), exoutput(), and excdint().
     426:  * In all cases, interrupts by EXOS are disabled.
     427:  */
     428: exstart(unit)
     429:     int unit;
     430: {
     431:     struct uba_device *ui = exinfo[unit];
     432:     register struct ex_softc *xs = &ex_softc[unit];
     433:     register struct exdevice *addr = (struct exdevice *)ui->ui_addr;
     434:     register struct ex_msg *bp;
     435:     struct mbuf *m;
     436:         int len;
     437:
     438: #ifdef DEBUG
     439:     if (xs->xs_flags & EX_XPENDING)
     440:         panic("exstart(): xmit still pending");
     441: #endif
     442:     IF_DEQUEUE(&xs->xs_if.if_snd, m);
     443:     if (m == 0)
     444:         return;
     445:     len = if_wubaput(&xs->xs_ifuba, m);
     446:     if (len - sizeof(struct ether_header) < ETHERMIN)
     447:         len = ETHERMIN + sizeof(struct ether_header);
     448:     /*
     449: 	 * Place a transmit request.
     450: 	 */
     451:     bp = exgetcbuf(xs);
     452:     bp->mb_rqst = LLRTRANSMIT;
     453:     bp->mb_et.et_nblock = 1;
     454:     bp->mb_et.et_blks[0].bb_len = (u_short)len;
     455:     *(u_long *)bp->mb_et.et_blks[0].bb_addr =
     456:         UNIADDR(xs->xs_ifuba.ifu_w.ifrw_info);
     457:     xs->xs_flags |= EX_XPENDING;
     458:     bp->mb_status |= MH_EXOS;
     459:     addr->xd_portb = EX_NTRUPT;
     460: }
     461:
     462: /*
     463:  * Command done interrupt.
     464:  */
     465: excdint(unit)
     466:     int unit;
     467: {
     468:     register struct ex_softc *xs = &ex_softc[unit];
     469:     register struct ex_msg *bp = xs->xs_x2hnext;
     470:     struct uba_device *ui = exinfo[unit];
     471:     struct exdevice *addr = (struct exdevice *)ui->ui_addr;
     472:
     473:     while ((bp->mb_status & MH_OWNER) == MH_HOST) {
     474:         switch (bp->mb_rqst) {
     475:         case LLRECEIVE:
     476:             exrecv(unit, bp);
     477:             exhangrcv(unit);
     478:             break;
     479:         case LLRTRANSMIT:
     480: #ifdef DEBUG
     481:             if ((xs->xs_flags & EX_XPENDING) == 0)
     482:                 panic("exxmit: no xmit pending");
     483: #endif
     484:             xs->xs_flags &= ~EX_XPENDING;
     485:             xs->xs_if.if_opackets++;
     486:             if (bp->mb_rply == LL_OK) {
     487:                 ;
     488:             } else if (bp->mb_rply & LLXM_1RTRY) {
     489:                 xs->xs_if.if_collisions++;
     490:             } else if (bp->mb_rply & LLXM_RTRYS) {
     491:                 xs->xs_if.if_collisions += 2;   /* guess */
     492:             } else if (bp->mb_rply & LLXM_ERROR) {
     493:                 xs->xs_if.if_oerrors++;
     494:                 log(LOG_ERR, "ex%d: transmit error=%b\n",
     495:                     unit, bp->mb_rply, XMIT_BITS);
     496:             }
     497:             if (xs->xs_ifuba.ifu_xtofree) {
     498:                 m_freem(xs->xs_ifuba.ifu_xtofree);
     499:                 xs->xs_ifuba.ifu_xtofree = 0;
     500:             }
     501:             exstart(unit);
     502:             break;
     503:         case LLNET_STSTCS:
     504:             xs->xs_if.if_ierrors = xs->xs_xsa.sa_crc;
     505:             xs->xs_flags &= ~EX_STATPENDING;
     506:             break;
     507:         case LLNET_ADDRS:
     508:         case LLNET_RECV:
     509:             break;
     510: #ifdef  DEBUG
     511:         default:
     512:             panic("ex%d: unknown reply");
     513: #endif
     514:         } /* end of switch */
     515:         bp->mb_length = MBDATALEN;
     516:         bp->mb_status |= MH_EXOS;       /* free up buffer */
     517:         addr->xd_portb = EX_NTRUPT;     /* tell EXOS about it */
     518:         bp = xs->xs_x2hnext = xs->xs_x2hnext->mb_next;
     519:     }
     520: }
     521:
     522: /*
     523:  * Get a request buffer, fill in standard values, advance pointer.
     524:  */
     525: struct ex_msg *
     526: exgetcbuf(xs)
     527:     struct ex_softc *xs;
     528: {
     529:     register struct ex_msg *bp = xs->xs_h2xnext;
     530:
     531: #ifdef DEBUG
     532:     if ((bp->mb_status & MH_OWNER) == MH_EXOS)
     533:         panic("exgetcbuf(): EXOS owns message buffer");
     534: #endif
     535:     bp->mb_1rsrv = 0;
     536:     bp->mb_length = MBDATALEN;
     537:     xs->xs_h2xnext = xs->xs_h2xnext->mb_next;
     538:     return bp;
     539: }
     540:
     541: /*
     542:  * Process Ethernet receive completion:
     543:  *	If input error just drop packet.
     544:  *	Otherwise purge input buffered data path and examine
     545:  *	packet to determine type.  If can't determine length
     546:  *	from type, then have to drop packet.  Otherwise decapsulate
     547:  *	packet based on type and pass to type-specific higher-level
     548:  *	input routine.
     549:  */
     550: exrecv(unit, bp)
     551:     int unit;
     552:     register struct ex_msg *bp;
     553: {
     554:     register struct ex_softc *xs = &ex_softc[unit];
     555:     register struct ether_header *eh;
     556:         struct mbuf *m;
     557:     register int len, off, resid;
     558:     register struct ifqueue *inq;
     559:     int s;
     560:
     561:     xs->xs_if.if_ipackets++;
     562:     len = bp->mb_er.er_blks[0].bb_len - sizeof(struct ether_header) - 4;
     563:     if (bp->mb_rply != LL_OK) {
     564:         xs->xs_if.if_ierrors++;
     565:         log(LOG_ERR, "ex%d: receive error=%b\n",
     566:             unit, bp->mb_rply, RECV_BITS);
     567:         return;
     568:     }
     569:     eh = (struct ether_header *)(xs->xs_ifuba.ifu_r.ifrw_addr);
     570:
     571:     /*
     572: 	 * Deal with trailer protocol: if type is trailer
     573: 	 * get true type from first 16-bit word past data.
     574: 	 * Remember that type was trailer by setting off.
     575: 	 */
     576:     eh->ether_type = ntohs((u_short)eh->ether_type);
     577: #define exdataaddr(eh, off, type)   ((type)(((caddr_t)((eh)+1)+(off))))
     578:     if (eh->ether_type >= ETHERTYPE_TRAIL &&
     579:         eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
     580:         off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
     581:         if (off >= ETHERMTU)
     582:             return;     /* sanity */
     583:         eh->ether_type = ntohs(*exdataaddr(eh, off, u_short *));
     584:         resid = ntohs(*(exdataaddr(eh, off+2, u_short *)));
     585:         if (off + resid > len)
     586:             return;     /* sanity */
     587:         len = off + resid;
     588:     } else
     589:         off = 0;
     590:     if (len == 0)
     591:         return;
     592:
     593:     /*
     594: 	 * Pull packet off interface.  Off is nonzero if packet
     595: 	 * has trailing header; if_rubaget will then force this header
     596: 	 * information to be at the front, but we still have to drop
     597: 	 * the type and length which are at the front of any trailer data.
     598: 	 */
     599:     m = if_rubaget(&xs->xs_ifuba, len, off, &xs->xs_if);
     600:     if (m == 0)
     601:         return;
     602:     if (off) {
     603:         struct ifnet *ifp;
     604:
     605:         ifp = *(mtod(m, struct ifnet **));
     606:         m->m_off += 2 * sizeof (u_short);
     607:         m->m_len -= 2 * sizeof (u_short);
     608:         *(mtod(m, struct ifnet **)) = ifp;
     609:     }
     610:     switch (eh->ether_type) {
     611:
     612: #ifdef INET
     613:     case ETHERTYPE_IP:
     614:         schednetisr(NETISR_IP); /* is this necessary */
     615:         inq = &ipintrq;
     616:         break;
     617:
     618:     case ETHERTYPE_ARP:
     619:         arpinput(&xs->xs_ac, m);
     620:         return;
     621: #endif
     622: #ifdef NS
     623:     case ETHERTYPE_NS:
     624:         schednetisr(NETISR_NS);
     625:         inq = &nsintrq;
     626:         break;
     627:
     628: #endif
     629:     default:
     630:         m_freem(m);
     631:         return;
     632:     }
     633:
     634:     s = splimp();
     635:     if (IF_QFULL(inq)) {
     636:         IF_DROP(inq);
     637:         m_freem(m);
     638:     } else
     639:         IF_ENQUEUE(inq, m);
     640:     splx(s);
     641: }
     642:
     643: /*
     644:  * Send receive request to EXOS.
     645:  * This routine is called by exinit and excdint,
     646:  * with interrupts disabled in both cases.
     647:  */
     648: exhangrcv(unit)
     649:     int unit;
     650: {
     651:     register struct ex_softc *xs = &ex_softc[unit];
     652:     register struct ex_msg *bp = exgetcbuf(xs);
     653:     struct exdevice *addr = (struct exdevice *)exinfo[unit]->ui_addr;
     654:
     655:     bp->mb_rqst = LLRECEIVE;
     656:     bp->mb_er.er_nblock = 1;
     657:     bp->mb_er.er_blks[0].bb_len = EXMAXRBUF;
     658:     *(u_long *)bp->mb_er.er_blks[0].bb_addr =
     659:         UNIADDR(xs->xs_ifuba.ifu_r.ifrw_info);
     660:     bp->mb_status |= MH_EXOS;
     661:     addr->xd_portb = EX_NTRUPT;
     662: }
     663:
     664: /*
     665:  * Ethernet output routine.
     666:  * Encapsulate a packet of type family for the local net.
     667:  * Use trailer local net encapsulation if enough data in first
     668:  * packet leaves a multiple of 512 bytes of data in remainder.
     669:  */
     670: exoutput(ifp, m0, dst)
     671:     register struct ifnet *ifp;
     672:     register struct mbuf *m0;
     673:     struct sockaddr *dst;
     674: {
     675:     int type, s, error;
     676:     u_char edst[6];
     677:     struct in_addr idst;
     678:     register struct ex_softc *xs = &ex_softc[ifp->if_unit];
     679:     register struct mbuf *m = m0;
     680:     register struct ether_header *eh;
     681:     register int off;
     682:     int usetrailers;
     683:
     684:     if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
     685:         error = ENETDOWN;
     686:         goto bad;
     687:     }
     688:     switch (dst->sa_family) {
     689:
     690: #ifdef INET
     691:     case AF_INET:
     692:         idst = ((struct sockaddr_in *)dst)->sin_addr;
     693:         if (!arpresolve(&xs->xs_ac, m, &idst, edst, &usetrailers))
     694:             return (0); /* if not yet resolved */
     695:         off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
     696:         if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
     697:             m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
     698:             type = ETHERTYPE_TRAIL + (off>>9);
     699:             m->m_off -= 2 * sizeof (u_short);
     700:             m->m_len += 2 * sizeof (u_short);
     701:             *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
     702:             *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
     703:             goto gottrailertype;
     704:         }
     705:         type = ETHERTYPE_IP;
     706:         off = 0;
     707:         goto gottype;
     708: #endif
     709: #ifdef NS
     710:     case AF_NS:
     711:         type = ETHERTYPE_NS;
     712:         bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
     713:         (caddr_t)edst, sizeof (edst));
     714:         off = 0;
     715:         goto gottype;
     716: #endif
     717:
     718:     case AF_UNSPEC:
     719:         eh = (struct ether_header *)dst->sa_data;
     720:         bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
     721:         type = eh->ether_type;
     722:         goto gottype;
     723:
     724:     default:
     725:         printf("ex%d: can't handle af%d\n", ifp->if_unit,
     726:             dst->sa_family);
     727:         error = EAFNOSUPPORT;
     728:         goto bad;
     729:     }
     730:
     731: gottrailertype:
     732:     /*
     733: 	 * Packet to be sent as trailer: move first packet
     734: 	 * (control information) to end of chain.
     735: 	 */
     736:     while (m->m_next)
     737:         m = m->m_next;
     738:     m->m_next = m0;
     739:     m = m0->m_next;
     740:     m0->m_next = 0;
     741:     m0 = m;
     742:
     743: gottype:
     744:     /*
     745: 	 * Add local net header.  If no space in first mbuf,
     746: 	 * allocate another.
     747: 	 */
     748:     if (m->m_off > MMAXOFF ||
     749:         MMINOFF + sizeof (struct ether_header) > m->m_off) {
     750:         m = m_get(M_DONTWAIT, MT_HEADER);
     751:         if (m == 0) {
     752:             error = ENOBUFS;
     753:             goto bad;
     754:         }
     755:         m->m_next = m0;
     756:         m->m_off = MMINOFF;
     757:         m->m_len = sizeof (struct ether_header);
     758:     } else {
     759:         m->m_off -= sizeof (struct ether_header);
     760:         m->m_len += sizeof (struct ether_header);
     761:     }
     762:     eh = mtod(m, struct ether_header *);
     763:     eh->ether_type = htons((u_short)type);
     764:     bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
     765:     bcopy((caddr_t)xs->xs_addr, (caddr_t)eh->ether_shost, 6);
     766:
     767:     /*
     768: 	 * Queue message on interface, and start output if interface
     769: 	 * not yet active.
     770: 	 */
     771:     s = splimp();
     772:     if (IF_QFULL(&ifp->if_snd)) {
     773:         IF_DROP(&ifp->if_snd);
     774:         splx(s);
     775:         m_freem(m);
     776:         return (ENOBUFS);
     777:     }
     778:     IF_ENQUEUE(&ifp->if_snd, m);
     779:     /*
     780: 	 * If transmit request not already pending, then
     781: 	 * kick the back end.
     782: 	 */
     783:     if ((xs->xs_flags & EX_XPENDING) == 0) {
     784:         exstart(ifp->if_unit);
     785:     }
     786: #ifdef DEBUG
     787:     else {
     788:         xs->xs_wait++;
     789:     }
     790: #endif
     791:     splx(s);
     792:     return (0);
     793:
     794: bad:
     795:     m_freem(m0);
     796:     return (error);
     797: }
     798:
     799: /*
     800:  * Watchdog routine - place stats request to EXOS
     801:  * (This could be dispensed with, if you don't care
     802:  *  about the if_ierrors count, or are willing to receive
     803:  *  bad packets in order to derive it.)
     804:  */
     805: exwatch(unit)
     806:     int unit;
     807: {
     808:     struct uba_device *ui = exinfo[unit];
     809:     struct exdevice *addr = (struct exdevice *)ui->ui_addr;
     810:     register struct ex_softc *xs = &ex_softc[unit];
     811:     register struct ex_msg *bp;
     812:     int s = splimp();
     813:
     814:     if (xs->xs_flags & EX_STATPENDING) goto exspnd;
     815:     bp = exgetcbuf(xs);
     816:     xs->xs_flags |= EX_STATPENDING;
     817:     bp->mb_rqst = LLNET_STSTCS;
     818:     bp->mb_ns.ns_mask = READ_OBJ;
     819:     bp->mb_ns.ns_rsrv = 0;
     820:     bp->mb_ns.ns_nobj = 8;      /* read all 8 stats objects */
     821:     bp->mb_ns.ns_xobj = 0;      /* starting with the 1st one */
     822:     bp->mb_ns.ns_bufp = P_UNIADDR(xs->xs_ubaddr) + SA_OFFSET(unit);
     823:     bp->mb_status |= MH_EXOS;
     824:     addr->xd_portb = EX_NTRUPT;
     825: exspnd:
     826:     splx(s);
     827:     xs->xs_if.if_timer = EXWATCHINTVL;
     828: }
     829:
     830: /*
     831:  * Process an ioctl request.
     832:  */
     833: exioctl(ifp, cmd, data)
     834:     register struct ifnet *ifp;
     835:     int cmd;
     836:     caddr_t data;
     837: {
     838:     register struct ifaddr *ifa = (struct ifaddr *)data;
     839:     register struct ex_softc *xs = &ex_softc[ifp->if_unit];
     840:     int s = splimp(), error = 0;
     841:
     842:     switch (cmd) {
     843:
     844:     case SIOCSIFADDR:
     845:                 ifp->if_flags |= IFF_UP;
     846:                 exinit(ifp->if_unit);
     847:
     848:                 switch (ifa->ifa_addr.sa_family) {
     849: #ifdef INET
     850:         case AF_INET:
     851:             ((struct arpcom *)ifp)->ac_ipaddr =
     852:                 IA_SIN(ifa)->sin_addr;
     853:             arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
     854:             break;
     855: #endif
     856: #ifdef NS
     857:         case AF_NS:
     858:             {
     859:             register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
     860:
     861:             if (ns_nullhost(*ina))
     862:                 ina->x_host = *(union ns_host *)(xs->xs_addr);
     863:             else
     864:                 ex_setaddr(ina->x_host.c_host,ifp->if_unit);
     865:             break;
     866:             }
     867: #endif
     868:         }
     869:         break;
     870:
     871:     case SIOCSIFFLAGS:
     872:         if ((ifp->if_flags & IFF_UP) == 0 &&
     873:             xs->xs_flags & EX_RUNNING) {
     874:             ((struct exdevice *)
     875:               (exinfo[ifp->if_unit]->ui_addr))->xd_porta = EX_RESET;
     876:             xs->xs_flags &= ~EX_RUNNING;
     877:         } else if (ifp->if_flags & IFF_UP &&
     878:             (xs->xs_flags & EX_RUNNING) == 0)
     879:             exinit(ifp->if_unit);
     880:         break;
     881:
     882:     default:
     883:         error = EINVAL;
     884:     }
     885:     splx(s);
     886:     return (error);
     887: }
     888:
     889: /*
     890:  * set ethernet address for unit
     891:  */
     892: ex_setaddr(physaddr, unit)
     893:     u_char *physaddr;
     894:     int unit;
     895: {
     896:     register struct ex_softc *xs = &ex_softc[unit];
     897:     struct uba_device *ui = exinfo[unit];
     898:     register struct exdevice *addr= (struct exdevice *)ui->ui_addr;
     899:     register struct ex_msg *bp;
     900:
     901:     if (physaddr) {
     902:         xs->xs_flags |= EX_SETADDR;
     903:         bcopy((caddr_t)physaddr, (caddr_t)xs->xs_addr, 6);
     904:     }
     905:     if (! (xs->xs_flags & EX_RUNNING))
     906:         return;
     907:     bp = exgetcbuf(xs);
     908:     bp->mb_rqst = LLNET_ADDRS;
     909:     bp->mb_na.na_mask = READ_OBJ|WRITE_OBJ;
     910:     bp->mb_na.na_slot = PHYSSLOT;
     911:     bcopy((caddr_t)xs->xs_addr, (caddr_t)bp->mb_na.na_addrs, 6);
     912:     bp->mb_status |= MH_EXOS;
     913:     addr->xd_portb = EX_NTRUPT;
     914:     bp = xs->xs_x2hnext;
     915:     while ((bp->mb_status & MH_OWNER) == MH_EXOS)   /* poll for reply */
     916:         ;
     917: #ifdef  DEBUG
     918:     log(LOG_ERR, "ex%d: reset addr %s\n", ui->ui_unit,
     919:         ether_sprintf(bp->mb_na.na_addrs));
     920: #endif
     921:     /*
     922: 	 * Now, re-enable reception on phys slot.
     923: 	 */
     924:     bp = exgetcbuf(xs);
     925:     bp->mb_rqst = LLNET_RECV;
     926:     bp->mb_nr.nr_mask = ENABLE_RCV|READ_OBJ|WRITE_OBJ;
     927:     bp->mb_nr.nr_slot = PHYSSLOT;
     928:     bp->mb_status |= MH_EXOS;
     929:     addr->xd_portb = EX_NTRUPT;
     930:     bp = xs->xs_x2hnext;
     931:     while ((bp->mb_status & MH_OWNER) == MH_EXOS)   /* poll for reply */
     932:         ;
     933: }
     934: #endif

#### Defined functions

ex_setaddr defined in line 892; used 2 times

- in line 299, 864

exattach defined in line 175; used 2 times

- in line 63-67(2)

excdint defined in line 465; used 2 times

- in line 63, 163

exconfig defined in line 310; used 2 times

- in line 192, 273

exgetcbuf defined in line 525; used 8 times

- in line 69, 195, 277, 451, 652, 815, 907, 924

exhangrcv defined in line 648; used 2 times

- in line 295, 477

exinit defined in line 246; used 5 times

- in line 68, 211, 237, 846, 879

exioctl defined in line 833; used 2 times

- in line 68, 213

exoutput defined in line 670; used 2 times

- in line 68, 212

exprobe defined in line 135; used 2 times

- in line 63-67(2)

exrecv defined in line 550; used 1 times

- in line 476

exreset defined in line 226; used 2 times

- in line 68, 214

exstart defined in line 428; used 3 times

- in line 300, 501, 784

exwatch defined in line 805; used 2 times

- in line 68, 292

#### Defined variables

ex_cvecs defined in line 131; used 4 times

- in line 147-148(2), 361, 367

ex_ncall defined in line 133; used 3 times

- in line 147-148(2), 165

ex_softc defined in line 122; used 17 times

- in line 111-113(4), 178, 235-236(2), 249, 315, 432, 468, 554, 651, 678, 810, 839, 896

exdriver defined in line 66; never used
exinfo defined in line 64; used 9 times

- in line 67, 231, 250, 431, 470, 653, 808, 875, 897

exstd defined in line 65; used 1 times

- in line 67

#### Defined struct's

ex_cvecs defined in line 128; never used
ex_softc defined in line 83; used 24 times

- in line 178(2), 249(2), 315(2), 432(2), 468(2), 527(2), 554(2), 651(2), 678(2), 810(2), 839(2), 896(2)

#### Defined macros

CM_OFFSET defined in line 118; used 1 times

- in line 409

DEBUG defined in line 57; used 8 times

- in line 87, 362, 438, 480, 510, 531, 786, 917

EXWATCHINTVL defined in line 61; used 2 times

- in line 293, 827

EX_RUNNING defined in line 94; used 7 times

- in line 236, 259, 297, 873-878(3), 905

EX_SETADDR defined in line 95; used 2 times

- in line 298, 902

EX_STATPENDING defined in line 93; used 3 times

- in line 505, 814-816(2)

EX_XPENDING defined in line 92; used 5 times

- in line 439, 457, 481-484(2), 783

H2XENT_OFFSET defined in line 116; used 1 times

- in line 381

H2XHDR_OFFSET defined in line 114; used 1 times

- in line 356

INCORE_BASE defined in line 109; used 6 times

- in line 111-113(2), 190, 270, 373, 388

INCORE_SIZE defined in line 120; used 2 times

- in line 191, 271

LVAL_OFF defined in line 112; used 2 times

- in line 116-117(2)

NH2X defined in line 59; used 4 times

- in line 104, 372, 380-383(2)

NX2H defined in line 60; used 4 times

- in line 105, 387, 395-398(2)

P_UNIADDR defined in line 100; used 3 times

- in line 355, 409, 822

RVAL_OFF defined in line 110; used 5 times

- in line 114-120(5)

SA_OFFSET defined in line 119; used 1 times

- in line 822

UNIADDR defined in line 99; used 2 times

- in line 456, 659

X2HENT_OFFSET defined in line 117; used 1 times

- in line 396

X2HHDR_OFFSET defined in line 115; used 1 times

- in line 359

exdataaddr defined in line 577; used 2 times

- in line 583-584(2)

xs_addr defined in line 86; used 6 times

- in line 208-209(2), 765, 862, 903, 911

xs_if defined in line 85; used 15 times

- in line 179, 235, 252, 267, 296, 442, 485-493(4), 504, 561-564(2), 599, 827

Last modified: 1987-06-03 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 331 |