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

#### Defined functions

vvattach defined in line 190; used 2 times

- in line 106, 112

vvidentify defined in line 320; used 2 times

- in line 107, 265

vvinit defined in line 239; used 4 times

- in line 106, 200, 232, 961

vvioctl defined in line 948; used 2 times

- in line 108, 201

vvoutput defined in line 804; used 2 times

- in line 108, 202

vvprobe defined in line 157; used 2 times

- in line 106, 112

vvprt_hdr defined in line 991; used 1 times

- in line 100

vvreset defined in line 223; used 2 times

- in line 106, 203

vvrint defined in line 627; used 2 times

- in line 108, 839

vvstart defined in line 486; used 5 times

- in line 107, 579, 596, 614, 934

vvwatchdog defined in line 604; used 2 times

- in line 107, 205

vvxint defined in line 548; used 2 times

- in line 107, 301

#### Defined variables

vv_modes defined in line 314; used 3 times

- in line 374, 389-393(2)

vv_softc defined in line 149; used 9 times

- in line 195, 247, 332, 497, 557, 610, 638, 821, 974

vv_tracehdr defined in line 98; used 1 times

- in line 100

vvdriver defined in line 111; never used
vvinfo defined in line 109; used 8 times

- in line 112, 228, 248, 333, 496, 556, 640, 820

vvstd defined in line 110; used 1 times

- in line 112

#### Defined struct's

vv_softc defined in line 132; used 16 times

- in line 193(2), 242(2), 323(2), 490(2), 552(2), 607(2), 630(2), 814(2)

#### Defined macros

LOOPBACK defined in line 115; used 2 times

- in line 116, 851

NOHOST defined in line 151; used 4 times

- in line 265, 330, 438, 463

VVBUFSIZE defined in line 90; used 7 times

- in line 89-91(2), 297, 392, 522, 693, 786

VVMRU defined in line 91; used 4 times

- in line 85-92(3), 696

VVMTU defined in line 92; used 6 times

- in line 84-87(3), 198, 255, 713

VVUNIT defined in line 113; used 1 times

- in line 495

vvdataaddr defined in line 710; used 2 times

- in line 718-719(2)

vvprintf defined in line 101; used 13 times

- in line 562, 589, 611, 652, 697, 705, 714, 721-722(2), 732, 739, 767, 836

vvtracehdr defined in line 100; used 2 times

- in line 689, 920

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