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

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

unix.superglobalmegacorp.com

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