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

##### Functions

    vvattach          X
    vvidentify        X
    vvinit            X
    vvioctl           X
    vvoutput          X
    vvprobe           X
    vvprt_hdr         X
    vvreset           X
    vvrint            X
    vvstart           X
    vvwatchdog        X
    vvxint            X

##### Variables

    vv_softc          X
    vv_tracehdr       X
    vvdriver          X
    vvinfo            X
    vvstd             X

##### Macros

    LOOPBACK          X
    NOHOST            X
    VVBUFSIZE         X
    VVMRU             X
    VVMTU             X
    VVUNIT            X
    vvdataaddr        X
    vvprintf          X
    vvtracehdr        X

##### struct's

    vv_softc          X

       1: /*
       2:  * Copyright (c) 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_vv.c	2.1 (2.11BSD) 1996/11/27
       7:  */
       8:
       9: #include "vv.h"
      10: #if NVV > 0
      11:
      12: /*
      13:  * Proteon proNET-10 and proNET-80 token ring driver.
      14:  * The name of this device driver derives from the old MIT
      15:  * name of V2LNI for the proNET hardware, would would abbreviate
      16:  * to "v2", but this won't work right. Thus the name is "vv".
      17:  *
      18:  * This driver is compatible with the proNET 10 meagbit and
      19:  * 80 megabit token ring interfaces (models p1000 and p1080).
      20:  * A unit may be marked as 80 megabit using "flags 1" in the
      21:  * config file.
      22:  *
      23:  * TRAILERS: This driver has a new implementation of trailers that
      24:  * is at least a tolerable neighbor on the ring. The offset is not
      25:  * stored in the protocol type, but instead only in the vh_info
      26:  * field. Also, the vh_info field, and the two shorts before the
      27:  * trailing header, are in network byte order, not VAX byte order.
      28:  *
      29:  * Of course, nothing but BSD UNIX supports trailers on ProNET.
      30:  * If you need interoperability with anything else, turn off
      31:  * trailers using the -trailers option to ifconfig!
      32:  *
      33:  * HARDWARE COMPATABILITY: This driver prefers that the HSBU (p1001)
      34:  * have a serial number >= 040, which is about March, 1982. Older
      35:  * HSBUs do not carry across 64kbyte boundaries. They can be supported
      36:  * by adding "| UBA_NEED16" to the vs_ifuba.ifu_flags initialization
      37:  * in vvattach().
      38:  *
      39:  * The old warning about use without Wire Centers applies only to CTL
      40:  * (p1002) cards with serial <= 057, which have not received ECO 176-743,
      41:  * which was implemented in March, 1982. Most such CTLs have received
      42:  * this ECO.
      43:  */
      44:
      45: #include "param.h"
      46: #include "../machine/seg.h"
      47: #include "systm.h"
      48: #include "mbuf.h"
      49: #include "buf.h"
      50: #include "domain.h"
      51: #include "protosw.h"
      52: #include "socket.h"
      53: #include "ioctl.h"
      54: #include "pdpif/if_vv.h"
      55: #include "pdpif/if_uba.h"
      56: #include "errno.h"
      57: #include "pdpuba/ubavar.h"
      58: #include "net/if.h"
      59: #include "net/netisr.h"
      60: #include "net/route.h"
      61:
      62: #ifdef  INET
      63: #include "netinet/in.h"
      64: #include "netinet/in_systm.h"
      65: #include "netinet/in_var.h"
      66: #include "netinet/ip.h"
      67: #include "netinet/ip_var.h"
      68: #endif
      69:
      70: /*
      71:  *    maximum transmission unit definition --
      72:  *        you can set VVMTU at anything from 576 to 2024.
      73:  *        1536 is a popular "large" value, because it is a multiple
      74:  *	  of 512, which the trailer scheme likes.
      75:  *        The absolute maximum size is 2024, which is enforced.
      76:  */
      77:
      78: #define VVMTU (1536)
      79:
      80: #define VVMRU (VVMTU + 16)
      81: #define VVBUFSIZE (VVMRU + sizeof(struct vv_header))
      82: #if VVMTU>2024
      83: #undef VVMTU
      84: #undef VVMRU
      85: #undef VVBUFSIZE
      86: #define VVBUFSIZE (2046)
      87: #define VVMRU (VVBUFSIZE - sizeof (struct vv_header))
      88: #define VVMTU (VVMRU - 16)
      89: #endif
      90:
      91: /*
      92:  *   debugging and tracing stuff
      93:  */
      94: int vv_tracehdr = 0;    /* 1 => trace headers (slowly!!) */
      95:
      96: #define vvtracehdr  if (vv_tracehdr) vvprt_hdr
      97: #define vvprintf    if (vs->vs_if.if_flags & IFF_DEBUG) printf
      98:
      99: /*
     100:  * externals, types, etc.
     101:  */
     102: int vvprobe(), vvattach(), vvreset(), vvinit();
     103: int vvidentify(), vvstart(), vvxint(), vvwatchdog();
     104: int vvrint(), vvoutput(), vvioctl();
     105: struct  uba_device *vvinfo[NVV];
     106: u_short vvstd[] = { 0 };
     107: struct  uba_driver vvdriver =
     108:     { vvprobe, 0, vvattach, 0, vvstd, "vv", vvinfo };
     109: #define VVUNIT(x)   minor(x)
     110:
     111: #define LOOPBACK        /* use loopback for packets meant for us */
     112: #ifdef  LOOPBACK
     113: extern struct ifnet loif;
     114: #endif
     115:
     116: /*
     117:  * Software status of each interface.
     118:  *
     119:  * Each interface is referenced by a network interface structure,
     120:  * vs_if, which the routing code uses to locate the interface.
     121:  * This structure contains the output queue for the interface, its address, ...
     122:  * We also have, for each interface, a UBA interface structure, which
     123:  * contains information about the UNIBUS resources held by the interface:
     124:  * map registers, buffered data paths, etc.  Information is cached in this
     125:  * structure for use by the if_uba.c routines in running the interface
     126:  * efficiently.
     127:  */
     128: struct  vv_softc {
     129:     struct  ifnet vs_if;        /* network-visible interface */
     130:     struct  ifuba vs_ifuba;     /* UNIBUS resources */
     131:     u_short vs_host;        /* this interface address */
     132:     short   vs_oactive;     /* is output active */
     133:     short   vs_is80;        /* is 80 megabit version */
     134:     short   vs_olen;        /* length of last output */
     135:     u_short vs_lastx;       /* address of last packet sent */
     136:     u_short vs_lastr;       /* address of last packet received */
     137:     short   vs_tries;       /* transmit current retry count */
     138:     short   vs_init;        /* number of ring inits */
     139:     short   vs_refused;     /* number of packets refused */
     140:     short   vs_timeouts;        /* number of transmit timeouts */
     141:     short   vs_otimeout;        /* number of output timeouts */
     142:     short   vs_ibadf;       /* number of input bad formats */
     143:     short   vs_parity;      /* number of parity errors on 10 meg, */
     144:                     /* link data errors on 80 meg */
     145: } vv_softc[NVV];
     146:
     147: #define NOHOST  0xffff          /* illegal host number */
     148:
     149: vvprobe(reg)
     150:     caddr_t reg;
     151: {
     152: #ifdef  notdef
     153:     register int br, cvec;
     154:     register struct vvreg *addr;
     155:
     156: #ifdef lint
     157:     br = 0; cvec = br; br = cvec;
     158: #endif
     159:     addr = (struct vvreg *)reg;
     160:     /* reset interface, enable, and wait till dust settles */
     161:     addr->vvicsr = VV_RST;
     162:     addr->vvocsr = VV_RST;
     163:     DELAY(100000L);
     164:
     165:     /* generate interrupt by doing 1 word DMA from 0 in uba space!! */
     166:     addr->vvoba = 0;        /* low 16 bits */
     167:     addr->vvoea = 0;        /* extended bits */
     168:     addr->vvowc = -1;       /* for 1 word */
     169:     addr->vvocsr = VV_IEN | VV_DEN; /* start the DMA, with interrupt */
     170:     DELAY(100000L);
     171:     addr->vvocsr = VV_RST;      /* clear out the CSR */
     172:     if (cvec && cvec != 0x200)
     173:         cvec -= 4;      /* backup so vector => receive */
     174: #endif
     175:     return(1);
     176: }
     177:
     178: /*
     179:  * Interface exists: make available by filling in network interface
     180:  * record.  System will initialize the interface when it is ready
     181:  * to accept packets.
     182:  */
     183: vvattach(ui)
     184:     struct uba_device *ui;
     185: {
     186:     register struct vv_softc *vs;
     187:
     188:     vs = &vv_softc[ui->ui_unit];
     189:     vs->vs_if.if_unit = ui->ui_unit;
     190:     vs->vs_if.if_name = "vv";
     191:     vs->vs_if.if_mtu = VVMTU;
     192:     vs->vs_if.if_flags = IFF_BROADCAST;
     193:     vs->vs_if.if_init = vvinit;
     194:     vs->vs_if.if_ioctl = vvioctl;
     195:     vs->vs_if.if_output = vvoutput;
     196:     vs->vs_if.if_reset = vvreset;
     197:     vs->vs_if.if_timer = 0;
     198:     vs->vs_if.if_watchdog = vvwatchdog;
     199:     vs->vs_ifuba.ifu_flags = UBA_CANTWAIT | UBA_NEEDBDP;
     200:
     201:     /* use flag to determine if this is proNET-80 */
     202:     vs->vs_is80 = (short)(ui->ui_flags & 01);
     203:
     204: #if defined(VAX750)
     205:     /* don't chew up 750 bdp's */
     206:     if (cpu == VAX_750 && ui->ui_unit > 0)
     207:         vs->vs_ifuba.ifu_flags &= ~UBA_NEEDBDP;
     208: #endif
     209:     if_attach(&vs->vs_if);
     210: }
     211:
     212: /*
     213:  * Reset of interface after UNIBUS reset.
     214:  * If interface is on specified uba, reset its state.
     215:  */
     216: vvreset(unit, uban)
     217:     int unit, uban;
     218: {
     219:     register struct uba_device *ui;
     220:
     221:     if (unit >= NVV || (ui = vvinfo[unit]) == 0 || ui->ui_alive == 0 ||
     222:         ui->ui_ubanum != uban)
     223:         return;
     224:     printf(" vv%d", unit);
     225:     vvinit(unit);
     226: }
     227:
     228: /*
     229:  * Initialization of interface; clear recorded pending
     230:  * operations, and reinitialize UNIBUS usage.
     231:  */
     232: vvinit(unit)
     233:     int unit;
     234: {
     235:     register struct vv_softc *vs;
     236:     register struct uba_device *ui;
     237:     register struct vvreg *addr;
     238:     register int s;
     239:     ubadr_t ubainfo;
     240:
     241:     vs = &vv_softc[unit];
     242:     ui = vvinfo[unit];
     243:
     244:     if (vs->vs_if.if_addrlist == (struct ifaddr *)0)
     245:         return;
     246:
     247:     addr = (struct vvreg *)ui->ui_addr;
     248:     if (if_ubainit(&vs->vs_ifuba, ui->ui_ubanum,
     249:         sizeof (struct vv_header), (int)btoc(VVMTU)) == 0) {
     250:         printf("vv%d: can't initialize, if_ubainit() failed\n", unit);
     251:         vs->vs_if.if_flags &= ~IFF_UP;
     252:         return;
     253:     }
     254:
     255:     /*
     256: 	 * Now that the uba is set up, figure out our address and
     257: 	 * update complete our host address.
     258: 	 */
     259:     if ((vs->vs_host = vvidentify(unit)) == NOHOST) {
     260:         vs->vs_if.if_flags &= ~IFF_UP;
     261:         return;
     262:     }
     263:     printf("vv%d: host %u\n", unit, vs->vs_host);
     264:
     265:     /*
     266: 	 * Reset the interface, and stay in the ring
     267: 	 */
     268:     addr->vvocsr = VV_RST;          /* take over output */
     269:     addr->vvocsr = VV_CPB;          /* clear packet buffer */
     270:     addr->vvicsr = VV_RST | VV_HEN;     /* take over input, */
     271:                         /* keep relay closed */
     272:     DELAY(500000L);             /* let contacts settle */
     273:
     274:     vs->vs_init = 0;            /* clear counters, etc. */
     275:     vs->vs_refused = 0;
     276:     vs->vs_timeouts = 0;
     277:     vs->vs_otimeout = 0;
     278:     vs->vs_ibadf = 0;
     279:     vs->vs_parity = 0;
     280:     vs->vs_lastx = 256;         /* an invalid address */
     281:     vs->vs_lastr = 256;         /* an invalid address */
     282:
     283:     /*
     284: 	 * Hang a receive and start any
     285: 	 * pending writes by faking a transmit complete.
     286: 	 */
     287:     s = splimp();
     288:     ubainfo = vs->vs_ifuba.ifu_r.ifrw_info;
     289:     addr->vviba = (u_short)ubainfo;
     290:     addr->vviea = (u_short)(ubainfo >> 16);
     291:     addr->vviwc = -(VVBUFSIZE) >> 1;
     292:     addr->vvicsr = VV_IEN | VV_HEN | VV_DEN | VV_ENB;
     293:     vs->vs_oactive = 1;
     294:     vs->vs_if.if_flags |= IFF_RUNNING;
     295:     vvxint(unit);
     296:     splx(s);
     297: }
     298:
     299: /*
     300:  * Return our host address.
     301:  */
     302:
     303: vvidentify(unit)
     304:     int unit;
     305: {
     306:     register struct vv_softc *vs;
     307:     register struct uba_device *ui;
     308:     register struct vvreg *addr;
     309:     register struct mbuf *m;
     310:     register struct vv_header *v;
     311:     register int attempts, waitcount;
     312:     ubadr_t ubainfo;
     313:     segm    seg5;
     314:     u_short host;
     315:     u_char  type;
     316:
     317:     /*
     318: 	 * Build a multicast message to identify our address
     319: 	 */
     320:     vs = &vv_softc[unit];
     321:     ui = vvinfo[unit];
     322:     addr = (struct vvreg *)ui->ui_addr;
     323:     attempts = 0;       /* total attempts, including bad msg type */
     324:     m = m_get(M_DONTWAIT, MT_HEADER);
     325:     if (m == NULL) {
     326:         printf("vv%d: can't initialize, m_get() failed\n", unit);
     327:         return (NOHOST);
     328:     }
     329:     m->m_next = 0;
     330:     m->m_off = MMINOFF;
     331:     m->m_len = sizeof(struct vv_header);
     332:     v = mtod(m, struct vv_header *);
     333:     v->vh_dhost = VV_BROADCAST; /* multicast destination address */
     334:     v->vh_shost = 0;        /* will be overwritten with ours */
     335:     v->vh_version = RING_VERSION;
     336:     v->vh_type = RING_WHOAMI;
     337:     v->vh_info = 0;
     338:     /* map xmit message into uba */
     339:     vs->vs_olen =  if_wubaput(&vs->vs_ifuba, m);
     340:     /*
     341: 	 * Reset interface, establish Digital Loopback Mode, and
     342: 	 * send the multicast (to myself) with Input Copy enabled.
     343: 	 */
     344: retry:
     345:     ubainfo = vs->vs_ifuba.ifu_r.ifrw_info;
     346:     addr->vvicsr = VV_RST;
     347:     addr->vviba = (u_short) ubainfo;
     348:     addr->vviea = (u_short) (ubainfo >> 16);
     349:     addr->vviwc = -(sizeof (struct vv_header) + VVMTU) >> 1;
     350:     addr->vvicsr = VV_STE | VV_DEN | VV_ENB | VV_LPB;
     351:
     352:     /* let flag timers fire so ring will initialize */
     353:     DELAY(2000000L);        /* about 2 SECONDS on a 780!! */
     354:
     355:     addr->vvocsr = VV_RST | VV_CPB; /* clear packet buffer */
     356:     ubainfo = vs->vs_ifuba.ifu_w.ifrw_info;
     357:     addr->vvoba = (u_short) ubainfo;
     358:     addr->vvoea = (u_short) (ubainfo >> 16);
     359:     addr->vvowc = -((vs->vs_olen + 1) >> 1);
     360:     addr->vvocsr = VV_CPB | VV_DEN | VV_INR | VV_ENB;
     361:     /*
     362: 	 * Wait for receive side to finish.
     363: 	 * Extract source address (which will be our own),
     364: 	 * and post to interface structure.
     365: 	 */
     366:     DELAY(10000L);
     367:     for (waitcount = 0; (addr->vvicsr & VV_RDY) == 0; waitcount++) {
     368:         if (waitcount < 10) {
     369:             DELAY(1000L);
     370:             continue;
     371:         }
     372:         if (attempts++ < VVIDENTRETRY)
     373:             goto retry;
     374:         break;
     375:     }
     376:     /* deallocate mbuf used for send packet */
     377:     if (vs->vs_ifuba.ifu_xtofree) {
     378:         m_freem(vs->vs_ifuba.ifu_xtofree);
     379:         vs->vs_ifuba.ifu_xtofree = 0;
     380:     }
     381:     if (attempts >= VVIDENTRETRY) {
     382:         printf("vv%d: can't initialize after %d tries, icsr = %b\n",
     383:             unit, VVIDENTRETRY, 0xffff&(addr->vvicsr), VV_IBITS);
     384:         return (NOHOST);
     385:     }
     386:     m = if_rubaget(&vs->vs_ifuba, sizeof(struct vv_header), 0, &vs->vs_if);
     387:     if (m != NULL)
     388:         m_freem(m);
     389:     /*
     390: 	 * Check message type before we believe the source host address
     391: 	 */
     392:     saveseg5(seg5);
     393:     mapseg5(vs->vs_ifuba.ifu_r.ifrw_click, 077406);
     394:     v = (struct vv_header *) SEG5;
     395:     type = v->vh_type;
     396:     host = (u_short)v->vh_shost;
     397:     restorseg5(seg5);
     398:     if (type != (u_char)RING_WHOAMI)
     399:         goto retry;
     400:     return(host);
     401: }
     402:
     403: /*
     404:  * Start or restart output on interface.
     405:  * If interface is active, this is a retransmit, so just
     406:  * restuff registers and go.
     407:  * If interface is not already active, get another datagram
     408:  * to send off of the interface queue, and map it to the interface
     409:  * before starting the output.
     410:  */
     411: vvstart(dev)
     412:     dev_t dev;
     413: {
     414:     register struct uba_device *ui;
     415:     register struct vv_softc *vs;
     416:     register struct vvreg *addr;
     417:     register struct mbuf *m;
     418:     register int unit, dest, s;
     419:     ubadr_t ubainfo;
     420:     segm save5;
     421:
     422:     unit = VVUNIT(dev);
     423:     ui = vvinfo[unit];
     424:     vs = &vv_softc[unit];
     425:     if (vs->vs_oactive)
     426:         goto restart;
     427:     /*
     428: 	 * Not already active: dequeue another request
     429: 	 * and map it to the UNIBUS.  If no more requests,
     430: 	 * just return.
     431: 	 */
     432:     s = splimp();
     433:     IF_DEQUEUE(&vs->vs_if.if_snd, m);
     434:     splx(s);
     435:     if (m == NULL) {
     436:         vs->vs_oactive = 0;
     437:         return;
     438:     }
     439:     dest = mtod(m, struct vv_header *)->vh_dhost;
     440:     vs->vs_olen = if_wubaput(&vs->vs_ifuba, m);
     441:     vs->vs_lastx = dest;
     442: restart:
     443:     /*
     444: 	 * Have request mapped to UNIBUS for transmission.
     445: 	 * Purge any stale data from this BDP, and start the output.
     446: 	 *
     447: 	 * Make sure this packet will fit in the interface.
     448: 	 */
     449:     if (vs->vs_olen > VVBUFSIZE) {
     450:         printf("vv%d vs_olen: %d > VVBUFSIZE\n", unit, vs->vs_olen);
     451:         panic("vvdriver vs_olen botch");
     452:     }
     453:
     454:     vs->vs_if.if_timer = VVTIMEOUT;
     455:     vs->vs_oactive = 1;
     456:
     457:     /* ship it */
     458:     addr = (struct vvreg *)ui->ui_addr;
     459:     ubainfo = vs->vs_ifuba.ifu_w.ifrw_info;
     460:     addr->vvoba = (u_short) ubainfo;
     461:     addr->vvoea = (u_short) (ubainfo >> 16);
     462:     addr->vvowc = -((vs->vs_olen + 1) >> 1);
     463:     addr->vvowc = -((vs->vs_olen + 1) >> 1); /* extra byte is garbage */
     464:     if (addr->vvocsr & VV_NOK)
     465:         vs->vs_init++;          /* count ring inits */
     466:     addr->vvocsr = VV_IEN | VV_CPB | VV_DEN | VV_INR | VV_ENB;
     467: }
     468:
     469: /*
     470:  * proNET transmit interrupt
     471:  * Start another output if more data to send.
     472:  */
     473: vvxint(unit)
     474:     int unit;
     475: {
     476:     register struct uba_device *ui;
     477:     register struct vv_softc *vs;
     478:     register struct vvreg *addr;
     479:     register int oc;
     480:
     481:     ui = vvinfo[unit];
     482:     vs = &vv_softc[unit];
     483:     vs->vs_if.if_timer = 0;
     484:     addr = (struct vvreg *)ui->ui_addr;
     485:     oc = 0xffff & (addr->vvocsr);
     486:     if (vs->vs_oactive == 0) {
     487:         vvprintf("vv%d: stray interrupt vvocsr = %b\n", unit,
     488:             oc, VV_OBITS);
     489:         return;
     490:     }
     491:
     492:     /*
     493: 	 * we retransmit on soft error
     494: 	 * TODO: sort retransmits to end of queue if possible!
     495: 	 */
     496:     if (oc & (VV_OPT | VV_RFS)) {
     497:         if (vs->vs_tries++ < VVRETRY) {
     498:             if (oc & VV_OPT)
     499:                 vs->vs_otimeout++;
     500:             if (oc & VV_RFS) {
     501:                 vs->vs_if.if_collisions++;
     502:                 vs->vs_refused++;
     503:             }
     504:             vvstart(unit);      /* restart this message */
     505:             return;
     506:         }
     507:     }
     508:     vs->vs_if.if_opackets++;
     509:     vs->vs_oactive = 0;
     510:     vs->vs_tries = 0;
     511:
     512:     if (oc & VVXERR) {
     513:         vs->vs_if.if_oerrors++;
     514:         vvprintf("vv%d: error vvocsr = %b\n", unit, 0xffff & oc,
     515:             VV_OBITS);
     516:     }
     517:     if (vs->vs_ifuba.ifu_xtofree) {
     518:         m_freem(vs->vs_ifuba.ifu_xtofree);
     519:         vs->vs_ifuba.ifu_xtofree = 0;
     520:     }
     521:     vvstart(unit);
     522: }
     523:
     524: /*
     525:  * Transmit watchdog timer routine.
     526:  * This routine gets called when we lose a transmit interrupt.
     527:  * The best we can do is try to restart output.
     528:  */
     529: vvwatchdog(unit)
     530:     int unit;
     531: {
     532:     register struct vv_softc *vs;
     533:     register int s;
     534:
     535:     vs = &vv_softc[unit];
     536:     vvprintf("vv%d: lost a transmit interrupt.\n", unit);
     537:     vs->vs_timeouts++;
     538:     s = splimp();
     539:     vvstart(unit);
     540:     splx(s);
     541: }
     542:
     543: /*
     544:  * proNET interface receiver interrupt.
     545:  * If input error just drop packet.
     546:  * Otherwise purge input buffered data path and examine
     547:  * packet to determine type.  If can't determine length
     548:  * from type, then have to drop packet.  Otherwise decapsulate
     549:  * packet based on type and pass to type specific higher-level
     550:  * input routine.
     551:  */
     552: vvrint(unit)
     553:     int unit;
     554: {
     555:     register struct vv_softc *vs;
     556:     register struct vvreg *addr;
     557:     register struct vv_header *vv;
     558:     register struct ifqueue *inq;
     559:     register struct mbuf *m;
     560:     int len, off, s;
     561:     ubadr_t ubainfo;
     562:     segm save5;
     563:     short resid;
     564:     u_short type, shost;
     565:
     566:     saveseg5(save5);
     567:     vs = &vv_softc[unit];
     568:     vs->vs_if.if_ipackets++;
     569:     addr = (struct vvreg *)vvinfo[unit]->ui_addr;
     570:     if (addr->vvicsr & VVRERR) {
     571:         vvprintf("vv%d: receive error, vvicsr = %b\n", unit,
     572:             0xffff&(addr->vvicsr), VV_IBITS);
     573:         if (addr->vvicsr & VV_BDF)
     574:             vs->vs_ibadf++;
     575:         goto dropit;
     576:     }
     577:
     578:     /*
     579: 	 * parity errors?
     580: 	 */
     581:     if (addr->vvicsr & VV_LDE) {
     582:         /* we don't have to clear it because the receive command */
     583:         /* writes 0 to parity bit */
     584:         vs->vs_parity++;
     585:
     586:         /*
     587: 		 * only on 10 megabit proNET is VV_LDE an end-to-end parity
     588: 		 * bit. On 80 megabit, it returns to the intended use of
     589: 		 * node-to-node parity. End-to-end parity errors on 80 megabit
     590: 		 * give VV_BDF.
     591: 		 */
     592:         if (vs->vs_is80 == 0)
     593:             goto dropit;
     594:     }
     595:
     596:     /*
     597: 	 * Get packet length from residual word count
     598: 	 *
     599: 	 * Compute header offset if trailer protocol
     600: 	 *
     601: 	 * Pull packet off interface.  Off is nonzero if packet
     602: 	 * has trailing header; if_rubaget will then force this header
     603: 	 * information to be at the front.  The vh_info field
     604: 	 * carries the offset to the trailer data in trailer
     605: 	 * format packets.
     606: 	 */
     607:     mapseg5(vs->vs_ifuba.ifu_r.ifrw_click, (btoc(VVMRU) << 8) | RW);
     608:     vv = (struct vv_header *) SEG5;
     609:     vvtracehdr("vi", vv);
     610:     resid = addr->vviwc & 01777;        /* only low 10 bits valid */
     611:     if (resid)
     612:         resid |= 0176000;       /* high 6 bits are undefined */
     613:     len = ((VVBUFSIZE >> 1) + resid) << 1;
     614:     len -= sizeof(struct vv_header);
     615:
     616:     if ((addr->vvicsr & VV_DPR) || len > VVMRU || len <= 0) {
     617:         vvprintf("vv%d: len too long or short, \
     618: len = %d, vvicsr = %b\n",
     619:             unit, len, 0xffff&(addr->vvicsr), VV_IBITS);
     620:         goto dropit;
     621:     }
     622:
     623:     /* check the protocol header version */
     624:     if (vv->vh_version != RING_VERSION) {
     625:         vvprintf("vv%d: bad protocol header version %d\n",
     626:             unit, vv->vh_version & 0xff);
     627:         goto dropit;
     628:     }
     629:
     630: #define vvdataaddr(vv, off, type)   ((type)(((caddr_t)((vv)+1)+(off))))
     631:     if (vv->vh_type == RING_TRAILER ) {
     632:         off = ntohs((u_short)vv->vh_info);
     633:         if (off > VVMTU) {
     634:             vvprintf("vv%d: off > VVMTU, off = %d, vvicsr = %b\n",
     635:                     unit, off, 0xffff&(addr->vvicsr), VV_IBITS);
     636:             goto dropit;
     637:         }
     638:         vv->vh_type = ntohs(*vvdataaddr(vv, off, u_short *));
     639:         resid = ntohs(*(vvdataaddr(vv, off+sizeof(u_short), u_short *)));
     640:         if (off + resid > len) {
     641:             vvprintf("vv%d: trailer packet too short\n", unit);
     642:             vvprintf("vv%d: off = %d, resid = %d, vvicsr = %b\n",
     643:                     unit, off, resid,
     644:                     0xffff&(addr->vvicsr), VV_IBITS);
     645:             goto dropit;
     646:         }
     647:         len = off + resid;
     648:     } else
     649:         off = 0;
     650:
     651:     if (len == 0) {
     652:         vvprintf("vv%d: len is zero, vvicsr = %b\n", unit,
     653:                 0xffff&(addr->vvicsr), VV_IBITS);
     654:         goto dropit;
     655:     }
     656: /*
     657:  * have to restore the mapping before manipulating mbufs because
     658:  * there may be mbufs in SEG5.  save the 'type' and 'shost' then
     659:  * restore the mapping.
     660: */
     661:     type = vv->vh_type;
     662:     shost = vv->vh_shost;
     663:     restorseg5(save5);
     664:     m = if_rubaget(&vs->vs_ifuba, len, off, &vs->vs_if);
     665:     if (m == NULL) {
     666:         vvprintf("vv%d: if_rubaget() failed, vvicsr = %b\n", unit,
     667:                 0xffff&(addr->vvicsr), VV_IBITS);
     668:         goto dropit;
     669:     }
     670:     if (off) {
     671:         struct ifnet *ifp;
     672:
     673:         ifp = *(mtod(m, struct ifnet **));
     674:         m->m_off += 2 * sizeof (u_short);
     675:         m->m_len -= 2 * sizeof (u_short);
     676:         *(mtod(m, struct ifnet **)) = ifp;
     677:     }
     678:
     679:     /* Keep track of source address of this packet */
     680:     vs->vs_lastr = shost;
     681:
     682:     /*
     683: 	 * Demultiplex on packet type
     684: 	 */
     685:     switch (type) {
     686:
     687: #ifdef INET
     688:     case RING_IP:
     689:         schednetisr(NETISR_IP);
     690:         inq = &ipintrq;
     691:         break;
     692: #endif
     693:     default:
     694:         vvprintf("vv%d: unknown pkt type 0x%x\n", unit, type);
     695:         m_freem(m);
     696:         goto setup;
     697:     }
     698:     s = splimp();
     699:     if (IF_QFULL(inq)) {
     700:         IF_DROP(inq);
     701:         m_freem(m);
     702:     } else
     703:         IF_ENQUEUE(inq, m);
     704:
     705:     splx(s);
     706:     /*
     707: 	 * Reset for the next packet.
     708: 	 */
     709: setup:
     710:     restorseg5(save5);
     711:     ubainfo = vs->vs_ifuba.ifu_r.ifrw_info;
     712:     addr->vviba = (u_short) ubainfo;
     713:     addr->vviea = (u_short) (ubainfo >> 16);
     714:     addr->vviwc = -(VVBUFSIZE) >> 1;
     715:     addr->vvicsr = VV_HEN | VV_IEN | VV_DEN | VV_ENB;
     716:     return;
     717:
     718:     /*
     719: 	 * Drop packet on floor -- count them!!
     720: 	 */
     721: dropit:
     722:     vs->vs_if.if_ierrors++;
     723:     goto setup;
     724: }
     725:
     726: /*
     727:  * proNET output routine.
     728:  * Encapsulate a packet of type family for the local net.
     729:  * Use trailer local net encapsulation if enough data in first
     730:  * packet leaves a multiple of 512 bytes of data in remainder.
     731:  */
     732: vvoutput(ifp, m0, dst)
     733:     struct ifnet *ifp;
     734:     struct mbuf *m0;
     735:     struct sockaddr *dst;
     736: {
     737:     register struct mbuf *m;
     738:     register struct vv_header *vv;
     739:     register int off;
     740:     register int unit;
     741:     register struct vvreg *addr;
     742:     register struct vv_softc *vs;
     743:     register int s;
     744:     int type, error;
     745:     u_long dest;
     746:     segm save5;
     747:
     748:     saveseg5(save5);
     749:     m = m0;
     750:     unit = ifp->if_unit;
     751:     addr = (struct vvreg *)vvinfo[unit]->ui_addr;
     752:     vs = &vv_softc[unit];
     753:
     754:     /*
     755: 	 * Check to see if the input side has wedged.
     756: 	 *
     757: 	 * We are lower than device ipl when we enter this routine,
     758: 	 * so if the interface is ready with an input packet then
     759: 	 * an input interrupt must have slipped through the cracks.
     760: 	 *
     761: 	 * Avoid the race with an input interrupt by watching to see
     762: 	 * if any packets come in.
     763: 	 */
     764:     s = vs->vs_if.if_ipackets;
     765:     if (addr->vvicsr & VV_RDY && s == vs->vs_if.if_ipackets) {
     766:         vvprintf("vv%d: lost a receive interrupt, icsr = %b\n",
     767:                 unit, 0xffff&(addr->vvicsr), VV_IBITS);
     768:         s = splimp();
     769:         vvrint(unit);
     770:         splx(s);
     771:     }
     772:
     773:     switch (dst->sa_family) {
     774:
     775: #ifdef INET
     776:     case AF_INET:
     777:         if (in_broadcast(((struct sockaddr_in *)dst)->sin_addr))
     778:             dest = VV_BROADCAST;
     779:         else
     780:             dest = in_lnaof(((struct sockaddr_in *)dst)->sin_addr);
     781: /* Rene Nieuwboer reneni@psy.vu.nl suggests a 'dest &= 0xff;' at this point */
     782: /*   dest is contrained in the 'if' a few lines down, i don't see why the & */
     783: #ifdef  LOOPBACK
     784:         if (dest == vs->vs_host && (loif.if_flags & IFF_UP))
     785:             return (looutput(&loif, m0, dst));
     786: #endif	LOOPBACK
     787:         if (dest >= 0x100) {
     788:             error = EPERM;
     789:             goto bad;
     790:         }
     791:         off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
     792:         /*
     793: 		 * Trailerize, if the configuration allows it.
     794: 		 * TODO: Need per host negotiation.
     795: 		 */
     796:         if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
     797:         if (off > 0 && (off & 0x1ff) == 0 &&
     798:             m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
     799:             type = RING_TRAILER;
     800:             m->m_off -= 2 * sizeof (u_short);
     801:             m->m_len += 2 * sizeof (u_short);
     802:             *mtod(m, u_short *) = htons((short)RING_IP);
     803:             *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
     804:             goto gottrailertype;
     805:         }
     806:         type = RING_IP;
     807:         off = 0;
     808:         goto gottype;
     809: #endif
     810:     default:
     811:         printf("vv%d: can't handle af%d\n", unit, dst->sa_family);
     812:         error = EAFNOSUPPORT;
     813:         goto bad;
     814:     }
     815:
     816: gottrailertype:
     817:     /*
     818: 	 * Packet to be sent as trailer: move first packet
     819: 	 * (control information) to end of chain.
     820: 	 */
     821:     while (m->m_next)
     822:         m = m->m_next;
     823:     m->m_next = m0;
     824:     m = m0->m_next;
     825:     m0->m_next = 0;
     826:     m0 = m;
     827: gottype:
     828:     /*
     829: 	 * Add local net header.  If no space in first mbuf,
     830: 	 * allocate another.
     831: 	 */
     832:     if (m->m_off > MMAXOFF ||
     833:         MMINOFF + sizeof (struct vv_header) > m->m_off) {
     834:         m = m_get(M_DONTWAIT, MT_HEADER);
     835:         if (m == NULL) {
     836:             error = ENOBUFS;
     837:             goto bad;
     838:         }
     839:         m->m_next = m0;
     840:         m->m_off = MMINOFF;
     841:         m->m_len = sizeof (struct vv_header);
     842:     } else {
     843:         m->m_off -= sizeof (struct vv_header);
     844:         m->m_len += sizeof (struct vv_header);
     845:     }
     846:     vv = mtod(m, struct vv_header *);
     847:     vv->vh_shost = vs->vs_host;
     848:     vv->vh_dhost = dest;
     849:     vv->vh_version = RING_VERSION;
     850:     vv->vh_type = type;
     851:     vv->vh_info = htons((u_short)off);
     852:     vvtracehdr("vo", vv);
     853:
     854:     /*
     855: 	 * Queue message on interface, and start output if interface
     856: 	 * not yet active.
     857: 	 */
     858:     s = splimp();
     859:     if (IF_QFULL(&ifp->if_snd)) {
     860:         IF_DROP(&ifp->if_snd);
     861:         error = ENOBUFS;
     862:         goto qfull;
     863:     }
     864:     IF_ENQUEUE(&ifp->if_snd, m);
     865:     if (vs->vs_oactive == 0)
     866:         vvstart(unit);
     867:     splx(s);
     868:     return (0);
     869: qfull:
     870:     m0 = m;
     871:     splx(s);
     872: bad:
     873:     m_freem(m0);
     874:     return(error);
     875: }
     876:
     877: /*
     878:  * Process an ioctl request.
     879:  */
     880: vvioctl(ifp, cmd, data)
     881:     register struct ifnet *ifp;
     882:     u_int cmd;
     883:     caddr_t data;
     884: {
     885:     struct ifaddr *ifa = (struct ifaddr *) data;
     886:     int s = splimp(), error = 0;
     887:
     888:     switch (cmd) {
     889:
     890:     case SIOCSIFADDR:
     891:         ifp->if_flags |= IFF_UP;
     892:         if ((ifp->if_flags & IFF_RUNNING) == 0)
     893:             vvinit(ifp->if_unit);
     894:         /*
     895: 		 * Did self-test succeed?
     896: 		 */
     897:         if ((ifp->if_flags & IFF_UP) == 0)
     898:             error = ENETDOWN;
     899:                 /*
     900:                  * Attempt to check agreement of protocol address
     901:                  * and board address.
     902:                  */
     903:         switch (ifa->ifa_addr.sa_family) {
     904:                 case AF_INET:
     905: /* Rene Nieuwboer reneni@psy.vu.nl suggests a '& 0xff;' below */
     906:             if ((u_short)(in_lnaof(IA_SIN(ifa)->sin_addr)) !=
     907:                 vv_softc[ifp->if_unit].vs_host)
     908:                 error = EADDRNOTAVAIL;
     909:             break;
     910:         }
     911:         break;
     912:
     913:     default:
     914:         error = EINVAL;
     915:     }
     916:     splx(s);
     917:     return (error);
     918: }
     919:
     920: /*
     921:  * vvprt_hdr(s, v) print the local net header in "v"
     922:  *	with title is "s"
     923:  */
     924: vvprt_hdr(s, v)
     925:     char *s;
     926:     register struct vv_header *v;
     927: {
     928:     printf("%s: dsvti: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
     929:         s,
     930:         0xff & (int)(v->vh_dhost), 0xff & (int)(v->vh_shost),
     931:         0xff & (int)(v->vh_version), 0xff & (int)(v->vh_type),
     932:         0xffff & (int)(v->vh_info));
     933: }
     934: #endif NVV

