Annotation of 42BSD/sys/vaxif/if_en.c, revision 1.1.1.1

1.1       root        1: /*     if_en.c 6.1     83/07/29        */
                      2: 
                      3: #include "en.h"
                      4: 
                      5: /*
                      6:  * Xerox prototype (3 Mb) Ethernet interface driver.
                      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/errno.h"
                     18: #include "../h/ioctl.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 "../netpup/pup.h"
                     28: #include "../netpup/ether.h"
                     29: 
                     30: #include "../vax/cpu.h"
                     31: #include "../vax/mtpr.h"
                     32: #include "../vaxif/if_en.h"
                     33: #include "../vaxif/if_enreg.h"
                     34: #include "../vaxif/if_uba.h"
                     35: #include "../vaxuba/ubareg.h"
                     36: #include "../vaxuba/ubavar.h"
                     37: 
                     38: #define        ENMTU   (1024+512)
                     39: #define        ENMRU   (1024+512+16)           /* 16 is enough to receive trailer */
                     40: 
                     41: int    enprobe(), enattach(), enrint(), enxint(), encollide();
                     42: struct uba_device *eninfo[NEN];
                     43: u_short enstd[] = { 0 };
                     44: struct uba_driver endriver =
                     45:        { enprobe, 0, enattach, 0, enstd, "en", eninfo };
                     46: #define        ENUNIT(x)       minor(x)
                     47: 
                     48: int    eninit(),enoutput(),enreset(),enioctl();
                     49: 
                     50: #ifdef notdef
                     51: /*
                     52:  * If you need to byte swap IP's in the system, define
                     53:  * this and do a SIOCSIFFLAGS at boot time.
                     54:  */
                     55: #define        ENF_SWABIPS     0x100
                     56: #endif
                     57: 
                     58: /*
                     59:  * Ethernet software status per interface.
                     60:  *
                     61:  * Each interface is referenced by a network interface structure,
                     62:  * es_if, which the routing code uses to locate the interface.
                     63:  * This structure contains the output queue for the interface, its address, ...
                     64:  * We also have, for each interface, a UBA interface structure, which
                     65:  * contains information about the UNIBUS resources held by the interface:
                     66:  * map registers, buffered data paths, etc.  Information is cached in this
                     67:  * structure for use by the if_uba.c routines in running the interface
                     68:  * efficiently.
                     69:  */
                     70: struct en_softc {
                     71:        struct  ifnet es_if;            /* network-visible interface */
                     72:        struct  ifuba es_ifuba;         /* UNIBUS resources */
                     73:        short   es_delay;               /* current output delay */
                     74:        short   es_mask;                /* mask for current output delay */
                     75:        short   es_lastx;               /* host last transmitted to */
                     76:        short   es_oactive;             /* is output active? */
                     77:        short   es_olen;                /* length of last output */
                     78: } en_softc[NEN];
                     79: 
                     80: /*
                     81:  * Do output DMA to determine interface presence and
                     82:  * interrupt vector.  DMA is too short to disturb other hosts.
                     83:  */
                     84: enprobe(reg)
                     85:        caddr_t reg;
                     86: {
                     87:        register int br, cvec;          /* r11, r10 value-result */
                     88:        register struct endevice *addr = (struct endevice *)reg;
                     89: 
                     90: #ifdef lint
                     91:        br = 0; cvec = br; br = cvec;
                     92:        enrint(0); enxint(0); encollide(0);
                     93: #endif
                     94:        addr->en_istat = 0;
                     95:        addr->en_owc = -1;
                     96:        addr->en_oba = 0;
                     97:        addr->en_ostat = EN_IEN|EN_GO;
                     98:        DELAY(100000);
                     99:        addr->en_ostat = 0;
                    100:        return (1);
                    101: }
                    102: 
                    103: /*
                    104:  * Interface exists: make available by filling in network interface
                    105:  * record.  System will initialize the interface when it is ready
                    106:  * to accept packets.
                    107:  */
                    108: enattach(ui)
                    109:        struct uba_device *ui;
                    110: {
                    111:        register struct en_softc *es = &en_softc[ui->ui_unit];
                    112: 
                    113:        es->es_if.if_unit = ui->ui_unit;
                    114:        es->es_if.if_name = "en";
                    115:        es->es_if.if_mtu = ENMTU;
                    116:        es->es_if.if_init = eninit;
                    117:        es->es_if.if_output = enoutput;
                    118:        es->es_if.if_ioctl = enioctl;
                    119:        es->es_if.if_reset = enreset;
                    120:        es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT;
                    121: #if defined(VAX750)
                    122:        /* don't chew up 750 bdp's */
                    123:        if (cpu == VAX_750 && ui->ui_unit > 0)
                    124:                es->es_ifuba.ifu_flags &= ~UBA_NEEDBDP;
                    125: #endif
                    126:        if_attach(&es->es_if);
                    127: }
                    128: 
                    129: /*
                    130:  * Reset of interface after UNIBUS reset.
                    131:  * If interface is on specified uba, reset its state.
                    132:  */
                    133: enreset(unit, uban)
                    134:        int unit, uban;
                    135: {
                    136:        register struct uba_device *ui;
                    137: 
                    138:        if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 ||
                    139:            ui->ui_ubanum != uban)
                    140:                return;
                    141:        printf(" en%d", unit);
                    142:        eninit(unit);
                    143: }
                    144: 
                    145: /*
                    146:  * Initialization of interface; clear recorded pending
                    147:  * operations, and reinitialize UNIBUS usage.
                    148:  */
                    149: eninit(unit)
                    150:        int unit;
                    151: {
                    152:        register struct en_softc *es = &en_softc[unit];
                    153:        register struct uba_device *ui = eninfo[unit];
                    154:        register struct endevice *addr;
                    155:        struct sockaddr_in *sin = (struct sockaddr_in *)&es->es_if.if_addr;
                    156:        int s;
                    157: 
                    158:        if (in_netof(sin->sin_addr) == 0)
                    159:                return;
                    160:        if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
                    161:            sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { 
                    162:                printf("en%d: can't initialize\n", unit);
                    163:                es->es_if.if_flags &= ~IFF_UP;
                    164:                return;
                    165:        }
                    166:        addr = (struct endevice *)ui->ui_addr;
                    167:        addr->en_istat = addr->en_ostat = 0;
                    168: 
                    169:        /*
                    170:         * Hang a receive and start any
                    171:         * pending writes by faking a transmit complete.
                    172:         */
                    173:        s = splimp();
                    174:        addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
                    175:        addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
                    176:        addr->en_istat = EN_IEN|EN_GO;
                    177:        es->es_oactive = 1;
                    178:        es->es_if.if_flags |= IFF_UP|IFF_RUNNING;
                    179:        enxint(unit);
                    180:        splx(s);
                    181:        if_rtinit(&es->es_if, RTF_UP);
                    182: }
                    183: 
                    184: int    enalldelay = 0;
                    185: int    enlastdel = 50;
                    186: int    enlastmask = (~0) << 5;
                    187: 
                    188: /*
                    189:  * Start or restart output on interface.
                    190:  * If interface is already active, then this is a retransmit
                    191:  * after a collision, and just restuff registers and delay.
                    192:  * If interface is not already active, get another datagram
                    193:  * to send off of the interface queue, and map it to the interface
                    194:  * before starting the output.
                    195:  */
                    196: enstart(dev)
                    197:        dev_t dev;
                    198: {
                    199:         int unit = ENUNIT(dev);
                    200:        struct uba_device *ui = eninfo[unit];
                    201:        register struct en_softc *es = &en_softc[unit];
                    202:        register struct endevice *addr;
                    203:        struct mbuf *m;
                    204:        int dest;
                    205: 
                    206:        if (es->es_oactive)
                    207:                goto restart;
                    208: 
                    209:        /*
                    210:         * Not already active: dequeue another request
                    211:         * and map it to the UNIBUS.  If no more requests,
                    212:         * just return.
                    213:         */
                    214:        IF_DEQUEUE(&es->es_if.if_snd, m);
                    215:        if (m == 0) {
                    216:                es->es_oactive = 0;
                    217:                return;
                    218:        }
                    219:        dest = mtod(m, struct en_header *)->en_dhost;
                    220:        es->es_olen = if_wubaput(&es->es_ifuba, m);
                    221: #ifdef ENF_SWABIPS
                    222:        /*
                    223:         * The Xerox interface does word at a time DMA, so
                    224:         * someone must do byte swapping of user data if high
                    225:         * and low ender machines are to communicate.  It doesn't
                    226:         * belong here, but certain people depend on it, so...
                    227:         *
                    228:         * Should swab everybody, but this is a kludge anyway.
                    229:         */
                    230:        if (es->es_if.if_flags & ENF_SWABIPS) {
                    231:                register struct en_header *en;
                    232: 
                    233:                en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr;
                    234:                if (en->en_type == ENTYPE_IP)
                    235:                        enswab((caddr_t)(en + 1), (caddr_t)(en + 1),
                    236:                            es->es_olen - sizeof (struct en_header) + 1);
                    237:        }
                    238: #endif
                    239: 
                    240:        /*
                    241:         * Ethernet cannot take back-to-back packets (no
                    242:         * buffering in interface.  To help avoid overrunning
                    243:         * receivers, enforce a small delay (about 1ms) in interface:
                    244:         *      * between all packets when enalldelay
                    245:         *      * whenever last packet was broadcast
                    246:         *      * whenever this packet is to same host as last packet
                    247:         */
                    248:        if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) {
                    249:                es->es_delay = enlastdel;
                    250:                es->es_mask = enlastmask;
                    251:        }
                    252:        es->es_lastx = dest;
                    253: 
                    254: restart:
                    255:        /*
                    256:         * Have request mapped to UNIBUS for transmission.
                    257:         * Purge any stale data from this BDP, and start the otput.
                    258:         */
                    259:        if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
                    260:                UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp);
                    261:        addr = (struct endevice *)ui->ui_addr;
                    262:        addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info;
                    263:        addr->en_odelay = es->es_delay;
                    264:        addr->en_owc = -((es->es_olen + 1) >> 1);
                    265:        addr->en_ostat = EN_IEN|EN_GO;
                    266:        es->es_oactive = 1;
                    267: }
                    268: 
                    269: /*
                    270:  * Ethernet interface transmitter interrupt.
                    271:  * Start another output if more data to send.
                    272:  */
                    273: enxint(unit)
                    274:        int unit;
                    275: {
                    276:        register struct uba_device *ui = eninfo[unit];
                    277:        register struct en_softc *es = &en_softc[unit];
                    278:        register struct endevice *addr = (struct endevice *)ui->ui_addr;
                    279: 
                    280:        if (es->es_oactive == 0)
                    281:                return;
                    282:        if (es->es_mask && (addr->en_ostat&EN_OERROR)) {
                    283:                es->es_if.if_oerrors++;
                    284:                endocoll(unit);
                    285:                return;
                    286:        }
                    287:        es->es_if.if_opackets++;
                    288:        es->es_oactive = 0;
                    289:        es->es_delay = 0;
                    290:        es->es_mask = ~0;
                    291:        if (es->es_ifuba.ifu_xtofree) {
                    292:                m_freem(es->es_ifuba.ifu_xtofree);
                    293:                es->es_ifuba.ifu_xtofree = 0;
                    294:        }
                    295:        if (es->es_if.if_snd.ifq_head == 0) {
                    296:                es->es_lastx = 256;             /* putatively illegal */
                    297:                return;
                    298:        }
                    299:        enstart(unit);
                    300: }
                    301: 
                    302: /*
                    303:  * Collision on ethernet interface.  Do exponential
                    304:  * backoff, and retransmit.  If have backed off all
                    305:  * the way print warning diagnostic, and drop packet.
                    306:  */
                    307: encollide(unit)
                    308:        int unit;
                    309: {
                    310:        struct en_softc *es = &en_softc[unit];
                    311: 
                    312:        es->es_if.if_collisions++;
                    313:        if (es->es_oactive == 0)
                    314:                return;
                    315:        endocoll(unit);
                    316: }
                    317: 
                    318: endocoll(unit)
                    319:        int unit;
                    320: {
                    321:        register struct en_softc *es = &en_softc[unit];
                    322: 
                    323:        /*
                    324:         * Es_mask is a 16 bit number with n low zero bits, with
                    325:         * n the number of backoffs.  When es_mask is 0 we have
                    326:         * backed off 16 times, and give up.
                    327:         */
                    328:        if (es->es_mask == 0) {
                    329:                printf("en%d: send error\n", unit);
                    330:                enxint(unit);
                    331:                return;
                    332:        }
                    333:        /*
                    334:         * Another backoff.  Restart with delay based on n low bits
                    335:         * of the interval timer.
                    336:         */
                    337:        es->es_mask <<= 1;
                    338:        es->es_delay = mfpr(ICR) &~ es->es_mask;
                    339:        enstart(unit);
                    340: }
                    341: 
                    342: #ifdef notdef
                    343: struct sockproto enproto = { AF_ETHERLINK };
                    344: struct sockaddr_en endst = { AF_ETHERLINK };
                    345: struct sockaddr_en ensrc = { AF_ETHERLINK };
                    346: #endif
                    347: /*
                    348:  * Ethernet interface receiver interrupt.
                    349:  * If input error just drop packet.
                    350:  * Otherwise purge input buffered data path and examine 
                    351:  * packet to determine type.  If can't determine length
                    352:  * from type, then have to drop packet.  Othewise decapsulate
                    353:  * packet based on type and pass to type specific higher-level
                    354:  * input routine.
                    355:  */
                    356: enrint(unit)
                    357:        int unit;
                    358: {
                    359:        register struct en_softc *es = &en_softc[unit];
                    360:        struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr;
                    361:        register struct en_header *en;
                    362:        struct mbuf *m;
                    363:        int len; short resid;
                    364:        register struct ifqueue *inq;
                    365:        int off;
                    366: 
                    367:        es->es_if.if_ipackets++;
                    368: 
                    369:        /*
                    370:         * Purge BDP; drop if input error indicated.
                    371:         */
                    372:        if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
                    373:                UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp);
                    374:        if (addr->en_istat&EN_IERROR) {
                    375:                es->es_if.if_ierrors++;
                    376:                goto setup;
                    377:        }
                    378: 
                    379:        /*
                    380:         * Calculate input data length.
                    381:         * Get pointer to ethernet header (in input buffer).
                    382:         * Deal with trailer protocol: if type is PUP trailer
                    383:         * get true type from first 16-bit word past data.
                    384:         * Remember that type was trailer by setting off.
                    385:         */
                    386:        resid = addr->en_iwc;
                    387:        if (resid)
                    388:                resid |= 0176000;
                    389:        len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1;
                    390:        len -= sizeof (struct en_header);
                    391:        if (len > ENMRU)
                    392:                goto setup;                     /* sanity */
                    393:        en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr);
                    394:        en->en_type = ntohs(en->en_type);
                    395: #define        endataaddr(en, off, type)       ((type)(((caddr_t)((en)+1)+(off))))
                    396:        if (en->en_type >= ENTYPE_TRAIL &&
                    397:            en->en_type < ENTYPE_TRAIL+ENTYPE_NTRAILER) {
                    398:                off = (en->en_type - ENTYPE_TRAIL) * 512;
                    399:                if (off > ENMTU)
                    400:                        goto setup;             /* sanity */
                    401:                en->en_type = ntohs(*endataaddr(en, off, u_short *));
                    402:                resid = ntohs(*(endataaddr(en, off+2, u_short *)));
                    403:                if (off + resid > len)
                    404:                        goto setup;             /* sanity */
                    405:                len = off + resid;
                    406:        } else
                    407:                off = 0;
                    408:        if (len == 0)
                    409:                goto setup;
                    410: #ifdef ENF_SWABIPS
                    411:        if (es->es_if.if_flags & ENF_SWABIPS && en->en_type == ENTYPE_IP)
                    412:                enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len);
                    413: #endif
                    414:        /*
                    415:         * Pull packet off interface.  Off is nonzero if packet
                    416:         * has trailing header; if_rubaget will then force this header
                    417:         * information to be at the front, but we still have to drop
                    418:         * the type and length which are at the front of any trailer data.
                    419:         */
                    420:        m = if_rubaget(&es->es_ifuba, len, off);
                    421:        if (m == 0)
                    422:                goto setup;
                    423:        if (off) {
                    424:                m->m_off += 2 * sizeof (u_short);
                    425:                m->m_len -= 2 * sizeof (u_short);
                    426:        }
                    427:        switch (en->en_type) {
                    428: 
                    429: #ifdef INET
                    430:        case ENTYPE_IP:
                    431:                schednetisr(NETISR_IP);
                    432:                inq = &ipintrq;
                    433:                break;
                    434: #endif
                    435: #ifdef PUP
                    436:        case ENTYPE_PUP:
                    437:                rpup_input(m);
                    438:                goto setup;
                    439: #endif
                    440:        default:
                    441: #ifdef notdef
                    442:                enproto.sp_protocol = en->en_type;
                    443:                endst.sen_host = en->en_dhost;
                    444:                endst.sen_net = ensrc.sen_net = es->es_if.if_net;
                    445:                ensrc.sen_host = en->en_shost;
                    446:                raw_input(m, &enproto,
                    447:                    (struct sockaddr *)&ensrc, (struct sockaddr *)&endst);
                    448: #else
                    449:                m_freem(m);
                    450: #endif
                    451:                goto setup;
                    452:        }
                    453: 
                    454:        if (IF_QFULL(inq)) {
                    455:                IF_DROP(inq);
                    456:                m_freem(m);
                    457:        } else
                    458:                IF_ENQUEUE(inq, m);
                    459: 
                    460: setup:
                    461:        /*
                    462:         * Reset for next packet.
                    463:         */
                    464:        addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
                    465:        addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
                    466:        addr->en_istat = EN_IEN|EN_GO;
                    467: }
                    468: 
                    469: /*
                    470:  * Ethernet output routine.
                    471:  * Encapsulate a packet of type family for the local net.
                    472:  * Use trailer local net encapsulation if enough data in first
                    473:  * packet leaves a multiple of 512 bytes of data in remainder.
                    474:  */
                    475: enoutput(ifp, m0, dst)
                    476:        struct ifnet *ifp;
                    477:        struct mbuf *m0;
                    478:        struct sockaddr *dst;
                    479: {
                    480:        int type, dest, s, error;
                    481:        register struct mbuf *m = m0;
                    482:        register struct en_header *en;
                    483:        register int off;
                    484: 
                    485:        switch (dst->sa_family) {
                    486: 
                    487: #ifdef INET
                    488:        case AF_INET:
                    489:                dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
                    490:                if (in_lnaof(*((struct in_addr *)&dest)) >= 0x100) {
                    491:                        error = EPERM;          /* ??? */
                    492:                        goto bad;
                    493:                }
                    494:                dest = (dest >> 24) & 0xff;
                    495:                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                    496:                /* need per host negotiation */
                    497:                if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
                    498:                if (off > 0 && (off & 0x1ff) == 0 &&
                    499:                    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
                    500:                        type = ENTYPE_TRAIL + (off>>9);
                    501:                        m->m_off -= 2 * sizeof (u_short);
                    502:                        m->m_len += 2 * sizeof (u_short);
                    503:                        *mtod(m, u_short *) = htons((u_short)ENTYPE_IP);
                    504:                        *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len);
                    505:                        goto gottrailertype;
                    506:                }
                    507:                type = ENTYPE_IP;
                    508:                off = 0;
                    509:                goto gottype;
                    510: #endif
                    511: #ifdef PUP
                    512:        case AF_PUP:
                    513:                dest = ((struct sockaddr_pup *)dst)->spup_host;
                    514:                type = ENTYPE_PUP;
                    515:                off = 0;
                    516:                goto gottype;
                    517: #endif
                    518: 
                    519: #ifdef notdef
                    520:        case AF_ETHERLINK:
                    521:                goto gotheader;
                    522: #endif
                    523: 
                    524:        default:
                    525:                printf("en%d: can't handle af%d\n", ifp->if_unit,
                    526:                        dst->sa_family);
                    527:                error = EAFNOSUPPORT;
                    528:                goto bad;
                    529:        }
                    530: 
                    531: gottrailertype:
                    532:        /*
                    533:         * Packet to be sent as trailer: move first packet
                    534:         * (control information) to end of chain.
                    535:         */
                    536:        while (m->m_next)
                    537:                m = m->m_next;
                    538:        m->m_next = m0;
                    539:        m = m0->m_next;
                    540:        m0->m_next = 0;
                    541:        m0 = m;
                    542: 
                    543: gottype:
                    544:        /*
                    545:         * Add local net header.  If no space in first mbuf,
                    546:         * allocate another.
                    547:         */
                    548:        if (m->m_off > MMAXOFF ||
                    549:            MMINOFF + sizeof (struct en_header) > m->m_off) {
                    550:                m = m_get(M_DONTWAIT, MT_HEADER);
                    551:                if (m == 0) {
                    552:                        error = ENOBUFS;
                    553:                        goto bad;
                    554:                }
                    555:                m->m_next = m0;
                    556:                m->m_off = MMINOFF;
                    557:                m->m_len = sizeof (struct en_header);
                    558:        } else {
                    559:                m->m_off -= sizeof (struct en_header);
                    560:                m->m_len += sizeof (struct en_header);
                    561:        }
                    562:        en = mtod(m, struct en_header *);
                    563:        en->en_shost = ifp->if_host[0];
                    564:        en->en_dhost = dest;
                    565:        en->en_type = htons((u_short)type);
                    566: 
                    567: gotheader:
                    568:        /*
                    569:         * Queue message on interface, and start output if interface
                    570:         * not yet active.
                    571:         */
                    572:        s = splimp();
                    573:        if (IF_QFULL(&ifp->if_snd)) {
                    574:                IF_DROP(&ifp->if_snd);
                    575:                error = ENOBUFS;
                    576:                goto qfull;
                    577:        }
                    578:        IF_ENQUEUE(&ifp->if_snd, m);
                    579:        if (en_softc[ifp->if_unit].es_oactive == 0)
                    580:                enstart(ifp->if_unit);
                    581:        splx(s);
                    582:        return (0);
                    583: qfull:
                    584:        m0 = m;
                    585:        splx(s);
                    586: bad:
                    587:        m_freem(m0);
                    588:        return (error);
                    589: }
                    590: 
                    591: /*
                    592:  * Process an ioctl request.
                    593:  */
                    594: enioctl(ifp, cmd, data)
                    595:        register struct ifnet *ifp;
                    596:        int cmd;
                    597:        caddr_t data;
                    598: {
                    599:        struct ifreq *ifr = (struct ifreq *)data;
                    600:        int s = splimp(), error = 0;
                    601: 
                    602:        switch (cmd) {
                    603: 
                    604:        case SIOCSIFADDR:
                    605:                if (ifp->if_flags & IFF_RUNNING)
                    606:                        if_rtinit(ifp, -1);     /* delete previous route */
                    607:                ensetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
                    608:                if (ifp->if_flags & IFF_RUNNING)
                    609:                        if_rtinit(ifp, RTF_UP);
                    610:                else
                    611:                        eninit(ifp->if_unit);
                    612:                break;
                    613: 
                    614:        default:
                    615:                error = EINVAL;
                    616:        }
                    617:        splx(s);
                    618:        return (error);
                    619: }
                    620: 
                    621: ensetaddr(ifp, sin)
                    622:        register struct ifnet *ifp;
                    623:        register struct sockaddr_in *sin;
                    624: {
                    625:        struct endevice *enaddr;
                    626: 
                    627:        ifp->if_net = in_netof(sin->sin_addr);
                    628:        enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr;
                    629:        ifp->if_host[0] = (~enaddr->en_addr) & 0xff;
                    630:        sin = (struct sockaddr_in *)&ifp->if_addr;
                    631:        sin->sin_family = AF_INET;
                    632:        sin->sin_addr = if_makeaddr(ifp->if_net, ifp->if_host[0]);
                    633:        sin = (struct sockaddr_in *)&ifp->if_broadaddr;
                    634:        sin->sin_family = AF_INET;
                    635:        sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
                    636:        ifp->if_flags |= IFF_BROADCAST;
                    637: }
                    638: 
                    639: #ifdef ENF_SWABIPS
                    640: /*
                    641:  * Swab bytes
                    642:  * Jeffrey Mogul, Stanford
                    643:  */
                    644: enswab(from, to, n)
                    645:        register caddr_t *from, *to;
                    646:        register int n;
                    647: {
                    648:        register unsigned long temp;
                    649:        
                    650:        n >>= 1; n++;
                    651: #define        STEP    temp = *from++,*to++ = *from++,*to++ = temp
                    652:        /* round to multiple of 8 */
                    653:        while ((--n) & 07)
                    654:                STEP;
                    655:        n >>= 3;
                    656:        while (--n >= 0) {
                    657:                STEP; STEP; STEP; STEP;
                    658:                STEP; STEP; STEP; STEP;
                    659:        }
                    660: }
                    661: #endif

unix.superglobalmegacorp.com

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