Annotation of 43BSDReno/sys/vaxif/if_il.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution is only permitted until one year after the first shipment
        !             6:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
        !             7:  * binary forms are permitted provided that: (1) source distributions retain
        !             8:  * this entire copyright notice and comment, and (2) distributions including
        !             9:  * binaries display the following acknowledgement:  This product includes
        !            10:  * software developed by the University of California, Berkeley and its
        !            11:  * contributors'' in the documentation or other materials provided with the
        !            12:  * distribution and in all advertising materials mentioning features or use
        !            13:  * of this software.  Neither the name of the University nor the names of
        !            14:  * its contributors may be used to endorse or promote products derived from
        !            15:  * this software without specific prior written permission.
        !            16:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            17:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            19:  *
        !            20:  *     @(#)if_il.c     7.7 (Berkeley) 6/28/90
        !            21:  */
        !            22: 
        !            23: #include "il.h"
        !            24: #if NIL > 0
        !            25: 
        !            26: /*
        !            27:  * Interlan Ethernet Communications Controller interface
        !            28:  */
        !            29: #include "machine/pte.h"
        !            30: 
        !            31: #include "param.h"
        !            32: #include "systm.h"
        !            33: #include "mbuf.h"
        !            34: #include "buf.h"
        !            35: #include "protosw.h"
        !            36: #include "socket.h"
        !            37: #include "vmmac.h"
        !            38: #include "ioctl.h"
        !            39: #include "errno.h"
        !            40: #include "syslog.h"
        !            41: 
        !            42: #include "../net/if.h"
        !            43: #include "../net/netisr.h"
        !            44: #include "../net/route.h"
        !            45: 
        !            46: #ifdef INET
        !            47: #include "../netinet/in.h"
        !            48: #include "../netinet/in_systm.h"
        !            49: #include "../netinet/in_var.h"
        !            50: #include "../netinet/ip.h"
        !            51: #include "../netinet/if_ether.h"
        !            52: #endif
        !            53: 
        !            54: #ifdef NS
        !            55: #include "../netns/ns.h"
        !            56: #include "../netns/ns_if.h"
        !            57: #endif
        !            58: 
        !            59: #include "../vax/cpu.h"
        !            60: #include "../vax/mtpr.h"
        !            61: #include "if_il.h"
        !            62: #include "if_ilreg.h"
        !            63: #include "if_uba.h"
        !            64: #include "../vaxuba/ubareg.h"
        !            65: #include "../vaxuba/ubavar.h"
        !            66: 
        !            67: int    ilprobe(), ilattach(), ilrint(), ilcint();
        !            68: struct uba_device *ilinfo[NIL];
        !            69: u_short ilstd[] = { 0 };
        !            70: struct uba_driver ildriver =
        !            71:        { ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo };
        !            72: #define        ILUNIT(x)       minor(x)
        !            73: int    ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch(),ilstart();
        !            74: int    ildebug = 0;
        !            75: 
        !            76: /*
        !            77:  * Ethernet software status per interface.
        !            78:  *
        !            79:  * Each interface is referenced by a network interface structure,
        !            80:  * is_if, which the routing code uses to locate the interface.
        !            81:  * This structure contains the output queue for the interface, its address, ...
        !            82:  * We also have, for each interface, a UBA interface structure, which
        !            83:  * contains information about the UNIBUS resources held by the interface:
        !            84:  * map registers, buffered data paths, etc.  Information is cached in this
        !            85:  * structure for use by the if_uba.c routines in running the interface
        !            86:  * efficiently.
        !            87:  */
        !            88: 
        !            89: struct ether_addr {
        !            90:        u_char  addr[6];
        !            91: };
        !            92: struct il_softc {
        !            93:        struct  arpcom is_ac;           /* Ethernet common part */
        !            94: #define        is_if   is_ac.ac_if             /* network-visible interface */
        !            95: #define        is_addr is_ac.ac_enaddr         /* hardware Ethernet address */
        !            96:        struct  ifuba is_ifuba;         /* UNIBUS resources */
        !            97:        int     is_flags;
        !            98: #define        ILF_RCVPENDING  0x2             /* start rcv in ilcint */
        !            99: #define        ILF_STATPENDING 0x4             /* stat cmd pending */
        !           100: #define        ILF_RUNNING     0x8             /* board is running */
        !           101: #define        ILF_SETADDR     0x10            /* physical address is changed */
        !           102:        short   is_lastcmd;             /* can't read csr, so must save it */
        !           103:        short   is_scaninterval;        /* interval of stat collection */
        !           104: #define        ILWATCHINTERVAL 60              /* once every 60 seconds */
        !           105:        union {
        !           106:            struct      il_stats isu_stats;     /* holds on-board statistics */
        !           107:            struct      ether_addr isu_maddrs[63];      /* multicast addrs */
        !           108:        }       is_isu;
        !           109: #define is_stats       is_isu.isu_stats
        !           110: #define is_maddrs      is_isu.isu_maddrs
        !           111:        struct  il_stats is_sum;        /* summation over time */
        !           112:        int     is_ubaddr;              /* mapping registers of is_stats */
        !           113: } il_softc[NIL];
        !           114: 
        !           115: ilprobe(reg)
        !           116:        caddr_t reg;
        !           117: {
        !           118:        register int br, cvec;          /* r11, r10 value-result */
        !           119:        register struct ildevice *addr = (struct ildevice *)reg;
        !           120:        register i;
        !           121: 
        !           122: #ifdef lint
        !           123:        br = 0; cvec = br; br = cvec;
        !           124:        i = 0; ilrint(i); ilcint(i); ilwatch(i);
        !           125: #endif
        !           126: 
        !           127:        addr->il_csr = ILC_OFFLINE|IL_CIE;
        !           128:        DELAY(100000);
        !           129:        i = addr->il_csr;               /* clear CDONE */
        !           130:        if (cvec > 0 && cvec != 0x200)
        !           131:                cvec -= 4;
        !           132:        return (1);
        !           133: }
        !           134: 
        !           135: /*
        !           136:  * Interface exists: make available by filling in network interface
        !           137:  * record.  System will initialize the interface when it is ready
        !           138:  * to accept packets.  A STATUS command is done to get the ethernet
        !           139:  * address and other interesting data.
        !           140:  */
        !           141: ilattach(ui)
        !           142:        struct uba_device *ui;
        !           143: {
        !           144:        register struct il_softc *is = &il_softc[ui->ui_unit];
        !           145:        register struct ifnet *ifp = &is->is_if;
        !           146:        register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
        !           147: 
        !           148:        ifp->if_unit = ui->ui_unit;
        !           149:        ifp->if_name = "il";
        !           150:        ifp->if_mtu = ETHERMTU;
        !           151:        ifp->if_flags = IFF_BROADCAST;
        !           152: 
        !           153:        /*
        !           154:         * Reset the board and map the statistics
        !           155:         * buffer onto the Unibus.
        !           156:         */
        !           157:        addr->il_csr = ILC_RESET;
        !           158:        (void)ilwait(ui, "reset");
        !           159:        
        !           160:        is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats,
        !           161:            sizeof (struct il_stats), 0);
        !           162:        addr->il_bar = is->is_ubaddr & 0xffff;
        !           163:        addr->il_bcr = sizeof (struct il_stats);
        !           164:        addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT;
        !           165:        (void)ilwait(ui, "status");
        !           166:        ubarelse(ui->ui_ubanum, &is->is_ubaddr);
        !           167:        if (ildebug)
        !           168:                printf("il%d: module=%s firmware=%s\n", ui->ui_unit,
        !           169:                        is->is_stats.ils_module, is->is_stats.ils_firmware);
        !           170:        bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
        !           171:            sizeof (is->is_addr));
        !           172:        printf("il%d: hardware address %s\n", ui->ui_unit,
        !           173:                ether_sprintf(is->is_addr));
        !           174:        ifp->if_init = ilinit;
        !           175:        ifp->if_output = ether_output;
        !           176:        ifp->if_ioctl = ilioctl;
        !           177:        ifp->if_reset = ilreset;
        !           178:        ifp->if_start = ilstart;
        !           179:        is->is_ifuba.ifu_flags = UBA_CANTWAIT;
        !           180:        if_attach(ifp);
        !           181: }
        !           182: 
        !           183: ilwait(ui, op)
        !           184:        struct uba_device *ui;
        !           185:        char *op;
        !           186: {
        !           187:        register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
        !           188: 
        !           189:        while ((addr->il_csr&IL_CDONE) == 0)
        !           190:                ;
        !           191:        if (addr->il_csr&IL_STATUS) {
        !           192:                printf("il%d: %s failed, csr=%b\n", ui->ui_unit, op,
        !           193:                        addr->il_csr, IL_BITS);
        !           194:                return (-1);
        !           195:        }
        !           196:        return (0);
        !           197: }
        !           198: 
        !           199: /*
        !           200:  * Reset of interface after UNIBUS reset.
        !           201:  * If interface is on specified uba, reset its state.
        !           202:  */
        !           203: ilreset(unit, uban)
        !           204:        int unit, uban;
        !           205: {
        !           206:        register struct uba_device *ui;
        !           207: 
        !           208:        if (unit >= NIL || (ui = ilinfo[unit]) == 0 || ui->ui_alive == 0 ||
        !           209:            ui->ui_ubanum != uban)
        !           210:                return;
        !           211:        printf(" il%d", unit);
        !           212:        il_softc[unit].is_if.if_flags &= ~IFF_RUNNING;
        !           213:        il_softc[unit].is_flags &= ~ILF_RUNNING;
        !           214:        ilinit(unit);
        !           215: }
        !           216: 
        !           217: /*
        !           218:  * Initialization of interface; clear recorded pending
        !           219:  * operations, and reinitialize UNIBUS usage.
        !           220:  */
        !           221: ilinit(unit)
        !           222:        int unit;
        !           223: {
        !           224:        register struct il_softc *is = &il_softc[unit];
        !           225:        register struct uba_device *ui = ilinfo[unit];
        !           226:        register struct ildevice *addr;
        !           227:        register struct ifnet *ifp = &is->is_if;
        !           228:        int s;
        !           229: 
        !           230:        /* not yet, if address still unknown */
        !           231:        if (ifp->if_addrlist == (struct ifaddr *)0)
        !           232:                return;
        !           233:        if (is->is_flags & ILF_RUNNING)
        !           234:                return;
        !           235: 
        !           236:        if ((ifp->if_flags & IFF_RUNNING) == 0) {
        !           237:                if (if_ubainit(&is->is_ifuba, ui->ui_ubanum,
        !           238:                    sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) { 
        !           239:                        printf("il%d: can't initialize\n", unit);
        !           240:                        is->is_if.if_flags &= ~IFF_UP;
        !           241:                        return;
        !           242:                }
        !           243:                is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_isu,
        !           244:                    sizeof (is->is_isu), 0);
        !           245:        }
        !           246:        ifp->if_watchdog = ilwatch;
        !           247:        is->is_scaninterval = ILWATCHINTERVAL;
        !           248:        ifp->if_timer = is->is_scaninterval;
        !           249:        addr = (struct ildevice *)ui->ui_addr;
        !           250: 
        !           251:        /*
        !           252:         * Turn off source address insertion (it's faster this way),
        !           253:         * and set board online.  Former doesn't work if board is
        !           254:         * already online (happens on ubareset), so we put it offline
        !           255:         * first.
        !           256:         */
        !           257:        s = splimp();
        !           258:        addr->il_csr = ILC_RESET;
        !           259:        if (ilwait(ui, "hardware diag")) {
        !           260:                is->is_if.if_flags &= ~IFF_UP;
        !           261:                splx(s);
        !           262:                return;
        !           263:        }
        !           264:        addr->il_csr = ILC_CISA;
        !           265:        while ((addr->il_csr & IL_CDONE) == 0)
        !           266:                ;
        !           267:        /*
        !           268:         * If we must reprogram this board's physical ethernet
        !           269:         * address (as for secondary XNS interfaces), we do so
        !           270:         * before putting it on line, and starting receive requests.
        !           271:         * If you try this on an older 1010 board, it will total
        !           272:         * wedge the board.
        !           273:         */
        !           274:        if (is->is_flags & ILF_SETADDR) {
        !           275:                bcopy((caddr_t)is->is_addr, (caddr_t)&is->is_isu,
        !           276:                                                        sizeof is->is_addr);
        !           277:                addr->il_bar = is->is_ubaddr & 0xffff;
        !           278:                addr->il_bcr = sizeof is->is_addr;
        !           279:                addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_LDPA;
        !           280:                if (ilwait(ui, "setaddr"))
        !           281:                        return;
        !           282:                addr->il_bar = is->is_ubaddr & 0xffff;
        !           283:                addr->il_bcr = sizeof (struct il_stats);
        !           284:                addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT;
        !           285:                if (ilwait(ui, "verifying setaddr"))
        !           286:                        return;
        !           287:                if (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
        !           288:                                                sizeof (is->is_addr)) != 0) {
        !           289:                        printf("il%d: setaddr didn't work\n", ui->ui_unit);
        !           290:                        return;
        !           291:                }
        !           292:        }
        !           293: #ifdef MULTICAST
        !           294:        if (is->is_if.if_flags & IFF_PROMISC) {
        !           295:                addr->il_csr = ILC_PRMSC;
        !           296:                if (ilwait(ui, "all multi"))
        !           297:                        return;
        !           298:        } else if (is->is_if.if_flags & IFF_ALLMULTI) {
        !           299:        too_many_multis:
        !           300:                addr->il_csr = ILC_ALLMC;
        !           301:                if (ilwait(ui, "all multi"))
        !           302:                        return;
        !           303:        else {
        !           304:                int i;
        !           305:                register struct ether_addr *ep = is->is_maddrs;
        !           306:                struct ether_multi *enm;
        !           307:                struct ether_multistep step;
        !           308:                /*
        !           309:                 * Step through our list of multicast addresses.  If we have
        !           310:                 * too many multicast addresses, or if we have to listen to
        !           311:                 * a range of multicast addresses, turn on reception of all
        !           312:                 * multicasts.
        !           313:                 */
        !           314:                i = 0;
        !           315:                ETHER_FIRST_MULTI(step, &is->is_ac, enm);
        !           316:                while (enm != NULL) {
        !           317:                        if (++i > 63 && k != 0) {
        !           318:                                break;
        !           319:                        }
        !           320:                        *ep++ = *(struct ether_addr *)enm->enm_addrlo;
        !           321:                        ETHER_NEXT_MULTI(step, enm);
        !           322:                }
        !           323:                if (i = 0) {
        !           324:                        /* no multicasts! */
        !           325:                } else if (i <= 63) {
        !           326:                        addr->il_bar = is->is_ubaddr & 0xffff;
        !           327:                        addr->il_bcr = i * sizeof (struct ether_addr);
        !           328:                        addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|
        !           329:                                                LC_LDGRPS;
        !           330:                        if (ilwait(ui, "load multi"))
        !           331:                                return;
        !           332:                } else {
        !           333:                    is->is_if.if_flags |= IFF_ALLMULTI;
        !           334:                    goto too_many_multis;
        !           335:                }
        !           336:        }
        !           337: #endif MULTI
        !           338:        /*
        !           339:         * Set board online.
        !           340:         * Hang receive buffer and start any pending
        !           341:         * writes by faking a transmit complete.
        !           342:         * Receive bcr is not a multiple of 8 so buffer
        !           343:         * chaining can't happen.
        !           344:         */
        !           345:        addr->il_csr = ILC_ONLINE;
        !           346:        while ((addr->il_csr & IL_CDONE) == 0)
        !           347:                ;
        !           348:        addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
        !           349:        addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
        !           350:        addr->il_csr =
        !           351:            ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
        !           352:        while ((addr->il_csr & IL_CDONE) == 0)
        !           353:                ;
        !           354:        is->is_if.if_flags |= IFF_RUNNING | IFF_OACTIVE;
        !           355:        is->is_flags |= ILF_RUNNING;
        !           356:        is->is_lastcmd = 0;
        !           357:        ilcint(unit);
        !           358:        splx(s);
        !           359: }
        !           360: 
        !           361: /*
        !           362:  * Start output on interface.
        !           363:  * Get another datagram to send off of the interface queue,
        !           364:  * and map it to the interface before starting the output.
        !           365:  */
        !           366: ilstart(ifp)
        !           367:        register struct ifnet *ifp;
        !           368: {
        !           369:         int unit = ifp->if_unit, len;
        !           370:        struct uba_device *ui = ilinfo[unit];
        !           371:        register struct il_softc *is = &il_softc[unit];
        !           372:        register struct ildevice *addr;
        !           373:        struct mbuf *m;
        !           374:        short csr;
        !           375: 
        !           376:        IF_DEQUEUE(&is->is_if.if_snd, m);
        !           377:        addr = (struct ildevice *)ui->ui_addr;
        !           378:        if (m == 0) {
        !           379:                if ((is->is_flags & ILF_STATPENDING) == 0)
        !           380:                        return (0);
        !           381:                addr->il_bar = is->is_ubaddr & 0xffff;
        !           382:                addr->il_bcr = sizeof (struct il_stats);
        !           383:                csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE;
        !           384:                is->is_flags &= ~ILF_STATPENDING;
        !           385:                goto startcmd;
        !           386:        }
        !           387:        len = if_wubaput(&is->is_ifuba, m);
        !           388:        /*
        !           389:         * Ensure minimum packet length.
        !           390:         * This makes the safe assumtion that there are no virtual holes
        !           391:         * after the data.
        !           392:         * For security, it might be wise to zero out the added bytes,
        !           393:         * but we're mainly interested in speed at the moment.
        !           394:         */
        !           395:        if (len - sizeof(struct ether_header) < ETHERMIN)
        !           396:                len = ETHERMIN + sizeof(struct ether_header);
        !           397:        if (is->is_ifuba.ifu_flags & UBA_NEEDBDP)
        !           398:                UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp);
        !           399:        addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff;
        !           400:        addr->il_bcr = len;
        !           401:        csr =
        !           402:          ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE;
        !           403: 
        !           404: startcmd:
        !           405:        is->is_lastcmd = csr & IL_CMD;
        !           406:        addr->il_csr = csr;
        !           407:        is->is_if.if_flags |= IFF_OACTIVE;
        !           408:        return (0);
        !           409: }
        !           410: 
        !           411: /*
        !           412:  * Command done interrupt.
        !           413:  */
        !           414: ilcint(unit)
        !           415:        int unit;
        !           416: {
        !           417:        register struct il_softc *is = &il_softc[unit];
        !           418:        struct uba_device *ui = ilinfo[unit];
        !           419:        register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
        !           420:        short csr;
        !           421: 
        !           422:        if ((is->is_if.if_flags & IFF_OACTIVE) == 0) {
        !           423:                printf("il%d: stray xmit interrupt, csr=%b\n", unit,
        !           424:                        addr->il_csr, IL_BITS);
        !           425:                return;
        !           426:        }
        !           427: 
        !           428:        csr = addr->il_csr;
        !           429:        /*
        !           430:         * Hang receive buffer if it couldn't
        !           431:         * be done earlier (in ilrint).
        !           432:         */
        !           433:        if (is->is_flags & ILF_RCVPENDING) {
        !           434:                int s;
        !           435: 
        !           436:                addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
        !           437:                addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
        !           438:                addr->il_csr =
        !           439:                  ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
        !           440:                s = splhigh();
        !           441:                while ((addr->il_csr & IL_CDONE) == 0)
        !           442:                        ;
        !           443:                splx(s);
        !           444:                is->is_flags &= ~ILF_RCVPENDING;
        !           445:        }
        !           446:        is->is_if.if_flags &= ~IFF_OACTIVE;
        !           447:        csr &= IL_STATUS;
        !           448:        switch (is->is_lastcmd) {
        !           449: 
        !           450:        case ILC_XMIT:
        !           451:                is->is_if.if_opackets++;
        !           452:                if (csr > ILERR_RETRIES)
        !           453:                        is->is_if.if_oerrors++;
        !           454:                break;
        !           455: 
        !           456:        case ILC_STAT:
        !           457:                if (csr == ILERR_SUCCESS)
        !           458:                        iltotal(is);
        !           459:                break;
        !           460:        }
        !           461:        if (is->is_ifuba.ifu_xtofree) {
        !           462:                m_freem(is->is_ifuba.ifu_xtofree);
        !           463:                is->is_ifuba.ifu_xtofree = 0;
        !           464:        }
        !           465:        (void) ilstart(&is->is_if);
        !           466: }
        !           467: 
        !           468: /*
        !           469:  * Ethernet interface receiver interrupt.
        !           470:  * If input error just drop packet.
        !           471:  * Otherwise purge input buffered data path and examine 
        !           472:  * packet to determine type.  If can't determine length
        !           473:  * from type, then have to drop packet.  Othewise decapsulate
        !           474:  * packet based on type and pass to type specific higher-level
        !           475:  * input routine.
        !           476:  */
        !           477: ilrint(unit)
        !           478:        int unit;
        !           479: {
        !           480:        register struct il_softc *is = &il_softc[unit];
        !           481:        struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr;
        !           482:        register struct il_rheader *il;
        !           483:        struct mbuf *m;
        !           484:        int len, off, resid, s;
        !           485:        register struct ifqueue *inq;
        !           486: 
        !           487:        is->is_if.if_ipackets++;
        !           488:        if (is->is_ifuba.ifu_flags & UBA_NEEDBDP)
        !           489:                UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp);
        !           490:        il = (struct il_rheader *)(is->is_ifuba.ifu_r.ifrw_addr);
        !           491:        len = il->ilr_length - sizeof(struct il_rheader);
        !           492:        if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 ||
        !           493:            len > ETHERMTU) {
        !           494:                is->is_if.if_ierrors++;
        !           495: #ifdef notdef
        !           496:                if (is->is_if.if_ierrors % 100 == 0)
        !           497:                        printf("il%d: += 100 input errors\n", unit);
        !           498: #endif
        !           499:                goto setup;
        !           500:        }
        !           501: 
        !           502:        /*
        !           503:         * Deal with trailer protocol: if type is trailer type
        !           504:         * get true type from first 16-bit word past data.
        !           505:         * Remember that type was trailer by setting off.
        !           506:         */
        !           507:        il->ilr_type = ntohs((u_short)il->ilr_type);
        !           508: #define        ildataaddr(il, off, type)       ((type)(((caddr_t)((il)+1)+(off))))
        !           509:        if (il->ilr_type >= ETHERTYPE_TRAIL &&
        !           510:            il->ilr_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
        !           511:                off = (il->ilr_type - ETHERTYPE_TRAIL) * 512;
        !           512:                if (off >= ETHERMTU)
        !           513:                        goto setup;             /* sanity */
        !           514:                il->ilr_type = ntohs(*ildataaddr(il, off, u_short *));
        !           515:                resid = ntohs(*(ildataaddr(il, off+2, u_short *)));
        !           516:                if (off + resid > len)
        !           517:                        goto setup;             /* sanity */
        !           518:                len = off + resid;
        !           519:        } else
        !           520:                off = 0;
        !           521:        if (len == 0)
        !           522:                goto setup;
        !           523: 
        !           524:        /*
        !           525:         * Pull packet off interface.  Off is nonzero if packet
        !           526:         * has trailing header; ilget will then force this header
        !           527:         * information to be at the front, but we still have to drop
        !           528:         * the type and length which are at the front of any trailer data.
        !           529:         */
        !           530:        m = if_rubaget(&is->is_ifuba, len, off, &is->is_if);
        !           531:        if (m)
        !           532:                ether_input(&is->is_if, (struct ether_header *)il->ilr_dhost, m);
        !           533: setup:
        !           534:        /*
        !           535:         * Reset for next packet if possible.
        !           536:         * If waiting for transmit command completion, set flag
        !           537:         * and wait until command completes.
        !           538:         */
        !           539:        if (is->is_if.if_flags & IFF_OACTIVE) {
        !           540:                is->is_flags |= ILF_RCVPENDING;
        !           541:                return;
        !           542:        }
        !           543:        addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
        !           544:        addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
        !           545:        addr->il_csr =
        !           546:                ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
        !           547:        s = splhigh();
        !           548:        while ((addr->il_csr & IL_CDONE) == 0)
        !           549:                ;
        !           550:        splx(s);
        !           551: }
        !           552: /*
        !           553:  * Watchdog routine, request statistics from board.
        !           554:  */
        !           555: ilwatch(unit)
        !           556:        int unit;
        !           557: {
        !           558:        register struct il_softc *is = &il_softc[unit];
        !           559:        register struct ifnet *ifp = &is->is_if;
        !           560:        int s;
        !           561: 
        !           562:        if (is->is_flags & ILF_STATPENDING) {
        !           563:                ifp->if_timer = is->is_scaninterval;
        !           564:                return;
        !           565:        }
        !           566:        s = splimp();
        !           567:        is->is_flags |= ILF_STATPENDING;
        !           568:        if ((is->is_if.if_flags & IFF_OACTIVE) == 0)
        !           569:                (void) ilstart(ifp);
        !           570:        splx(s);
        !           571:        ifp->if_timer = is->is_scaninterval;
        !           572: }
        !           573: 
        !           574: /*
        !           575:  * Total up the on-board statistics.
        !           576:  */
        !           577: iltotal(is)
        !           578:        register struct il_softc *is;
        !           579: {
        !           580:        register u_short *interval, *sum, *end;
        !           581: 
        !           582:        interval = &is->is_stats.ils_frames;
        !           583:        sum = &is->is_sum.ils_frames;
        !           584:        end = is->is_sum.ils_fill2;
        !           585:        while (sum < end)
        !           586:                *sum++ += *interval++;
        !           587:        is->is_if.if_collisions = is->is_sum.ils_collis;
        !           588:        if ((is->is_flags & ILF_SETADDR) &&
        !           589:            (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
        !           590:                                        sizeof (is->is_addr)) != 0)) {
        !           591:                log(LOG_ERR, "il%d: physaddr reverted\n", is->is_if.if_unit);
        !           592:                is->is_flags &= ~ILF_RUNNING;
        !           593:                ilinit(is->is_if.if_unit);
        !           594:        }
        !           595: }
        !           596: 
        !           597: /*
        !           598:  * Process an ioctl request.
        !           599:  */
        !           600: ilioctl(ifp, cmd, data)
        !           601:        register struct ifnet *ifp;
        !           602:        int cmd;
        !           603:        caddr_t data;
        !           604: {
        !           605:        register struct ifaddr *ifa = (struct ifaddr *)data;
        !           606:        register struct il_softc *is = &il_softc[ifp->if_unit];
        !           607:        int s = splimp(), error = 0;
        !           608: 
        !           609:        switch (cmd) {
        !           610: 
        !           611:        case SIOCSIFADDR:
        !           612:                ifp->if_flags |= IFF_UP;
        !           613:                ilinit(ifp->if_unit);
        !           614: 
        !           615:                switch (ifa->ifa_addr->sa_family) {
        !           616: #ifdef INET
        !           617:                case AF_INET:
        !           618:                        ((struct arpcom *)ifp)->ac_ipaddr =
        !           619:                                IA_SIN(ifa)->sin_addr;
        !           620:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
        !           621:                        break;
        !           622: #endif
        !           623: #ifdef NS
        !           624:                case AF_NS:
        !           625:                    {
        !           626:                        register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
        !           627:                        
        !           628:                        if (ns_nullhost(*ina)) {
        !           629:                                ina->x_host = * (union ns_host *) 
        !           630:                                     (il_softc[ifp->if_unit].is_addr);
        !           631:                        } else {
        !           632:                                il_setaddr(ina->x_host.c_host, ifp->if_unit);
        !           633:                                return (0);
        !           634:                        }
        !           635:                        break;
        !           636:                    }
        !           637: #endif
        !           638:                }
        !           639:                break;
        !           640: 
        !           641:        case SIOCSIFFLAGS:
        !           642:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !           643:                    is->is_flags & ILF_RUNNING) {
        !           644:                        ((struct ildevice *)
        !           645:                           (ilinfo[ifp->if_unit]->ui_addr))->il_csr = ILC_RESET;
        !           646:                        is->is_flags &= ~ILF_RUNNING;
        !           647:                } else if (ifp->if_flags & IFF_UP &&
        !           648:                    (is->is_flags & ILF_RUNNING) == 0)
        !           649:                        ilinit(ifp->if_unit);
        !           650:                break;
        !           651: 
        !           652:        default:
        !           653:                error = EINVAL;
        !           654:        }
        !           655:        splx(s);
        !           656:        return (error);
        !           657: }
        !           658: 
        !           659: /*
        !           660:  * set ethernet address for unit
        !           661:  */
        !           662: il_setaddr(physaddr, unit)
        !           663: u_char *physaddr;
        !           664: int unit;
        !           665: {
        !           666:        register struct il_softc *is = &il_softc[unit];
        !           667:        
        !           668:        if (! (is->is_flags & ILF_RUNNING))
        !           669:                return;
        !           670:                
        !           671:        bcopy((caddr_t)physaddr, (caddr_t)is->is_addr, sizeof is->is_addr);
        !           672:        is->is_flags &= ~ILF_RUNNING;
        !           673:        is->is_flags |= ILF_SETADDR;
        !           674:        ilinit(unit);
        !           675: }
        !           676: #endif

unix.superglobalmegacorp.com

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