#### Defined functions

vvattach defined in line 183; used 2 times

- in line 102, 108

vvidentify defined in line 303; used 2 times

- in line 103, 259

vvinit defined in line 232; used 4 times

- in line 102, 193, 225, 893

vvioctl defined in line 880; used 2 times

- in line 104, 194

vvoutput defined in line 732; used 2 times

- in line 104, 195

vvprobe defined in line 149; used 2 times

- in line 102, 108

vvprt_hdr defined in line 924; used 1 times

- in line 96

vvreset defined in line 216; used 2 times

- in line 102, 196

vvrint defined in line 552; used 2 times

- in line 104, 769

vvstart defined in line 411; used 5 times

- in line 103, 504, 521, 539, 866

vvwatchdog defined in line 529; used 2 times

- in line 103, 198

vvxint defined in line 473; used 2 times

- in line 103, 295

#### Defined variables

vv_softc defined in line 145; used 9 times

- in line 188, 241, 320, 424, 482, 535, 567, 752, 907

vv_tracehdr defined in line 94; used 1 times

- in line 96

vvdriver defined in line 107; never used
vvinfo defined in line 105; used 8 times

- in line 108, 221, 242, 321, 423, 481, 569, 751

vvstd defined in line 106; used 1 times

- in line 108

#### Defined struct's

vv_softc defined in line 128; used 16 times

- in line 186(2), 235(2), 306(2), 415(2), 477(2), 532(2), 555(2), 742(2)

#### Defined macros

LOOPBACK defined in line 111; used 2 times

- in line 112, 783

NOHOST defined in line 147; used 3 times

- in line 259, 327, 384

VVBUFSIZE defined in line 86; used 6 times

- in line 85-87(2), 291, 449, 613, 714

VVMRU defined in line 87; used 5 times

- in line 81-88(3), 607, 616

VVMTU defined in line 88; used 7 times

- in line 80-83(3), 191, 249, 349, 633

VVUNIT defined in line 109; used 1 times

- in line 422

vvdataaddr defined in line 630; used 2 times

- in line 638-639(2)

vvprintf defined in line 97; used 13 times

- in line 487, 514, 536, 571, 617, 625, 634, 641-642(2), 652, 666, 694, 766

vvtracehdr defined in line 96; used 2 times

- in line 609, 852

Last modified: 1996-11-18 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2061 |