Annotation of 42BSD/sys/vaxif/if_il.c, revision 1.1

1.1     ! root        1: /*     if_il.c 6.2     83/09/24        */
        !             2: 
        !             3: #include "il.h"
        !             4: 
        !             5: /*
        !             6:  * Interlan Ethernet Communications Controller interface
        !             7:  */
        !             8: #include "../machine/pte.h"
        !             9: 
        !            10: #include "../h/param.h"
        !            11: #include "../h/systm.h"
        !            12: #include "../h/mbuf.h"
        !            13: #include "../h/buf.h"
        !            14: #include "../h/protosw.h"
        !            15: #include "../h/socket.h"
        !            16: #include "../h/vmmac.h"
        !            17: #include "../h/ioctl.h"
        !            18: #include "../h/errno.h"
        !            19: 
        !            20: #include "../net/if.h"
        !            21: #include "../net/netisr.h"
        !            22: #include "../net/route.h"
        !            23: #include "../netinet/in.h"
        !            24: #include "../netinet/in_systm.h"
        !            25: #include "../netinet/ip.h"
        !            26: #include "../netinet/ip_var.h"
        !            27: #include "../netinet/if_ether.h"
        !            28: #include "../netpup/pup.h"
        !            29: 
        !            30: #include "../vax/cpu.h"
        !            31: #include "../vax/mtpr.h"
        !            32: #include "../vaxif/if_il.h"
        !            33: #include "../vaxif/if_ilreg.h"
        !            34: #include "../vaxif/if_uba.h"
        !            35: #include "../vaxuba/ubareg.h"
        !            36: #include "../vaxuba/ubavar.h"
        !            37: 
        !            38: int    ilprobe(), ilattach(), ilrint(), ilcint();
        !            39: struct uba_device *ilinfo[NIL];
        !            40: u_short ilstd[] = { 0 };
        !            41: struct uba_driver ildriver =
        !            42:        { ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo };
        !            43: #define        ILUNIT(x)       minor(x)
        !            44: int    ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch();
        !            45: 
        !            46: /*
        !            47:  * Ethernet software status per interface.
        !            48:  *
        !            49:  * Each interface is referenced by a network interface structure,
        !            50:  * is_if, which the routing code uses to locate the interface.
        !            51:  * This structure contains the output queue for the interface, its address, ...
        !            52:  * We also have, for each interface, a UBA interface structure, which
        !            53:  * contains information about the UNIBUS resources held by the interface:
        !            54:  * map registers, buffered data paths, etc.  Information is cached in this
        !            55:  * structure for use by the if_uba.c routines in running the interface
        !            56:  * efficiently.
        !            57:  */
        !            58: struct il_softc {
        !            59:        struct  arpcom is_ac;           /* Ethernet common part */
        !            60: #define        is_if   is_ac.ac_if             /* network-visible interface */
        !            61: #define        is_addr is_ac.ac_enaddr         /* hardware Ethernet address */
        !            62:        struct  ifuba is_ifuba;         /* UNIBUS resources */
        !            63:        int     is_flags;
        !            64: #define        ILF_OACTIVE     0x1             /* output is active */
        !            65: #define        ILF_RCVPENDING  0x2             /* start rcv in ilcint */
        !            66: #define        ILF_STATPENDING 0x4             /* stat cmd pending */
        !            67:        short   is_lastcmd;             /* can't read csr, so must save it */
        !            68:        short   is_scaninterval;        /* interval of stat collection */
        !            69: #define        ILWATCHINTERVAL 60              /* once every 60 seconds */
        !            70:        struct  il_stats is_stats;      /* holds on-board statistics */
        !            71:        struct  il_stats is_sum;        /* summation over time */
        !            72:        int     is_ubaddr;              /* mapping registers of is_stats */
        !            73: } il_softc[NIL];
        !            74: 
        !            75: ilprobe(reg)
        !            76:        caddr_t reg;
        !            77: {
        !            78:        register int br, cvec;          /* r11, r10 value-result */
        !            79:        register struct ildevice *addr = (struct ildevice *)reg;
        !            80:        register i;
        !            81: 
        !            82: #ifdef lint
        !            83:        br = 0; cvec = br; br = cvec;
        !            84:        i = 0; ilrint(i); ilcint(i); ilwatch(i);
        !            85: #endif
        !            86: 
        !            87:        addr->il_csr = ILC_OFFLINE|IL_CIE;
        !            88:        DELAY(100000);
        !            89:        i = addr->il_csr;               /* clear CDONE */
        !            90:        if (cvec > 0 && cvec != 0x200)
        !            91:                cvec -= 4;
        !            92:        return (1);
        !            93: }
        !            94: 
        !            95: /*
        !            96:  * Interface exists: make available by filling in network interface
        !            97:  * record.  System will initialize the interface when it is ready
        !            98:  * to accept packets.  A STATUS command is done to get the ethernet
        !            99:  * address and other interesting data.
        !           100:  */
        !           101: ilattach(ui)
        !           102:        struct uba_device *ui;
        !           103: {
        !           104:        register struct il_softc *is = &il_softc[ui->ui_unit];
        !           105:        register struct ifnet *ifp = &is->is_if;
        !           106:        register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
        !           107:        struct sockaddr_in *sin;
        !           108: 
        !           109:        ifp->if_unit = ui->ui_unit;
        !           110:        ifp->if_name = "il";
        !           111:        ifp->if_mtu = ETHERMTU;
        !           112: 
        !           113:        /*
        !           114:         * Reset the board and map the statistics
        !           115:         * buffer onto the Unibus.
        !           116:         */
        !           117:        addr->il_csr = ILC_RESET;
        !           118:        while ((addr->il_csr&IL_CDONE) == 0)
        !           119:                ;
        !           120:        if (addr->il_csr&IL_STATUS)
        !           121:                printf("il%d: reset failed, csr=%b\n", ui->ui_unit,
        !           122:                        addr->il_csr, IL_BITS);
        !           123:        
        !           124:        is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats,
        !           125:            sizeof (struct il_stats), 0);
        !           126:        addr->il_bar = is->is_ubaddr & 0xffff;
        !           127:        addr->il_bcr = sizeof (struct il_stats);
        !           128:        addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT;
        !           129:        while ((addr->il_csr&IL_CDONE) == 0)
        !           130:                ;
        !           131:        if (addr->il_csr&IL_STATUS)
        !           132:                printf("il%d: status failed, csr=%b\n", ui->ui_unit,
        !           133:                        addr->il_csr, IL_BITS);
        !           134:        ubarelse(ui->ui_ubanum, &is->is_ubaddr);
        !           135: #ifdef notdef
        !           136:        printf("il%d: addr=%x:%x:%x:%x:%x:%x module=%s firmware=%s\n",
        !           137:                ui->ui_unit,
        !           138:                is->is_stats.ils_addr[0]&0xff, is->is_stats.ils_addr[1]&0xff,
        !           139:                is->is_stats.ils_addr[2]&0xff, is->is_stats.ils_addr[3]&0xff,
        !           140:                is->is_stats.ils_addr[4]&0xff, is->is_stats.ils_addr[5]&0xff,
        !           141:                is->is_stats.ils_module, is->is_stats.ils_firmware);
        !           142: #endif
        !           143:        bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
        !           144:            sizeof (is->is_addr));
        !           145:        sin = (struct sockaddr_in *)&ifp->if_addr;
        !           146:        sin->sin_family = AF_INET;
        !           147:        sin->sin_addr = arpmyaddr((struct arpcom *)0);
        !           148:        ifp->if_init = ilinit;
        !           149:        ifp->if_output = iloutput;
        !           150:        ifp->if_ioctl = ilioctl;
        !           151:        ifp->if_reset = ilreset;
        !           152:        is->is_ifuba.ifu_flags = UBA_CANTWAIT;
        !           153: #ifdef notdef
        !           154:        is->is_ifuba.ifu_flags |= UBA_NEEDBDP;
        !           155: #endif
        !           156:        if_attach(ifp);
        !           157: }
        !           158: 
        !           159: /*
        !           160:  * Reset of interface after UNIBUS reset.
        !           161:  * If interface is on specified uba, reset its state.
        !           162:  */
        !           163: ilreset(unit, uban)
        !           164:        int unit, uban;
        !           165: {
        !           166:        register struct uba_device *ui;
        !           167: 
        !           168:        if (unit >= NIL || (ui = ilinfo[unit]) == 0 || ui->ui_alive == 0 ||
        !           169:            ui->ui_ubanum != uban)
        !           170:                return;
        !           171:        printf(" il%d", unit);
        !           172:        ilinit(unit);
        !           173: }
        !           174: 
        !           175: /*
        !           176:  * Initialization of interface; clear recorded pending
        !           177:  * operations, and reinitialize UNIBUS usage.
        !           178:  */
        !           179: ilinit(unit)
        !           180:        int unit;
        !           181: {
        !           182:        register struct il_softc *is = &il_softc[unit];
        !           183:        register struct uba_device *ui = ilinfo[unit];
        !           184:        register struct ildevice *addr;
        !           185:        register struct ifnet *ifp = &is->is_if;
        !           186:        register struct sockaddr_in *sin;
        !           187:        int s;
        !           188: 
        !           189:        sin = (struct sockaddr_in *)&ifp->if_addr;
        !           190:        if (sin->sin_addr.s_addr == 0)          /* address still unknown */
        !           191:                return;
        !           192: 
        !           193:        if (ifp->if_flags & IFF_RUNNING)
        !           194:                goto justarp;
        !           195:        if (if_ubainit(&is->is_ifuba, ui->ui_ubanum,
        !           196:            sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) { 
        !           197:                printf("il%d: can't initialize\n", unit);
        !           198:                is->is_if.if_flags &= ~IFF_UP;
        !           199:                return;
        !           200:        }
        !           201:        is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats,
        !           202:            sizeof (struct il_stats), 0);
        !           203:        ifp->if_watchdog = ilwatch;
        !           204:        is->is_scaninterval = ILWATCHINTERVAL;
        !           205:        ifp->if_timer = is->is_scaninterval;
        !           206:        addr = (struct ildevice *)ui->ui_addr;
        !           207: 
        !           208:        /*
        !           209:         * Turn off source address insertion (it's faster this way),
        !           210:         * and set board online.  Former doesn't work if board is
        !           211:         * already online (happens on ubareset), so we put it offline
        !           212:         * first.
        !           213:         */
        !           214:        s = splimp();
        !           215:        addr->il_csr = ILC_OFFLINE;
        !           216:        while ((addr->il_csr & IL_CDONE) == 0)
        !           217:                ;
        !           218:        addr->il_csr = ILC_CISA;
        !           219:        while ((addr->il_csr & IL_CDONE) == 0)
        !           220:                ;
        !           221:        /*
        !           222:         * Set board online.
        !           223:         * Hang receive buffer and start any pending
        !           224:         * writes by faking a transmit complete.
        !           225:         * Receive bcr is not a muliple of 4 so buffer
        !           226:         * chaining can't happen.
        !           227:         */
        !           228:        addr->il_csr = ILC_ONLINE;
        !           229:        while ((addr->il_csr & IL_CDONE) == 0)
        !           230:                ;
        !           231:        addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
        !           232:        addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
        !           233:        addr->il_csr =
        !           234:            ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
        !           235:        while ((addr->il_csr & IL_CDONE) == 0)
        !           236:                ;
        !           237:        is->is_flags = ILF_OACTIVE;
        !           238:        is->is_if.if_flags |= IFF_UP|IFF_RUNNING;
        !           239:        is->is_lastcmd = 0;
        !           240:        ilcint(unit);
        !           241:        splx(s);
        !           242: justarp:
        !           243:        if_rtinit(&is->is_if, RTF_UP);
        !           244:        arpattach(&is->is_ac);
        !           245:        arpwhohas(&is->is_ac, &sin->sin_addr);
        !           246: }
        !           247: 
        !           248: /*
        !           249:  * Start output on interface.
        !           250:  * Get another datagram to send off of the interface queue,
        !           251:  * and map it to the interface before starting the output.
        !           252:  */
        !           253: ilstart(dev)
        !           254:        dev_t dev;
        !           255: {
        !           256:         int unit = ILUNIT(dev), len;
        !           257:        struct uba_device *ui = ilinfo[unit];
        !           258:        register struct il_softc *is = &il_softc[unit];
        !           259:        register struct ildevice *addr;
        !           260:        struct mbuf *m;
        !           261:        short csr;
        !           262: 
        !           263:        IF_DEQUEUE(&is->is_if.if_snd, m);
        !           264:        addr = (struct ildevice *)ui->ui_addr;
        !           265:        if (m == 0) {
        !           266:                if ((is->is_flags & ILF_STATPENDING) == 0)
        !           267:                        return;
        !           268:                addr->il_bar = is->is_ubaddr & 0xffff;
        !           269:                addr->il_bcr = sizeof (struct il_stats);
        !           270:                csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE;
        !           271:                is->is_flags &= ~ILF_STATPENDING;
        !           272:                goto startcmd;
        !           273:        }
        !           274:        len = if_wubaput(&is->is_ifuba, m);
        !           275:        /*
        !           276:         * Ensure minimum packet length.
        !           277:         * This makes the safe assumtion that there are no virtual holes
        !           278:         * after the data.
        !           279:         * For security, it might be wise to zero out the added bytes,
        !           280:         * but we're mainly interested in speed at the moment.
        !           281:         */
        !           282:        if (len - sizeof(struct ether_header) < ETHERMIN)
        !           283:                len = ETHERMIN + sizeof(struct ether_header);
        !           284:        if (is->is_ifuba.ifu_flags & UBA_NEEDBDP)
        !           285:                UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp);
        !           286:        addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff;
        !           287:        addr->il_bcr = len;
        !           288:        csr =
        !           289:          ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE;
        !           290: 
        !           291: startcmd:
        !           292:        is->is_lastcmd = csr & IL_CMD;
        !           293:        addr->il_csr = csr;
        !           294:        is->is_flags |= ILF_OACTIVE;
        !           295: }
        !           296: 
        !           297: /*
        !           298:  * Command done interrupt.
        !           299:  */
        !           300: ilcint(unit)
        !           301:        int unit;
        !           302: {
        !           303:        register struct il_softc *is = &il_softc[unit];
        !           304:        struct uba_device *ui = ilinfo[unit];
        !           305:        register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
        !           306:        short csr;
        !           307: 
        !           308:        if ((is->is_flags & ILF_OACTIVE) == 0) {
        !           309:                printf("il%d: stray xmit interrupt, csr=%b\n", unit,
        !           310:                        addr->il_csr, IL_BITS);
        !           311:                return;
        !           312:        }
        !           313: 
        !           314:        csr = addr->il_csr;
        !           315:        /*
        !           316:         * Hang receive buffer if it couldn't
        !           317:         * be done earlier (in ilrint).
        !           318:         */
        !           319:        if (is->is_flags & ILF_RCVPENDING) {
        !           320:                addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
        !           321:                addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
        !           322:                addr->il_csr =
        !           323:                  ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
        !           324:                while ((addr->il_csr & IL_CDONE) == 0)
        !           325:                        ;
        !           326:                is->is_flags &= ~ILF_RCVPENDING;
        !           327:        }
        !           328:        is->is_flags &= ~ILF_OACTIVE;
        !           329:        csr &= IL_STATUS;
        !           330:        switch (is->is_lastcmd) {
        !           331: 
        !           332:        case ILC_XMIT:
        !           333:                is->is_if.if_opackets++;
        !           334:                if (csr > ILERR_RETRIES)
        !           335:                        is->is_if.if_oerrors++;
        !           336:                break;
        !           337: 
        !           338:        case ILC_STAT:
        !           339:                if (csr == ILERR_SUCCESS)
        !           340:                        iltotal(is);
        !           341:                break;
        !           342:        }
        !           343:        if (is->is_ifuba.ifu_xtofree) {
        !           344:                m_freem(is->is_ifuba.ifu_xtofree);
        !           345:                is->is_ifuba.ifu_xtofree = 0;
        !           346:        }
        !           347:        ilstart(unit);
        !           348: }
        !           349: 
        !           350: /*
        !           351:  * Ethernet interface receiver interrupt.
        !           352:  * If input error just drop packet.
        !           353:  * Otherwise purge input buffered data path and examine 
        !           354:  * packet to determine type.  If can't determine length
        !           355:  * from type, then have to drop packet.  Othewise decapsulate
        !           356:  * packet based on type and pass to type specific higher-level
        !           357:  * input routine.
        !           358:  */
        !           359: ilrint(unit)
        !           360:        int unit;
        !           361: {
        !           362:        register struct il_softc *is = &il_softc[unit];
        !           363:        struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr;
        !           364:        register struct il_rheader *il;
        !           365:        struct mbuf *m;
        !           366:        int len, off, resid;
        !           367:        register struct ifqueue *inq;
        !           368: 
        !           369:        is->is_if.if_ipackets++;
        !           370:        if (is->is_ifuba.ifu_flags & UBA_NEEDBDP)
        !           371:                UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp);
        !           372:        il = (struct il_rheader *)(is->is_ifuba.ifu_r.ifrw_addr);
        !           373:        len = il->ilr_length - sizeof(struct il_rheader);
        !           374:        if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 ||
        !           375:            len > ETHERMTU) {
        !           376:                is->is_if.if_ierrors++;
        !           377: #ifdef notdef
        !           378:                if (is->is_if.if_ierrors % 100 == 0)
        !           379:                        printf("il%d: += 100 input errors\n", unit);
        !           380: #endif
        !           381:                goto setup;
        !           382:        }
        !           383: 
        !           384:        /*
        !           385:         * Deal with trailer protocol: if type is PUP trailer
        !           386:         * get true type from first 16-bit word past data.
        !           387:         * Remember that type was trailer by setting off.
        !           388:         */
        !           389:        il->ilr_type = ntohs((u_short)il->ilr_type);
        !           390: #define        ildataaddr(il, off, type)       ((type)(((caddr_t)((il)+1)+(off))))
        !           391:        if (il->ilr_type >= ETHERPUP_TRAIL &&
        !           392:            il->ilr_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) {
        !           393:                off = (il->ilr_type - ETHERPUP_TRAIL) * 512;
        !           394:                if (off >= ETHERMTU)
        !           395:                        goto setup;             /* sanity */
        !           396:                il->ilr_type = ntohs(*ildataaddr(il, off, u_short *));
        !           397:                resid = ntohs(*(ildataaddr(il, off+2, u_short *)));
        !           398:                if (off + resid > len)
        !           399:                        goto setup;             /* sanity */
        !           400:                len = off + resid;
        !           401:        } else
        !           402:                off = 0;
        !           403:        if (len == 0)
        !           404:                goto setup;
        !           405: 
        !           406:        /*
        !           407:         * Pull packet off interface.  Off is nonzero if packet
        !           408:         * has trailing header; ilget will then force this header
        !           409:         * information to be at the front, but we still have to drop
        !           410:         * the type and length which are at the front of any trailer data.
        !           411:         */
        !           412:        m = if_rubaget(&is->is_ifuba, len, off);
        !           413:        if (m == 0)
        !           414:                goto setup;
        !           415:        if (off) {
        !           416:                m->m_off += 2 * sizeof (u_short);
        !           417:                m->m_len -= 2 * sizeof (u_short);
        !           418:        }
        !           419:        switch (il->ilr_type) {
        !           420: 
        !           421: #ifdef INET
        !           422:        case ETHERPUP_IPTYPE:
        !           423:                schednetisr(NETISR_IP);
        !           424:                inq = &ipintrq;
        !           425:                break;
        !           426: 
        !           427:        case ETHERPUP_ARPTYPE:
        !           428:                arpinput(&is->is_ac, m);
        !           429:                goto setup;
        !           430: #endif
        !           431:        default:
        !           432:                m_freem(m);
        !           433:                goto setup;
        !           434:        }
        !           435: 
        !           436:        if (IF_QFULL(inq)) {
        !           437:                IF_DROP(inq);
        !           438:                m_freem(m);
        !           439:                goto setup;
        !           440:        }
        !           441:        IF_ENQUEUE(inq, m);
        !           442: 
        !           443: setup:
        !           444:        /*
        !           445:         * Reset for next packet if possible.
        !           446:         * If waiting for transmit command completion, set flag
        !           447:         * and wait until command completes.
        !           448:         */
        !           449:        if (is->is_flags & ILF_OACTIVE) {
        !           450:                is->is_flags |= ILF_RCVPENDING;
        !           451:                return;
        !           452:        }
        !           453:        addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
        !           454:        addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
        !           455:        addr->il_csr =
        !           456:                ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
        !           457:        while ((addr->il_csr & IL_CDONE) == 0)
        !           458:                ;
        !           459: }
        !           460: 
        !           461: /*
        !           462:  * Ethernet output routine.
        !           463:  * Encapsulate a packet of type family for the local net.
        !           464:  * Use trailer local net encapsulation if enough data in first
        !           465:  * packet leaves a multiple of 512 bytes of data in remainder.
        !           466:  */
        !           467: iloutput(ifp, m0, dst)
        !           468:        struct ifnet *ifp;
        !           469:        struct mbuf *m0;
        !           470:        struct sockaddr *dst;
        !           471: {
        !           472:        int type, s, error;
        !           473:        u_char edst[6];
        !           474:        struct in_addr idst;
        !           475:        register struct il_softc *is = &il_softc[ifp->if_unit];
        !           476:        register struct mbuf *m = m0;
        !           477:        register struct ether_header *il;
        !           478:        register int off;
        !           479: 
        !           480:        switch (dst->sa_family) {
        !           481: 
        !           482: #ifdef INET
        !           483:        case AF_INET:
        !           484:                idst = ((struct sockaddr_in *)dst)->sin_addr;
        !           485:                if (!arpresolve(&is->is_ac, m, &idst, edst))
        !           486:                        return (0);     /* if not yet resolved */
        !           487:                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
        !           488:                /* need per host negotiation */
        !           489:                if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
        !           490:                if (off > 0 && (off & 0x1ff) == 0 &&
        !           491:                    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
        !           492:                        type = ETHERPUP_TRAIL + (off>>9);
        !           493:                        m->m_off -= 2 * sizeof (u_short);
        !           494:                        m->m_len += 2 * sizeof (u_short);
        !           495:                        *mtod(m, u_short *) = htons((u_short)ETHERPUP_IPTYPE);
        !           496:                        *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
        !           497:                        goto gottrailertype;
        !           498:                }
        !           499:                type = ETHERPUP_IPTYPE;
        !           500:                off = 0;
        !           501:                goto gottype;
        !           502: #endif
        !           503: 
        !           504:        case AF_UNSPEC:
        !           505:                il = (struct ether_header *)dst->sa_data;
        !           506:                bcopy((caddr_t)il->ether_dhost, (caddr_t)edst, sizeof (edst));
        !           507:                type = il->ether_type;
        !           508:                goto gottype;
        !           509: 
        !           510:        default:
        !           511:                printf("il%d: can't handle af%d\n", ifp->if_unit,
        !           512:                        dst->sa_family);
        !           513:                error = EAFNOSUPPORT;
        !           514:                goto bad;
        !           515:        }
        !           516: 
        !           517: gottrailertype:
        !           518:        /*
        !           519:         * Packet to be sent as trailer: move first packet
        !           520:         * (control information) to end of chain.
        !           521:         */
        !           522:        while (m->m_next)
        !           523:                m = m->m_next;
        !           524:        m->m_next = m0;
        !           525:        m = m0->m_next;
        !           526:        m0->m_next = 0;
        !           527:        m0 = m;
        !           528: 
        !           529: gottype:
        !           530:        /*
        !           531:         * Add local net header.  If no space in first mbuf,
        !           532:         * allocate another.
        !           533:         */
        !           534:        if (m->m_off > MMAXOFF ||
        !           535:            MMINOFF + sizeof (struct ether_header) > m->m_off) {
        !           536:                m = m_get(M_DONTWAIT, MT_HEADER);
        !           537:                if (m == 0) {
        !           538:                        error = ENOBUFS;
        !           539:                        goto bad;
        !           540:                }
        !           541:                m->m_next = m0;
        !           542:                m->m_off = MMINOFF;
        !           543:                m->m_len = sizeof (struct ether_header);
        !           544:        } else {
        !           545:                m->m_off -= sizeof (struct ether_header);
        !           546:                m->m_len += sizeof (struct ether_header);
        !           547:        }
        !           548:        il = mtod(m, struct ether_header *);
        !           549:        il->ether_type = htons((u_short)type);
        !           550:        bcopy((caddr_t)edst, (caddr_t)il->ether_dhost, sizeof (edst));
        !           551:        bcopy((caddr_t)is->is_addr, (caddr_t)il->ether_shost, 6);
        !           552: 
        !           553:        /*
        !           554:         * Queue message on interface, and start output if interface
        !           555:         * not yet active.
        !           556:         */
        !           557:        s = splimp();
        !           558:        if (IF_QFULL(&ifp->if_snd)) {
        !           559:                IF_DROP(&ifp->if_snd);
        !           560:                splx(s);
        !           561:                m_freem(m);
        !           562:                return (ENOBUFS);
        !           563:        }
        !           564:        IF_ENQUEUE(&ifp->if_snd, m);
        !           565:        if ((is->is_flags & ILF_OACTIVE) == 0)
        !           566:                ilstart(ifp->if_unit);
        !           567:        splx(s);
        !           568:        return (0);
        !           569: 
        !           570: bad:
        !           571:        m_freem(m0);
        !           572:        return (error);
        !           573: }
        !           574: 
        !           575: /*
        !           576:  * Watchdog routine, request statistics from board.
        !           577:  */
        !           578: ilwatch(unit)
        !           579:        int unit;
        !           580: {
        !           581:        register struct il_softc *is = &il_softc[unit];
        !           582:        register struct ifnet *ifp = &is->is_if;
        !           583:        int s;
        !           584: 
        !           585:        if (is->is_flags & ILF_STATPENDING) {
        !           586:                ifp->if_timer = is->is_scaninterval;
        !           587:                return;
        !           588:        }
        !           589:        s = splimp();
        !           590:        is->is_flags |= ILF_STATPENDING;
        !           591:        if ((is->is_flags & ILF_OACTIVE) == 0)
        !           592:                ilstart(ifp->if_unit);
        !           593:        splx(s);
        !           594:        ifp->if_timer = is->is_scaninterval;
        !           595: }
        !           596: 
        !           597: /*
        !           598:  * Total up the on-board statistics.
        !           599:  */
        !           600: iltotal(is)
        !           601:        register struct il_softc *is;
        !           602: {
        !           603:        register u_short *interval, *sum, *end;
        !           604: 
        !           605:        interval = &is->is_stats.ils_frames;
        !           606:        sum = &is->is_sum.ils_frames;
        !           607:        end = is->is_sum.ils_fill2;
        !           608:        while (sum < end)
        !           609:                *sum++ += *interval++;
        !           610:        is->is_if.if_collisions = is->is_sum.ils_collis;
        !           611: }
        !           612: 
        !           613: /*
        !           614:  * Process an ioctl request.
        !           615:  */
        !           616: ilioctl(ifp, cmd, data)
        !           617:        register struct ifnet *ifp;
        !           618:        int cmd;
        !           619:        caddr_t data;
        !           620: {
        !           621:        register struct ifreq *ifr = (struct ifreq *)data;
        !           622:        int s = splimp(), error = 0;
        !           623: 
        !           624:        switch (cmd) {
        !           625: 
        !           626:        case SIOCSIFADDR:
        !           627:                if (ifp->if_flags & IFF_RUNNING)
        !           628:                        if_rtinit(ifp, -1);     /* delete previous route */
        !           629:                ilsetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
        !           630:                ilinit(ifp->if_unit);
        !           631:                break;
        !           632: 
        !           633:        default:
        !           634:                error = EINVAL;
        !           635:        }
        !           636:        splx(s);
        !           637:        return (error);
        !           638: }
        !           639: 
        !           640: ilsetaddr(ifp, sin)
        !           641:        register struct ifnet *ifp;
        !           642:        register struct sockaddr_in *sin;
        !           643: {
        !           644: 
        !           645:        ifp->if_addr = *(struct sockaddr *)sin;
        !           646:        ifp->if_net = in_netof(sin->sin_addr);
        !           647:        ifp->if_host[0] = in_lnaof(sin->sin_addr);
        !           648:        sin = (struct sockaddr_in *)&ifp->if_broadaddr;
        !           649:        sin->sin_family = AF_INET;
        !           650:        sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
        !           651:        ifp->if_flags |= IFF_BROADCAST;
        !           652: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.