Annotation of 43BSDTahoe/sys/tahoeif/if_enp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1988 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that the above copyright notice and this paragraph are
                      7:  * duplicated in all such forms and that any documentation,
                      8:  * advertising materials, and other materials related to such
                      9:  * distribution and use acknowledge that the software was developed
                     10:  * by the University of California, Berkeley.  The name of the
                     11:  * University may not be used to endorse or promote products derived
                     12:  * from this software without specific prior written permission.
                     13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     15:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     16:  *
                     17:  *     @(#)if_enp.c    7.2 (Berkeley) 6/29/88
                     18:  */
                     19: 
                     20: #include "enp.h"
                     21: #if NENP > 0
                     22: /*
                     23:  * CMC ENP-20 Ethernet Controller.
                     24:  */
                     25: #include "param.h"
                     26: #include "systm.h"
                     27: #include "mbuf.h"
                     28: #include "buf.h"
                     29: #include "protosw.h"
                     30: #include "socket.h"
                     31: #include "vmmac.h"
                     32: #include "ioctl.h"
                     33: #include "errno.h"
                     34: #include "vmparam.h"
                     35: #include "syslog.h"
                     36: #include "uio.h"
                     37: 
                     38: #include "../net/if.h"
                     39: #include "../net/netisr.h"
                     40: #include "../net/route.h"
                     41: #ifdef INET
                     42: #include "../netinet/in.h"
                     43: #include "../netinet/in_systm.h"
                     44: #include "../netinet/in_var.h"
                     45: #include "../netinet/ip.h"
                     46: #include "../netinet/ip_var.h"
                     47: #include "../netinet/if_ether.h"
                     48: #endif
                     49: #ifdef NS
                     50: #include "../netns/ns.h"
                     51: #include "../netns/ns_if.h"
                     52: #endif
                     53: 
                     54: #include "../tahoe/cpu.h"
                     55: #include "../tahoe/pte.h"
                     56: #include "../tahoe/mtpr.h"
                     57: 
                     58: #include "../tahoevba/vbavar.h"
                     59: #include "../tahoeif/if_enpreg.h"
                     60: 
                     61: #define ENPSTART       0xf02000        /* standard enp start addr */
                     62: #define        ENPUNIT(dev)    (minor(dev))    /* for enp ram devices */
                     63: /* macros for dealing with longs in i/o space */
                     64: #define        ENPGETLONG(a)   ((((u_short *)(a))[0] << 16)|(((u_short *)(a))[1]))
                     65: #define        ENPSETLONG(a,v) \
                     66:    { register u_short *wp = (u_short *)(a); \
                     67:      wp[0] = ((u_short *)&(v))[0]; wp[1] = ((u_short *)&(v))[1];}
                     68: 
                     69: int    enpprobe(), enpattach(), enpintr();
                     70: long   enpstd[] = { 0xfff41000, 0xfff61000, 0 };
                     71: struct  vba_device *enpinfo[NENP];
                     72: struct  vba_driver enpdriver = 
                     73:     { enpprobe, 0, enpattach, 0, enpstd, "enp", enpinfo, "enp-20", 0 };
                     74: 
                     75: int    enpinit(), enpioctl(), enpreset(), enpoutput();
                     76: struct  mbuf *enpget();
                     77: 
                     78: /*
                     79:  * Ethernet software status per interface.
                     80:  *
                     81:  * Each interface is referenced by a network interface structure,
                     82:  * es_if, which the routing code uses to locate the interface.
                     83:  * This structure contains the output queue for the interface, its address, ...
                     84:  */
                     85: struct  enp_softc {
                     86:        struct  arpcom es_ac;           /* common ethernet structures */
                     87: #define es_if          es_ac.ac_if
                     88: #define es_addr        es_ac.ac_enaddr
                     89:        short   es_ivec;                /* interrupt vector */
                     90: } enp_softc[NENP]; 
                     91: extern struct ifnet loif;
                     92: 
                     93: enpprobe(reg, vi)
                     94:        caddr_t reg;
                     95:        struct vba_device *vi;
                     96: {
                     97:        register br, cvec;              /* must be r12, r11 */
                     98:        register struct enpdevice *addr = (struct enpdevice *)reg;
                     99:        struct enp_softc *es = &enp_softc[vi->ui_unit];
                    100: 
                    101: #ifdef lint
                    102:        br = 0; cvec = br; br = cvec;
                    103:        enpintr(0);
                    104: #endif
                    105:        if (badaddr((caddr_t)addr, 2) || badaddr((caddr_t)&addr->enp_ram[0], 2))
                    106:                return (0);
                    107:        es->es_ivec = --vi->ui_hd->vh_lastiv;
                    108:        addr->enp_state = S_ENPRESET;           /* reset by VERSAbus reset */
                    109:        br = 0x14, cvec = es->es_ivec;          /* XXX */
                    110:        return (sizeof (struct enpdevice));
                    111: }
                    112: 
                    113: /*
                    114:  * Interface exists: make available by filling in network interface
                    115:  * record.  System will initialize the interface when it is ready
                    116:  * to accept packets. 
                    117:  */
                    118: enpattach(ui)
                    119:        register struct vba_device *ui;
                    120: {
                    121:        struct enp_softc *es = &enp_softc[ui->ui_unit];
                    122:        register struct ifnet *ifp = &es->es_if;
                    123: 
                    124:        ifp->if_unit = ui->ui_unit;
                    125:        ifp->if_name = "enp";
                    126:        ifp->if_mtu = ETHERMTU;
                    127:        ifp->if_init = enpinit;
                    128:        ifp->if_ioctl = enpioctl;
                    129:        ifp->if_output = enpoutput;
                    130:        ifp->if_reset = enpreset;
                    131:        ifp->if_flags = IFF_BROADCAST;
                    132:        if_attach(ifp);
                    133: }
                    134: 
                    135: /*
                    136:  * Reset of interface after "system" reset.
                    137:  */
                    138: enpreset(unit, vban)
                    139:        int unit, vban;
                    140: {
                    141:        register struct vba_device *ui;
                    142: 
                    143:        if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 ||
                    144:            ui->ui_vbanum != vban)
                    145:                return;
                    146:        printf(" enp%d", unit);
                    147:        enpinit(unit);
                    148: }
                    149: 
                    150: /*
                    151:  * Initialization of interface; clear recorded pending operations.
                    152:  */
                    153: enpinit(unit)
                    154:        int unit;
                    155: {
                    156:        struct enp_softc *es = &enp_softc[unit];
                    157:        register struct vba_device *ui = enpinfo[unit];
                    158:        struct enpdevice *addr;
                    159:        register struct ifnet *ifp = &es->es_if;
                    160:        int s;
                    161: 
                    162:        if (ifp->if_addrlist == (struct ifaddr *)0)
                    163:                return;
                    164:        if ((ifp->if_flags & IFF_RUNNING) == 0) {
                    165:                addr = (struct enpdevice *)ui->ui_addr;
                    166:                s = splimp();
                    167:                RESET_ENP(addr);
                    168:                DELAY(200000);
                    169:                es->es_if.if_flags |= IFF_RUNNING;
                    170:                splx(s);
                    171:        }
                    172: }
                    173: 
                    174: /*
                    175:  * Ethernet interface interrupt.
                    176:  */
                    177: enpintr(unit)
                    178:        int unit;
                    179: {
                    180:        register struct enpdevice *addr;
                    181:        register BCB *bcbp;
                    182: 
                    183:        addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
                    184: #if ENP == 30
                    185:        if (!IS_ENP_INTR(addr))
                    186:                return;
                    187:        ACK_ENP_INTR(addr);
                    188: #endif
                    189:        while ((bcbp = (BCB *)ringget((RING *)&addr->enp_tohost )) != 0) {
                    190:                (void) enpread(&enp_softc[unit], bcbp);
                    191:                (void) ringput((RING *)&addr->enp_enpfree, bcbp); 
                    192:        }
                    193: }
                    194: 
                    195: /*
                    196:  * Read input packet, examine its packet type, and enqueue it.
                    197:  */
                    198: enpread(es, bcbp)
                    199:        struct enp_softc *es;
                    200:        register BCB *bcbp;
                    201: {
                    202:        register struct ether_header *enp;
                    203:        struct mbuf *m;
                    204:        int s, len, off, resid;
                    205:        register struct ifqueue *inq;
                    206: 
                    207:        es->es_if.if_ipackets++; 
                    208:        /*
                    209:         * Get input data length.
                    210:         * Get pointer to ethernet header (in input buffer).
                    211:         * Deal with trailer protocol: if type is PUP trailer
                    212:         * get true type from first 16-bit word past data.
                    213:         * Remember that type was trailer by setting off.
                    214:         */
                    215:        len = bcbp->b_msglen - sizeof (struct ether_header);
                    216:        enp = (struct ether_header *)ENPGETLONG(&bcbp->b_addr);
                    217: #define enpdataaddr(enp, off, type) \
                    218:     ((type)(((caddr_t)(((char *)enp)+sizeof (struct ether_header))+(off))))
                    219:        enp->ether_type = ntohs((u_short)enp->ether_type);
                    220:        if (enp->ether_type >= ETHERTYPE_TRAIL &&
                    221:            enp->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
                    222:                off = (enp->ether_type - ETHERTYPE_TRAIL) * 512;
                    223:                if (off >= ETHERMTU)
                    224:                        goto setup;
                    225:                enp->ether_type = ntohs(*enpdataaddr(enp, off, u_short *));
                    226:                resid = ntohs(*(enpdataaddr(enp, off+2, u_short *)));
                    227:                if (off + resid > len)
                    228:                        goto setup;
                    229:                len = off + resid;
                    230:        } else
                    231:                off = 0;
                    232:        if (len == 0)
                    233:                goto setup;
                    234: 
                    235:        /*
                    236:         * Pull packet off interface.  Off is nonzero if packet
                    237:         * has trailing header; enpget will then force this header
                    238:         * information to be at the front, but we still have to drop
                    239:         * the type and length which are at the front of any trailer data.
                    240:         */
                    241:        m = enpget((u_char *)enp, len, off, &es->es_if);
                    242:        if (m == 0)
                    243:                goto setup;
                    244:        if (off) {
                    245:                struct ifnet *ifp;
                    246: 
                    247:                ifp = *(mtod(m, struct ifnet **));
                    248:                m->m_off += 2 * sizeof (u_short);
                    249:                m->m_len -= 2 * sizeof (u_short);
                    250:                *(mtod(m, struct ifnet **)) = ifp;
                    251:        }
                    252:        switch (enp->ether_type) {
                    253: 
                    254: #ifdef INET
                    255:        case ETHERTYPE_IP:
                    256:                schednetisr(NETISR_IP);
                    257:                inq = &ipintrq;
                    258:                break;
                    259: #endif
                    260:        case ETHERTYPE_ARP:
                    261:                arpinput(&es->es_ac, m);
                    262:                goto setup;
                    263: 
                    264: #ifdef NS
                    265:        case ETHERTYPE_NS:
                    266:                schednetisr(NETISR_NS);
                    267:                inq = &nsintrq;
                    268:                break;
                    269: #endif
                    270:        default:
                    271:                m_freem(m);
                    272:                goto setup;
                    273:        }
                    274:        if (IF_QFULL(inq)) {
                    275:                IF_DROP(inq);
                    276:                m_freem(m);
                    277:                goto setup;
                    278:        }
                    279:        s = splimp();
                    280:        IF_ENQUEUE(inq, m);
                    281:        splx(s);
                    282: setup:
                    283:        return (0);
                    284: }
                    285: 
                    286: /*
                    287:  * Ethernet output routine. (called by user)
                    288:  * Encapsulate a packet of type family for the local net.
                    289:  * Use trailer local net encapsulation if enough data in first
                    290:  * packet leaves a multiple of 512 bytes of data in remainder.
                    291:  * If destination is this address or broadcast, send packet to
                    292:  * loop device to kludge around the fact that 3com interfaces can't
                    293:  * talk to themselves.
                    294:  */
                    295: enpoutput(ifp, m0, dst)
                    296:        struct ifnet *ifp;
                    297:        struct mbuf *m0;
                    298:        struct sockaddr *dst;
                    299: {
                    300:        register struct enp_softc *es = &enp_softc[ifp->if_unit];
                    301:        register struct mbuf *m = m0;
                    302:        register struct ether_header *enp;
                    303:        register int off;
                    304:        struct mbuf *mcopy = (struct mbuf *)0;
                    305:        int type, s, error, usetrailers;
                    306:        u_char edst[6];
                    307:        struct in_addr idst;
                    308: 
                    309:        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
                    310:                error = ENETDOWN;
                    311:                goto bad;
                    312:        }
                    313:        switch (dst->sa_family) {
                    314: #ifdef INET
                    315:        case AF_INET:
                    316:                idst = ((struct sockaddr_in *)dst)->sin_addr;
                    317:                if (!arpresolve(&es->es_ac, m, &idst, edst, &usetrailers))
                    318:                        return (0);     /* if not yet resolved */
                    319:                if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr,
                    320:                    sizeof (edst)))
                    321:                        mcopy = m_copy(m, 0, (int)M_COPYALL);
                    322:                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                    323:                if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
                    324:                    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
                    325:                        type = ETHERTYPE_TRAIL + (off>>9);
                    326:                        m->m_off -= 2 * sizeof (u_short);
                    327:                        m->m_len += 2 * sizeof (u_short);
                    328:                        *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
                    329:                        *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
                    330:                        goto gottrailertype;
                    331:                }
                    332:                type = ETHERTYPE_IP;
                    333:                off = 0;
                    334:                goto gottype;
                    335: #endif
                    336: #ifdef NS
                    337:        case AF_NS:
                    338:                bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
                    339:                    (caddr_t)edst, sizeof (edst));
                    340:                if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof (edst)))
                    341:                        mcopy = m_copy(m, 0, (int)M_COPYALL);
                    342:                else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost,
                    343:                    sizeof (edst)))
                    344:                        return (looutput(&loif, m, dst));
                    345:                type = ETHERTYPE_NS;
                    346:                off = 0;
                    347:                goto gottype;
                    348: #endif
                    349:        case AF_UNSPEC:
                    350:                enp = (struct ether_header *)dst->sa_data;
                    351:                bcopy((caddr_t)enp->ether_dhost, (caddr_t)edst, sizeof (edst));
                    352:                type = enp->ether_type;
                    353:                goto gottype;
                    354: 
                    355:        default:
                    356:                log(LOG_ERR, "enp%d: can't handle af%d\n",
                    357:                    ifp->if_unit, dst->sa_family);
                    358:                error = EAFNOSUPPORT;
                    359:                goto bad;
                    360:        }
                    361: 
                    362: gottrailertype:
                    363:        /*
                    364:         * Packet to be sent as trailer: move first packet
                    365:         * (control information) to end of chain.
                    366:         */
                    367:        while (m->m_next)
                    368:                m = m->m_next;
                    369:        m->m_next = m0;
                    370:        m = m0->m_next;
                    371:        m0->m_next = 0;
                    372:        m0 = m;
                    373: 
                    374: gottype:
                    375:        /*
                    376:          * Add local net header.  If no space in first mbuf,
                    377:          * allocate another.
                    378:          */
                    379:        if (m->m_off > MMAXOFF ||
                    380:            MMINOFF + sizeof (struct ether_header) > m->m_off) {
                    381:                m = m_get(M_DONTWAIT, MT_HEADER);
                    382:                if (m == 0) {
                    383:                        error = ENOBUFS;
                    384:                        goto bad;
                    385:                }
                    386:                m->m_next = m0;
                    387:                m->m_off = MMINOFF;
                    388:                m->m_len = sizeof (struct ether_header);
                    389:        } else {
                    390:                m->m_off -= sizeof (struct ether_header);
                    391:                m->m_len += sizeof (struct ether_header);
                    392:        }
                    393:        enp = mtod(m, struct ether_header *);
                    394:        bcopy((caddr_t)edst, (caddr_t)enp->ether_dhost, sizeof (edst));
                    395:        bcopy((caddr_t)es->es_addr, (caddr_t)enp->ether_shost,
                    396:            sizeof (es->es_addr));
                    397:        enp->ether_type = htons((u_short)type);
                    398: 
                    399:        /*
                    400:         * Queue message on interface if possible 
                    401:         */
                    402:        s = splimp();   
                    403:        if (enpput(ifp->if_unit, m)) {
                    404:                error = ENOBUFS;
                    405:                goto qfull;
                    406:        }
                    407:        splx(s);        
                    408:        es->es_if.if_opackets++; 
                    409:        return (mcopy ? looutput(&loif, mcopy, dst) : 0);
                    410: qfull:
                    411:        splx(s);        
                    412:        m0 = m;
                    413: bad:
                    414:        m_freem(m0);
                    415:        if (mcopy)
                    416:                m_freem(mcopy);
                    417:        return (error);
                    418: }
                    419: 
                    420: /*
                    421:  * Routine to copy from mbuf chain to transmitter buffer on the VERSAbus.
                    422:  */
                    423: enpput(unit, m)
                    424:        int unit;
                    425:        struct mbuf *m;
                    426: {
                    427:        register BCB *bcbp;
                    428:        register struct enpdevice *addr;
                    429:        register struct mbuf *mp;
                    430:        register u_char *bp;
                    431:        register u_int len;
                    432:        u_char *mcp;
                    433: 
                    434:        addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
                    435:        if (ringempty((RING *)&addr->enp_hostfree)) 
                    436:                return (1);     
                    437:        bcbp = (BCB *)ringget((RING *)&addr->enp_hostfree);
                    438:        bcbp->b_len = 0;
                    439:        bp = (u_char *)ENPGETLONG(&bcbp->b_addr);
                    440:        for (mp = m; mp; mp = mp->m_next) {
                    441:                len = mp->m_len;
                    442:                if (len == 0)
                    443:                        continue;
                    444:                mcp = mtod(mp, u_char *);
                    445:                enpcopy(mcp, bp, len);
                    446:                bp += len;
                    447:                bcbp->b_len += len;
                    448:        }
                    449:        bcbp->b_len = MAX(ETHERMIN+sizeof (struct ether_header), bcbp->b_len);
                    450:        bcbp->b_reserved = 0;
                    451:        if (ringput((RING *)&addr->enp_toenp, bcbp) == 1)
                    452:                INTR_ENP(addr);
                    453:        m_freem(m);
                    454:        return (0);
                    455: }
                    456: 
                    457: /*
                    458:  * Routine to copy from VERSAbus memory into mbufs.
                    459:  *
                    460:  * Warning: This makes the fairly safe assumption that
                    461:  * mbufs have even lengths.
                    462:  */
                    463: struct mbuf *
                    464: enpget(rxbuf, totlen, off0, ifp)
                    465:        u_char *rxbuf;
                    466:        int totlen, off0;
                    467:        struct ifnet *ifp;
                    468: {
                    469:        register u_char *cp, *mcp;
                    470:        register struct mbuf *m;
                    471:        struct mbuf *top = 0, **mp = &top;
                    472:        int len, off = off0;
                    473: 
                    474:        cp = rxbuf + sizeof (struct ether_header);
                    475:        while (totlen > 0) {
                    476:                MGET(m, M_DONTWAIT, MT_DATA);
                    477:                if (m == 0) 
                    478:                        goto bad;
                    479:                if (off) {
                    480:                        len = totlen - off;
                    481:                        cp = rxbuf + sizeof (struct ether_header) + off;
                    482:                } else
                    483:                        len = totlen;
                    484:                if (len >= NBPG) {
                    485:                        MCLGET(m);
                    486:                        if (m->m_len == CLBYTES)
                    487:                                m->m_len = len = MIN(len, CLBYTES);
                    488:                        else
                    489:                                m->m_len = len = MIN(MLEN, len);
                    490:                } else {
                    491:                        m->m_len = len = MIN(MLEN, len);
                    492:                        m->m_off = MMINOFF;
                    493:                }
                    494:                mcp = mtod(m, u_char *);
                    495:                if (ifp) {
                    496:                        /*
                    497:                         * Prepend interface pointer to first mbuf.
                    498:                         */
                    499:                        *(mtod(m, struct ifnet **)) = ifp;
                    500:                        mcp += sizeof (ifp);
                    501:                        len -= sizeof (ifp);
                    502:                        ifp = (struct ifnet *)0;
                    503:                }
                    504:                enpcopy(cp, mcp, (u_int)len);
                    505:                cp += len;
                    506:                *mp = m;
                    507:                mp = &m->m_next;
                    508:                if (off == 0) {
                    509:                        totlen -= len;
                    510:                        continue;
                    511:                }
                    512:                off += len;
                    513:                if (off == totlen) {
                    514:                        cp = rxbuf + sizeof (struct ether_header);
                    515:                        off = 0;
                    516:                        totlen = off0;
                    517:                }
                    518:        }
                    519:        return (top);
                    520: bad:
                    521:        m_freem(top);
                    522:        return (0);
                    523: }
                    524: 
                    525: enpcopy(from, to, cnt)
                    526:        register u_char *from, *to;
                    527:        register u_int cnt;
                    528: {
                    529:        register c;
                    530:        register short *f, *t;
                    531: 
                    532:        if (((int)from&01) && ((int)to&01)) {
                    533:                /* source & dest at odd addresses */
                    534:                *to++ = *from++;
                    535:                --cnt;
                    536:        }
                    537:        if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) {
                    538:                t = (short *)to;
                    539:                f = (short *)from;
                    540:                for (c = cnt>>1; c; --c)        /* even address copy */
                    541:                        *t++ = *f++;
                    542:                cnt &= 1;
                    543:                if (cnt) {                      /* odd len */
                    544:                        from = (u_char *)f;
                    545:                        to = (u_char *)t;
                    546:                        *to = *from;
                    547:                }
                    548:        }
                    549:        while ((int)cnt-- > 0)  /* one of the address(es) must be odd */
                    550:                *to++ = *from++;
                    551: }
                    552: 
                    553: /*
                    554:  * Process an ioctl request.
                    555:  */
                    556: enpioctl(ifp, cmd, data)
                    557:        register struct ifnet *ifp;
                    558:        int cmd;
                    559:        caddr_t data;
                    560: {
                    561:        register struct ifaddr *ifa = (struct ifaddr *)data;
                    562:        struct enpdevice *addr;
                    563:        int s = splimp(), error = 0;
                    564: 
                    565:        switch (cmd) {
                    566: 
                    567:        case SIOCSIFADDR:
                    568:                ifp->if_flags |= IFF_UP;
                    569:                switch (ifa->ifa_addr.sa_family) {
                    570: #ifdef INET
                    571:                case AF_INET:
                    572:                        enpinit(ifp->if_unit);
                    573:                        ((struct arpcom *)ifp)->ac_ipaddr =
                    574:                            IA_SIN(ifa)->sin_addr;
                    575:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
                    576:                        break;
                    577: #endif
                    578: #ifdef NS
                    579:                case AF_NS: {
                    580:                        struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
                    581:                        struct enp_softc *es = &enp_softc[ifp->if_unit];
                    582: 
                    583:                        if (!ns_nullhost(*ina)) {
                    584:                                ifp->if_flags &= ~IFF_RUNNING;
                    585:                                addr = (struct enpdevice *)
                    586:                                    enpinfo[ifp->if_unit]->ui_addr;
                    587:                                enpsetaddr(ifp->if_unit, addr,
                    588:                                    ina->x_host.c_host);
                    589:                        } else
                    590:                                ina->x_host = *(union ns_host *)es->es_addr;
                    591:                        enpinit(ifp->if_unit);
                    592:                        break;
                    593:                }
                    594: #endif
                    595:                default:
                    596:                        enpinit(ifp->if_unit);
                    597:                        break;
                    598:                }
                    599:                break;
                    600: 
                    601:        case SIOCSIFFLAGS:
                    602:                if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) {
                    603:                        enpinit(ifp->if_unit);          /* reset board */
                    604:                        ifp->if_flags &= ~IFF_RUNNING;
                    605:                } else if (ifp->if_flags&IFF_UP &&
                    606:                     (ifp->if_flags&IFF_RUNNING) == 0)
                    607:                        enpinit(ifp->if_unit);
                    608:                break;
                    609: 
                    610:        default:
                    611:                error = EINVAL;
                    612:        }
                    613:        splx(s);
                    614:        return (error);
                    615: }
                    616: 
                    617: enpsetaddr(unit, addr, enaddr)
                    618:        int unit;
                    619:        struct enpdevice *addr;
                    620:        u_char *enaddr;
                    621: {
                    622: 
                    623:        enpcopy(enaddr, addr->enp_addr.e_baseaddr.ea_addr,
                    624:            sizeof (struct ether_addr));
                    625:        enpinit(unit);
                    626:        enpgetaddr(unit, addr);
                    627: }
                    628: 
                    629: enpgetaddr(unit, addr)
                    630:        int unit;
                    631:        struct enpdevice *addr;
                    632: {
                    633:        struct enp_softc *es = &enp_softc[unit];
                    634: 
                    635:        enpcopy(addr->enp_addr.e_baseaddr.ea_addr, es->es_addr,
                    636:            sizeof (struct ether_addr));
                    637:        printf("enp%d: hardware address %s\n",
                    638:            unit, ether_sprintf(es->es_addr));
                    639: }
                    640: 
                    641: /* 
                    642:  * Routines to synchronize enp and host.
                    643:  */
                    644: #ifdef notdef
                    645: static
                    646: ringinit(rp, size)
                    647:        register RING *rp;
                    648: {
                    649: 
                    650:        rp->r_rdidx = rp->r_wrtidx = 0;
                    651:        rp->r_size = size;
                    652: }
                    653: 
                    654: static
                    655: ringfull(rp)
                    656:        register RING *rp;
                    657: {
                    658:        register short idx;
                    659: 
                    660:        idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
                    661:        return (idx == rp->r_rdidx);
                    662: }
                    663: 
                    664: static
                    665: fir(rp)
                    666:        register RING *rp;
                    667: {
                    668: 
                    669:        return (rp->r_rdidx != rp->r_wrtidx ? rp->r_slot[rp->r_rdidx] : 0);
                    670: }
                    671: #endif
                    672: 
                    673: static
                    674: ringempty(rp)
                    675:        register RING *rp;
                    676: {
                    677: 
                    678:        return (rp->r_rdidx == rp->r_wrtidx);
                    679: }
                    680: 
                    681: static
                    682: ringput(rp, v)
                    683:        register RING *rp;
                    684:        BCB *v;
                    685: {
                    686:        register int idx;
                    687: 
                    688:        idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
                    689:        if (idx != rp->r_rdidx) {
                    690:                ENPSETLONG(&rp->r_slot[rp->r_wrtidx], v);
                    691:                rp->r_wrtidx = idx;
                    692:                if ((idx -= rp->r_rdidx) < 0)
                    693:                        idx += rp->r_size;
                    694:                return (idx);                   /* num ring entries */
                    695:        }
                    696:        return (0);
                    697: }
                    698: 
                    699: static
                    700: ringget(rp)
                    701:        register RING *rp;
                    702: {
                    703:        register int i = 0;
                    704: 
                    705:        if (rp->r_rdidx != rp->r_wrtidx) {
                    706:                i = ENPGETLONG(&rp->r_slot[rp->r_rdidx]);
                    707:                rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1);
                    708:        }
                    709:        return (i);
                    710: }
                    711: 
                    712: /*
                    713:  * ENP Ram device.
                    714:  */
                    715: enpr_open(dev)
                    716:        dev_t dev;
                    717: {
                    718:        register int unit = ENPUNIT(dev);
                    719:        struct vba_device *ui;
                    720:        struct enpdevice *addr;
                    721: 
                    722:        if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 ||
                    723:            (addr = (struct enpdevice *)ui->ui_addr) == 0)
                    724:                return (ENODEV);
                    725:        if (addr->enp_state != S_ENPRESET)
                    726:                return (EACCES);  /* enp is not in reset state, don't open  */
                    727:        return (0);
                    728: }
                    729: 
                    730: /*ARGSUSED*/
                    731: enpr_close(dev)
                    732:        dev_t dev;
                    733: {
                    734: 
                    735:        return (0);
                    736: }
                    737: 
                    738: enpr_read(dev, uio)
                    739:        dev_t dev;
                    740:        register struct uio *uio;
                    741: {
                    742:        register struct iovec *iov;
                    743:        struct enpdevice *addr;
                    744: 
                    745:        if (uio->uio_offset > RAM_SIZE)
                    746:                return (ENODEV);
                    747:        iov = uio->uio_iov;
                    748:        if (uio->uio_offset + iov->iov_len > RAM_SIZE)
                    749:                iov->iov_len = RAM_SIZE - uio->uio_offset;
                    750:        addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr;
                    751:        if (useracc(iov->iov_base, (unsigned)iov->iov_len, 0) == 0)
                    752:                return (EFAULT);
                    753:        enpcopy((u_char *)&addr->enp_ram[uio->uio_offset],
                    754:            (u_char *)iov->iov_base, (u_int)iov->iov_len);
                    755:        uio->uio_resid -= iov->iov_len;
                    756:        iov->iov_len = 0;
                    757:        return (0);
                    758: }
                    759: 
                    760: enpr_write(dev, uio)
                    761:        dev_t dev;
                    762:        register struct uio *uio;
                    763: {
                    764:        register struct enpdevice *addr;
                    765:        register struct iovec *iov;
                    766: 
                    767:        addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr;
                    768:        iov = uio->uio_iov;
                    769:        if (uio->uio_offset > RAM_SIZE)
                    770:                return (ENODEV);
                    771:        if (uio->uio_offset + iov->iov_len > RAM_SIZE)
                    772:                iov->iov_len = RAM_SIZE - uio->uio_offset;
                    773:        if (useracc(iov->iov_base, (unsigned)iov->iov_len, 1) == 0)
                    774:                return (EFAULT);
                    775:        enpcopy((u_char *)iov->iov_base,
                    776:            (u_char *)&addr->enp_ram[uio->uio_offset], (u_int)iov->iov_len);
                    777:        uio->uio_resid -= iov->iov_len;
                    778:        iov->iov_len = 0;
                    779:        return (0);
                    780: }
                    781: 
                    782: /*ARGSUSED*/
                    783: enpr_ioctl(dev, cmd, data)
                    784:        dev_t dev;
                    785:        caddr_t data;
                    786: {
                    787:        register unit = ENPUNIT(dev);
                    788:        struct enpdevice *addr;
                    789: 
                    790:        addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
                    791:        switch(cmd) {
                    792: 
                    793:        case ENPIOGO:
                    794:                ENPSETLONG(&addr->enp_base, addr);
                    795:                addr->enp_intrvec = enp_softc[unit].es_ivec;
                    796:                ENP_GO(addr, ENPSTART);
                    797:                DELAY(200000);
                    798:                enpinit(unit);
                    799:                /*
                    800:                 * Fetch Ethernet address after link level
                    801:                 * is booted (firmware copies manufacturer's
                    802:                 * address from on-board ROM).
                    803:                 */
                    804:                enpgetaddr(unit, addr);
                    805:                addr->enp_state = S_ENPRUN;
                    806:                break;
                    807: 
                    808:        case ENPIORESET:
                    809:                RESET_ENP(addr);
                    810:                addr->enp_state = S_ENPRESET;
                    811:                DELAY(100000);
                    812:                break;
                    813:        default:
                    814:                return (EINVAL);
                    815:        }
                    816:        return (0);
                    817: }
                    818: #endif

unix.superglobalmegacorp.com

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