Annotation of cci/sys/tahoeif/if_enp.c, revision 1.1

1.1     ! root        1: #include "enp.h"
        !             2: #define ENPBPTE 128
        !             3: #if NENP > 0
        !             4: 
        !             5: /*
        !             6:  * Modified 3 Com Ethernet Controller interface
        !             7:  * enp modifications added S. F. Holmgren
        !             8:  */
        !             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/time.h"
        !            19: #include "../h/kernel.h"
        !            20: #include "../h/uio.h"
        !            21: #include "../net/if.h"
        !            22: #include "../net/netisr.h"
        !            23: #include "../net/route.h"
        !            24: #include "../netinet/in.h"
        !            25: #include "../h/ioctl.h"
        !            26: 
        !            27: #include "../netinet/in_systm.h"
        !            28: #include "../netinet/ip.h"
        !            29: #include "../netinet/ip_var.h"
        !            30: #include "../netinet/if_ether.h"
        !            31: #include "../netpup/pup.h"
        !            32: #include "../vba/vbavar.h"
        !            33: #include "../tahoeif/if_enp.h"
        !            34: #include "../machine/mtpr.h"
        !            35: #include "../tahoeif/if_debug.h"
        !            36: 
        !            37: #define ENP0_PHYSADDR  0xf40000        /* board # 0 physical base addr */
        !            38: #define ENP1_PHYSADDR  0xf60000        /* board # 1 physical base addr */
        !            39: #define ENPSTART       0xf02000        /* standard enp start addr      */
        !            40: 
        !            41: int    enpprobe(), enpattach(), enpintr();
        !            42: extern nulldev();
        !            43: caddr_t        vtoph();
        !            44: struct  mbuf *m_tofree();
        !            45: struct  vba_device *enpinfo[ NENP ];
        !            46: 
        !            47: /*     Maximun 2 controllers per system supported                      */
        !            48: 
        !            49: long  enpstd[] = { ENP0_PHYSADDR+0x1000,ENP1_PHYSADDR+0x1000, 0 };
        !            50: extern char    enp0utl[], enp1utl[];   /* enp accessible ram map       */
        !            51: char   *enpmap[]= { enp0utl, enp1utl };
        !            52: extern long    ENP0map[], ENP1map[];
        !            53: long   *ENPmap[] = {ENP0map, ENP1map};
        !            54: long   ENPmapa[] = {0xfff41000, 0xfff61000};
        !            55: long   enpismapped[NENP];
        !            56: 
        !            57: unsigned short intvec[4] = 
        !            58:        { 0xc1, 0xc2, 0xc3, 0xc4 };     /* intrvec of upto 4 enps       */
        !            59: 
        !            60: struct  vba_driver enpdriver = 
        !            61: {
        !            62: /* use of prom based version 
        !            63:        enpprobe, 0, enpattach, 0, 0,   enpintr,
        !            64: */
        !            65:        enpprobe, 0, nulldev, 0, 
        !            66:        enpstd,   "enp", enpinfo, "ENP 20", 0
        !            67: };
        !            68: 
        !            69: int     enpinit(),
        !            70:        enpioctl(),
        !            71:        enpoutput(),
        !            72:        enpreset(),
        !            73:        enpbroadcast(),
        !            74:        enptimeout();
        !            75: 
        !            76: int    enpcopy();
        !            77: 
        !            78: struct  mbuf *enpget();
        !            79: 
        !            80: extern  struct ifnet loif;
        !            81: 
        !            82: /*
        !            83:  * Ethernet software status per interface.
        !            84:  *
        !            85:  * Each interface is referenced by a network interface structure,
        !            86:  * es_if, which the routing code uses to locate the interface.
        !            87:  * This structure contains the output queue for the interface, its address, ...
        !            88:  */
        !            89: 
        !            90: struct         enp_softc       enp_softc[NENP];
        !            91: long   stat_addr[NENP];        /* enp statistic addr (for nstat use) */
        !            92: long   ring_addr[NENP];        /* enp dev ring addresses (for nstat use) */
        !            93: int    numenp = NENP;
        !            94: int    enp_intr = 0,           /* no. of enp_to_host interrupts */
        !            95:        host_intr = 0;          /* no. of host_to_enp interrupts */
        !            96: short  enpram[NENP];           /* open/close flags for enp devices */
        !            97: /*     Debugging tools, used to trace input packets */
        !            98: extern         int     printerror;     /* error print flag, from if_ace.c */
        !            99: int    save_enp_inpkt = 0;
        !           100: #define        ENPTRACE(X)     if (save_enp_inpkt) X;
        !           101: 
        !           102: struct         inp_err         enperr[NENP];
        !           103: 
        !           104: /*
        !           105:  * Probe for device.
        !           106:  */
        !           107: 
        !           108: enpprobe(reg)
        !           109: caddr_t reg;
        !           110: {
        !           111:        static  int     unit=0;
        !           112:        register ENPDEVICE      *addr = (ENPDEVICE *)reg;
        !           113: 
        !           114:        if( (badaddr( addr, 2 ) ) || (badaddr( &addr->enp_ram[0], 2 ) ) )
        !           115:                return( 0 );
        !           116:        addr->enp_state = S_ENPRESET; /* controller is reset by vbus reset */
        !           117:        /* save address of statistic area for nstat uses        */
        !           118: 
        !           119:        stat_addr[unit] = (long) &(addr->enp_stat); 
        !           120:        ring_addr[unit++] = (long) &(addr->enp_toenp); 
        !           121: 
        !           122:        return( ENPSIZE );
        !           123: }
        !           124: 
        !           125: /*
        !           126:  * Interface exists: make available by filling in network interface
        !           127:  * record.  System will initialize the interface when it is ready
        !           128:  * to accept packets. 
        !           129:  */
        !           130: 
        !           131: enpattach( md )
        !           132: register struct vba_device *md;
        !           133: {
        !           134:        struct enp_softc        *es = &enp_softc[md->ui_unit];
        !           135:        register struct ifnet   *ifp = &es->es_if;
        !           136:        register ENPDEVICE      *addr = (ENPDEVICE *)md->ui_addr;
        !           137:        struct sockaddr_in      *sin;
        !           138: 
        !           139:        enpgetaddr( md->ui_unit );
        !           140: 
        !           141:        ifp->if_unit = md->ui_unit;
        !           142:        ifp->if_name = "enp";
        !           143:        ifp->if_mtu = ETHERMTU;
        !           144: 
        !           145: /*     bcopy(&es->es_boardaddr, es->es_enaddr, sizeof(es->es_enaddr)); */
        !           146: 
        !           147:        sin = (struct sockaddr_in *)&es->es_if.if_addr;
        !           148:        sin->sin_family = AF_INET;
        !           149: 
        !           150:        ifp->if_init = enpinit;
        !           151:        ifp->if_ioctl = enpioctl;
        !           152:        ifp->if_output = enpoutput;
        !           153:        ifp->if_reset = enpreset;
        !           154:        if_attach(ifp);
        !           155: }
        !           156: 
        !           157: 
        !           158: /*
        !           159:  * Reset of interface after UNIBUS reset.
        !           160:  */
        !           161: enpreset(unit)
        !           162: int unit;
        !           163: {
        !           164:        register struct vba_device *md;
        !           165: 
        !           166:        if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0)
        !           167:                return(ENODEV);
        !           168: 
        !           169:        enpinit(unit);
        !           170: }
        !           171: 
        !           172: /*
        !           173:  * Initialization of interface; clear recorded pending
        !           174:  * operations.
        !           175:  */
        !           176: 
        !           177: enpinit( unit )
        !           178: int unit;
        !           179: {
        !           180:        struct enp_softc        *es = &enp_softc[unit];
        !           181:        ENPDEVICE               *addr;
        !           182:        int i, s;
        !           183:        u_char *cp, *ap;
        !           184:        register struct ifnet   *ifp = &es->es_if;
        !           185:        register struct sockaddr_in *sin, *sinb;
        !           186: 
        !           187:        sin = (struct sockaddr_in *)&ifp->if_addr;
        !           188: 
        !           189:        if ( !enpismapped[unit] ) {
        !           190:                ioaccess(ENPmap[unit],ENPmapa[unit],ENPBPTE);
        !           191:                ++enpismapped[unit];
        !           192:        }
        !           193:        if ((addr = (ENPDEVICE *)enpinfo[unit]->ui_addr) == (ENPDEVICE *)0)
        !           194:                return(ENODEV);
        !           195:        s = splimp();
        !           196:        RESET_ENP( addr );
        !           197:        DELAY( 200000 );
        !           198: 
        !           199: #ifdef notdef
        !           200: /* only needed if not downloading ( ie, ROM-resident ENP code) */
        !           201:        addr->enp_intrvec = intvec[unit];
        !           202:        ENP_GO( addr,ENPSTART );
        !           203:        DELAY( 200000 );
        !           204: /* end of ROM-resident */
        !           205: #endif notdef
        !           206: 
        !           207:        es->es_if.if_flags |= IFF_UP|IFF_RUNNING; /* open for business*/
        !           208:        splx(s);
        !           209: 
        !           210:        if_rtinit( &es->es_if,RTF_UP );
        !           211:        arpwhohas(&es->es_ac, &sin->sin_addr);
        !           212: }
        !           213: 
        !           214: 
        !           215: /*
        !           216:  * Ethernet interface interrupt.
        !           217:  */
        !           218: 
        !           219: enpintr( unit )
        !           220: {
        !           221:        register ENPDEVICE              *addr;
        !           222:        register BCB                    *bcbp;
        !           223:        register struct vba_device       *md;
        !           224: 
        !           225:        enp_intr++;
        !           226: 
        !           227:        if (unit >= NENP || (md = enpinfo[unit]) == 0)
        !           228:                return;
        !           229: 
        !           230:        addr = (ENPDEVICE *)md->ui_addr;
        !           231: 
        !           232:        if( IS_ENP_INTR(addr) == 0 )
        !           233:                return;
        !           234: 
        !           235:        ACK_ENP_INTR( addr );
        !           236: 
        !           237:        while( (bcbp = (BCB *)ringget( &addr->enp_tohost )) != 0 )
        !           238:        {
        !           239:                enpread( &enp_softc[ unit ],bcbp, unit );
        !           240:                ringput( &addr->enp_enpfree,bcbp ); 
        !           241:        }
        !           242:        return(0);
        !           243: }
        !           244: 
        !           245: #define        MAXBLEN 1500
        !           246: char   errpkt[MAXBLEN];
        !           247: int    bufptr = 0;
        !           248: int    maxl_tosave = 200;              /* save only the first 200 bytes */
        !           249: 
        !           250: saverrpkt(errbuf, errtype, len)
        !           251: register u_char *errbuf;
        !           252: int errtype, len;
        !           253: {
        !           254:        int remain, newptr;
        !           255: 
        !           256:        remain = MAXBLEN - bufptr;
        !           257:        if (remain < 50)                /* if too small                 */
        !           258:                return;                 /* no space avail               */
        !           259:        len = (len > maxl_tosave || len <= 0) ? maxl_tosave : len;
        !           260:        len = len > remain ? (remain - 2*sizeof(len)): len;
        !           261:        newptr = bufptr + len + 2*sizeof(len);
        !           262:        if (newptr <= MAXBLEN) {
        !           263:                enpcopy((char *)&len, &errpkt[bufptr], sizeof(len));
        !           264:                enpcopy((char *)&errtype, &errpkt[bufptr+sizeof(len)],
        !           265:                        sizeof(errtype));
        !           266:                enpcopy(errbuf, &errpkt[bufptr+(2*sizeof(len))], len);
        !           267:        }
        !           268:        bufptr = newptr;
        !           269: }
        !           270: 
        !           271: /*
        !           272:  * Read input packet, examine its packet type, and enqueue it.
        !           273:  */
        !           274: 
        !           275: enpread( es, bcbp, unit )
        !           276: struct enp_softc *es;
        !           277: register BCB *bcbp;
        !           278: int    unit;
        !           279: {
        !           280:        register struct ether_header *enp;
        !           281:        struct mbuf *m;
        !           282:        long int  s, v;
        !           283:        register short *vp = (short *)&v,
        !           284:                        *sp;
        !           285:        int len, off, resid, enptype;
        !           286:        register struct ifqueue *inq;
        !           287: 
        !           288:        es->es_if.if_ipackets++; 
        !           289: 
        !           290:        /*
        !           291:         * Get input data length.
        !           292:         * Get pointer to ethernet header (in input buffer).
        !           293:         * Deal with trailer protocol: if type is PUP trailer
        !           294:         * get true type from first 16-bit word past data.
        !           295:         * Remember that type was trailer by setting off.
        !           296:         */
        !           297: 
        !           298:        len = bcbp->b_msglen - SIZEOF_ETHEADER;
        !           299: #ifdef TAHOE
        !           300:        sp = (short *)&bcbp->b_addr;
        !           301:        *vp = *sp; vp[1] = sp[1];
        !           302:        enp = (struct ether_header *) v;
        !           303: #else
        !           304:        enp = (struct ether_header *)bcbp->b_addr;
        !           305: #endif TAHOE
        !           306: 
        !           307: #define enpdataaddr(enp, off, type) ((type)(((caddr_t)(((char *)enp)+SIZEOF_ETHEADER)+(off))))
        !           308: 
        !           309:        enptype = enp->ether_type;
        !           310:        if (enptype >= ETHERPUP_TRAIL && enptype < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) 
        !           311:        {
        !           312:                off = (enptype - ETHERPUP_TRAIL) * 512;
        !           313:                if (off >= ETHERMTU) {
        !           314:                        enperr[unit].bad_offset++;
        !           315:                        ENPTRACE(saverrpkt((char *)enp, B_OFFSET, bcbp->b_msglen)); 
        !           316: 
        !           317:                        goto badinput;
        !           318:                }
        !           319:                enptype = *enpdataaddr(enp, off, u_short *);
        !           320:                resid = *(enpdataaddr(enp, off+2, u_short *));
        !           321: 
        !           322:                if (off + resid > len) {
        !           323:                        enperr[unit].bad_length++;
        !           324:                        ENPTRACE(saverrpkt((char *)enp, B_LENGTH, bcbp->b_msglen)); 
        !           325:                        goto badinput;
        !           326:                }
        !           327:                len = off + resid;
        !           328:        } 
        !           329:        else
        !           330:                off = 0;
        !           331: 
        !           332:        if( len == 0 ) {
        !           333:                enperr[unit].bad_length++;
        !           334:                ENPTRACE(saverrpkt((char *)enp, B_LENGTH, bcbp->b_msglen)); 
        !           335:                goto badinput;
        !           336:        }
        !           337:        /*
        !           338:         * Pull packet off interface.  Off is nonzero if packet
        !           339:         * has trailing header; enpget will then force this header
        !           340:         * information to be at the front, but we still have to drop
        !           341:         * the type and length which are at the front of any trailer data.
        !           342:         */
        !           343: 
        !           344:        m = enpget(bcbp, len, off);
        !           345:        if( m == 0 )  {
        !           346:                enperr[unit].h_nobuffer++; /* host runs out of buf */
        !           347:                goto badinput;
        !           348:        }
        !           349:        if( off )
        !           350:        {
        !           351:                m->m_off += 2 * sizeof (u_short);
        !           352:                m->m_len -= 2 * sizeof (u_short);
        !           353:        }
        !           354: 
        !           355:        switch (enptype) 
        !           356:        {
        !           357: #ifdef INET
        !           358:        case ETHERPUP_IPTYPE:
        !           359: #ifdef notdef
        !           360:                arpipin(enp, m);
        !           361: #endif notdef
        !           362:                schednetisr(NETISR_IP);
        !           363:                inq = &ipintrq;
        !           364:                break;
        !           365: 
        !           366:        case ETHERPUP_ARPTYPE:
        !           367:                arpinput(&es->es_ac, m);
        !           368:                return(0);
        !           369: #endif
        !           370:        default:        /* unrecognized ethernet header */
        !           371:                enperr[unit].bad_packetype++;
        !           372:                if (printerror) { 
        !           373:                        printf("\nenp%d: Undefined packet type 0x%x ", unit,
        !           374:                                enp->ether_type);
        !           375:                        printf("from host: %x.%x.%x.%x.%x.%x\n", 
        !           376:                                enp->ether_shost[0], enp->ether_shost[1], 
        !           377:                                enp->ether_shost[2], enp->ether_shost[3],
        !           378:                                enp->ether_shost[4], enp->ether_shost[5]);
        !           379:                }       /* end debugging aid    */
        !           380:                ENPTRACE(saverrpkt((char *)enp, B_PACKETYPE, bcbp->b_msglen)); 
        !           381:                m_freem(m);
        !           382:                goto badinput;
        !           383:        }
        !           384: 
        !           385:        if (IF_QFULL(inq)) 
        !           386:        {
        !           387:                enperr[unit].inq_full++;
        !           388:                IF_DROP(inq);
        !           389:                m_freem(m);
        !           390:                return(0);
        !           391:        }
        !           392:        s = splimp();
        !           393:        IF_ENQUEUE(inq, m);
        !           394:        splx(s);
        !           395: badinput:
        !           396:        return(0);         /* sanity */
        !           397: }
        !           398: 
        !           399: /*
        !           400:  * Ethernet output routine. (called by user)
        !           401:  * Encapsulate a packet of type family for the local net.
        !           402:  * Use trailer local net encapsulation if enough data in first
        !           403:  * packet leaves a multiple of 512 bytes of data in remainder.
        !           404:  * If destination is this address or broadcast, send packet to
        !           405:  * loop device to kludge around the fact that 3com interfaces can't
        !           406:  * talk to themselves.
        !           407:  */
        !           408: 
        !           409: enpoutput(ifp, m0, dst)
        !           410: struct ifnet *ifp;
        !           411: struct mbuf *m0;
        !           412: struct sockaddr *dst;
        !           413: {
        !           414:        int type, s, error;
        !           415:        struct ether_addr edst;
        !           416:        struct in_addr idst;
        !           417: 
        !           418:        register struct enp_softc *es = &enp_softc[ifp->if_unit];
        !           419:        register struct mbuf *m = m0;
        !           420:        register struct ether_header *enp;
        !           421:        register int off, i;
        !           422: 
        !           423:        struct mbuf *mcopy = (struct mbuf *) 0;         /* Null */
        !           424:        int unit = ifp->if_unit;
        !           425: 
        !           426:        switch( dst->sa_family )
        !           427:        {
        !           428: #ifdef INET
        !           429:        case AF_INET:
        !           430:                idst = ((struct sockaddr_in *)dst)->sin_addr;
        !           431: 
        !           432:                /* translate internet to ethernet address */
        !           433: 
        !           434:                switch(arpresolve(&es->es_ac, m, &idst, &edst)) {
        !           435: 
        !           436:                        case ARPRESOLVE_WILLSEND:
        !           437:                                return (0);     /* if not yet resolved */
        !           438:                        case ARPRESOLVE_BROADCAST:
        !           439:                                mcopy = m_copy(m, 0, (int)M_COPYALL);
        !           440:                                if (mcopy)
        !           441:                                        looutput(&loif, mcopy, dst);
        !           442: 
        !           443:                                /* falls through ... */
        !           444:                        case ARPRESOLVE_OK:
        !           445:                                break;
        !           446:                }
        !           447:                off = ((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
        !           448:                if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
        !           449:                        if (off > 0 && (off & 0x1ff) == 0 &&
        !           450:                            m->m_off >= MMINOFF + 2 * sizeof (u_short)) 
        !           451:                        {
        !           452:                                type = ETHERPUP_TRAIL + (off>>9);
        !           453:                                m->m_off -= 2 * sizeof (u_short);
        !           454:                                m->m_len += 2 * sizeof (u_short);
        !           455:                                *mtod(m, u_short *) = ETHERPUP_IPTYPE;
        !           456:                                *(mtod(m, u_short *) + 1) = m->m_len;
        !           457:                                goto gottrailertype;
        !           458:                        }
        !           459: 
        !           460:                type = ETHERPUP_IPTYPE;
        !           461:                off = 0;
        !           462:                goto gottype;
        !           463: #endif
        !           464: 
        !           465: #ifdef notdef
        !           466:        case AF_RAW:
        !           467:                enp = mtod(m, struct ether_header *);
        !           468:                if (m->m_len < sizeof *enp) 
        !           469:                {
        !           470:                        error = EMSGSIZE;
        !           471:                        goto bad;
        !           472:                }
        !           473:                goto gotheader;
        !           474: #endif
        !           475: 
        !           476:        case AF_UNSPEC:
        !           477:                enp = (struct ether_header *)dst->sa_data;
        !           478:                bcopy( enp->ether_dhost, &edst, sizeof(edst));
        !           479:                type = enp->ether_type;
        !           480:                goto gottype;
        !           481: 
        !           482:        default:
        !           483:                if (printerror)
        !           484:                    printf("enp%d: can't handle af%d\n", unit,dst->sa_family);
        !           485:                error = EAFNOSUPPORT;
        !           486:                goto bad;
        !           487:        }
        !           488: 
        !           489: gottrailertype:
        !           490:        /*
        !           491:         * Packet to be sent as trailer: move first packet
        !           492:         * (control information) to end of chain.
        !           493:         */
        !           494:        while (m->m_next)
        !           495:                m = m->m_next;
        !           496:        m->m_next = m0;
        !           497:        m = m0->m_next;
        !           498:        m0->m_next = 0;
        !           499:        m0 = m;
        !           500: 
        !           501: gottype:
        !           502:        /*
        !           503:          * Add local net header.  If no space in first mbuf,
        !           504:          * allocate another.
        !           505:          */
        !           506:        if (m->m_off > MMAXOFF ||
        !           507:            MMINOFF + SIZEOF_ETHEADER > m->m_off) 
        !           508:        {
        !           509:                m = m_get(M_DONTWAIT, MT_HEADER);
        !           510:                if (m == 0) 
        !           511:                {
        !           512:                        enperr[unit].h_nobuffer++; /* host runs out of buf */
        !           513:                        error = ENOBUFS;
        !           514:                        goto bad;
        !           515:                }
        !           516:                m->m_next = m0;
        !           517:                m->m_off = MMINOFF;
        !           518:                m->m_len = SIZEOF_ETHEADER;
        !           519:        } 
        !           520:        else
        !           521:        {
        !           522:                m->m_off -= SIZEOF_ETHEADER;
        !           523:                m->m_len += SIZEOF_ETHEADER;
        !           524:        }
        !           525:        enp = mtod(m, struct ether_header *);
        !           526:        bcopy( &edst, enp->ether_dhost, sizeof(enp->ether_dhost) );
        !           527:        enp->ether_type = type;
        !           528: gotheader:
        !           529:        bcopy( es->es_enaddr, enp->ether_shost, sizeof(enp->ether_shost));
        !           530: 
        !           531:        /*
        !           532:         * Queue message on interface if possible 
        !           533:         */
        !           534: 
        !           535:        s = splimp();   
        !           536:        if( enpput( unit,m ) )
        !           537:        {
        !           538:                error = ENOBUFS;
        !           539:                enperr[unit].c_nobuffer++; /* controller runs out of buf */
        !           540:                goto qfull;
        !           541:        }
        !           542:        splx( s );      
        !           543:        es->es_if.if_opackets++; 
        !           544:        return(0);
        !           545: qfull:
        !           546:        splx( s );      
        !           547:        m0 = m;
        !           548: bad:
        !           549:        m_freem(m0);
        !           550:        return(error);
        !           551: }
        !           552: 
        !           553: /*
        !           554:  * Routine to copy from mbuf chain to transmitter
        !           555:  * buffer in Multibus memory.
        !           556:  */
        !           557: 
        !           558: enpput( unit,m )
        !           559: int unit;
        !           560: struct mbuf *m;
        !           561: {
        !           562:        register BCB *bcbp;
        !           563:        register ENPDEVICE *addr;
        !           564:        register struct mbuf *mp;
        !           565:        register u_char *bp;
        !           566:        int      ctr = 0;
        !           567:        long int        v;
        !           568:        register short *vp = (short *)&v,
        !           569:                        *sp;
        !           570: 
        !           571:        addr = (ENPDEVICE *)enpinfo[ unit ]->ui_addr;
        !           572: 
        !           573:        if ( ringempty( &addr->enp_hostfree ) ) 
        !           574:                        return( 1 );    
        !           575: 
        !           576:        bcbp = (BCB *)ringget( &addr->enp_hostfree );
        !           577:        bcbp->b_len = 0;
        !           578: #ifdef TAHOE
        !           579:        sp = (short *)&bcbp->b_addr;
        !           580:        *vp = *sp; vp[1] = sp[1];
        !           581:        bp = (u_char *)v;
        !           582: #else
        !           583:        bp = (u_char *)bcbp->b_addr;
        !           584: #endif TAHOE
        !           585:        for (mp = m; mp; mp = mp->m_next) 
        !           586:        {
        !           587:                register unsigned len;
        !           588:                u_char *mcp;
        !           589: 
        !           590:                len = mp->m_len;
        !           591:                if( len == 0 )
        !           592:                        continue;
        !           593:                mcp = mtod( mp,u_char * );
        !           594:                enpcopy( mcp,bp,len );
        !           595:                bp += len;
        !           596:                bcbp->b_len += len;
        !           597:        }
        !           598:        bcbp->b_len = max( MINPKTSIZE,bcbp->b_len );
        !           599:        bcbp->b_reserved = 0;
        !           600:        if ( ringput( &addr->enp_toenp,bcbp ) == 1 ) {
        !           601:                host_intr++;
        !           602:                INTR_ENP( addr );
        !           603:        }
        !           604:        m_freem(m);
        !           605:        return( 0 );
        !           606: }
        !           607: 
        !           608: /*
        !           609:  * Routine to copy from Multibus memory into mbufs.
        !           610:  *
        !           611:  * Warning: This makes the fairly safe assumption that
        !           612:  * mbufs have even lengths.
        !           613:  */
        !           614: struct mbuf *
        !           615: enpget( bcbp, totlen, off0 )
        !           616: register BCB *bcbp;
        !           617: int totlen, off0;
        !           618: {
        !           619:        register struct mbuf *m;
        !           620:        register int off = off0;
        !           621:        register unsigned char *cp;
        !           622:        long int        v;
        !           623:        register short *vp = (short *)&v,
        !           624:                        *sp;
        !           625: 
        !           626:        int len;
        !           627:        struct mbuf *top = 0;
        !           628:        struct mbuf **mp = &top;
        !           629: 
        !           630: #ifdef TAHOE
        !           631:        sp = (short *)&bcbp->b_addr;
        !           632:        *vp = *sp; vp[1] = sp[1];
        !           633:        cp = (unsigned char *)v + SIZEOF_ETHEADER;
        !           634: #else
        !           635:        cp = (unsigned char *)bcbp->b_addr + SIZEOF_ETHEADER;
        !           636: #endif TAHOE
        !           637: 
        !           638:        while( totlen > 0 )
        !           639:        {
        !           640:                u_char *mcp;
        !           641: 
        !           642:                MGET(m, M_DONTWAIT, MT_DATA);
        !           643:                if (m == 0) 
        !           644:                        goto bad;
        !           645:                if( off )
        !           646:                {
        !           647:                        len = totlen - off;
        !           648: #ifdef TAHOE
        !           649:                        sp = (short *)&bcbp->b_addr;
        !           650:                        *vp = *sp; vp[1] = sp[1];
        !           651:                        cp = (unsigned char *)v + SIZEOF_ETHEADER
        !           652:                                + off;
        !           653: #else
        !           654:                        cp = (unsigned char *)bcbp->b_addr + 
        !           655:                                SIZEOF_ETHEADER + off;
        !           656: #endif TAHOE
        !           657:                } 
        !           658:                else
        !           659:                        len = totlen;
        !           660: 
        !           661: 
        !           662:                if (len >= CLBYTES) {
        !           663:                        struct mbuf *p;
        !           664: 
        !           665:                        MCLGET(p, 1);
        !           666:                        if (p != 0) {
        !           667:                                m->m_len = len = CLBYTES;
        !           668:                                m->m_off = (int)p - (int)m;
        !           669:                        } else  {
        !           670:                                m->m_len = len = MIN(MLEN, len);
        !           671:                                m->m_off = MMINOFF;
        !           672:                                }
        !           673:                } else  { 
        !           674:                        m->m_len = len = MIN(MLEN, len);
        !           675:                        m->m_off = MMINOFF;
        !           676:                }
        !           677: 
        !           678:                mcp = mtod(m, u_char *);
        !           679:                enpcopy(cp, mcp, len);
        !           680:                cp += len;
        !           681:                *mp = m;
        !           682:                mp = &m->m_next;
        !           683:                if (off == 0) 
        !           684:                {
        !           685:                        totlen -= len;
        !           686:                        continue;
        !           687:                }
        !           688:                off += len;
        !           689:                if (off == totlen) 
        !           690:                {
        !           691: #ifdef TAHOE
        !           692:                        sp = (short *)&bcbp->b_addr;
        !           693:                        *vp = *sp; vp[1] = sp[1];
        !           694:                        cp = (unsigned char *)v + SIZEOF_ETHEADER;
        !           695: #else
        !           696:                        cp = (unsigned char *)bcbp->b_addr + SIZEOF_ETHEADER;
        !           697: #endif TAHOE
        !           698:                        off = 0;
        !           699:                        totlen = off0;
        !           700:                }
        !           701:        }
        !           702:        return (top);
        !           703: bad:
        !           704:        m_freem(top);
        !           705:        return (0);
        !           706: }
        !           707: 
        !           708: /*
        !           709:  * Process an ioctl request.
        !           710:  *    this can be called via the "socket" route for SIOCSIFADDR or
        !           711:  *     by the cdev/inode route for SIOCSIFCCFWR/RD
        !           712:  *
        !           713:  */
        !           714: 
        !           715: enpioctl(ifp, cmd, data)
        !           716: register struct ifnet *ifp;
        !           717: int cmd;
        !           718: caddr_t data;
        !           719: {
        !           720:        register int    unit = ifp->if_unit;
        !           721:        register struct vba_device *md;
        !           722:        int s, error = 0;
        !           723:        struct sockaddr_in      *sin;
        !           724:        struct sockaddr         *sa;
        !           725:        struct enp_softc        *es = &enp_softc[ifp->if_unit];
        !           726:        ENPDEVICE               *addr;
        !           727:        struct config_entry     *cf;
        !           728:        struct ifreq *ifr       = (struct ifreq *)data;
        !           729:        struct sockaddr_in      *et_addr;
        !           730:        int code, i;
        !           731: 
        !           732: 
        !           733:        if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0)
        !           734:                return(ENODEV);
        !           735: 
        !           736:        switch (cmd) {
        !           737: 
        !           738:        case SIOCSIFADDR:
        !           739:                s = splimp();
        !           740:                sa = (struct sockaddr *)&ifr->ifr_addr;
        !           741:                if (sa->sa_family == AF_UNSPEC ) {
        !           742:                        if (sa->sa_data[0] & 1){ /*broad or multi-cast*/
        !           743:                                splx( s );
        !           744:                                return( EINVAL );
        !           745:                        }
        !           746:                        bcopy(sa->sa_data,es->es_enaddr,sizeof(es->es_enaddr));
        !           747:                        enpinit( ifp->if_unit);
        !           748:                        break;
        !           749:                }
        !           750:                sin = (struct sockaddr_in *)&ifr->ifr_addr;
        !           751:                if (sin->sin_family != AF_INET){
        !           752:                        splx( s );
        !           753:                        return( EINVAL );
        !           754:                }
        !           755:                if (ifp->if_flags & IFF_RUNNING)
        !           756:                        if_rtinit(ifp, -1);     /* delete previous route */
        !           757:                enpsetaddr(ifp, sin);
        !           758:                enpinit(ifp->if_unit);
        !           759:                enpgetaddr( ifp->if_unit );
        !           760:                splx(s);
        !           761:                break;
        !           762: 
        !           763: 
        !           764:        case SIOCSETETADDR:     /* Set Ethernet station address */
        !           765:                s = splimp();
        !           766:                ifp->if_flags &= (~IFF_RUNNING | IFF_UP);
        !           767:                et_addr = (struct sockaddr_in *)&ifr->ifr_addr;
        !           768:                addr = (ENPDEVICE *)enpinfo[ifp->if_unit]->ui_addr;
        !           769: 
        !           770:                /* Set station address and reset controller board */
        !           771:                {
        !           772:                u_char  *to = &addr->enp_addr.e_baseaddr.ea_addr[0];
        !           773:                char    *from = &et_addr->sin_zero[2];
        !           774:                int     i;
        !           775: 
        !           776:                for (i = 0 ; i < ETHADDR_SIZE; i++) 
        !           777:                        *to++ = (u_char) (~(*from++ & 0xff));
        !           778:                }
        !           779:                enpcopy(&addr->enp_addr.e_listsize, &code, sizeof(code)); 
        !           780:                code |= E_ADDR_SUPP;
        !           781:                enpcopy(&code, &addr->enp_addr.e_listsize, sizeof(code)); 
        !           782:                enpreset(ifp->if_unit);         /* Re-initialize */
        !           783:                enpgetaddr(ifp->if_unit);
        !           784:                splx(s);
        !           785:                break;
        !           786: 
        !           787:        case SIOCGETETADDR:     /* Get Foreign Hosts' Ethernet addresses */
        !           788:                arpwhohas(&es->es_ac, (struct in_addr *)ifr->ifr_data);
        !           789:                break;
        !           790: 
        !           791:        default:
        !           792:                error = EINVAL;
        !           793:        }
        !           794:        return(error);
        !           795: }
        !           796: 
        !           797: enpsetaddr(ifp, sin)
        !           798: register struct ifnet *ifp;
        !           799: register struct sockaddr_in *sin;
        !           800: {
        !           801: 
        !           802:        ifp->if_addr = *(struct sockaddr *)sin;
        !           803:        ifp->if_net = in_netof(sin->sin_addr);
        !           804:        ifp->if_host[0] = in_lnaof(sin->sin_addr);
        !           805:        sin = (struct sockaddr_in *)&ifp->if_broadaddr;
        !           806:        sin->sin_family = AF_INET;
        !           807:        sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
        !           808:        ifp->if_flags |= IFF_BROADCAST;
        !           809: }
        !           810: 
        !           811: 
        !           812: /*
        !           813:  * Get the ethernet addr, store it and print it
        !           814:  * Read the ethernet address off the board, one byte at a time.
        !           815:  *     put it in enp_softc
        !           816:  */
        !           817: 
        !           818: 
        !           819: enpgetaddr( unit )
        !           820: int unit;
        !           821: {
        !           822:        register struct enp_softc       *es = &enp_softc[unit];
        !           823:        register ENPDEVICE *addr =(ENPDEVICE *)enpinfo[unit]->ui_addr;
        !           824:        int i;
        !           825:        
        !           826: #ifdef TAHOE
        !           827:        enpcopy(&addr->enp_addr.e_baseaddr, &es->es_boardaddr, sizeof(es->es_boardaddr));
        !           828: #else
        !           829:        es->es_boardaddr = addr->enp_addr.e_baseaddr;
        !           830: #endif TAHOE
        !           831:        bcopy(&es->es_boardaddr, es->es_enaddr, ETHADDR_SIZE);
        !           832:        return( 1 );
        !           833: }
        !           834: 
        !           835: /*
        !           836:  * enpram device
        !           837:  *
        !           838:  */
        !           839: 
        !           840: enpr_open( dev )
        !           841: {
        !           842:        register int    unit = minor(dev);
        !           843:        register struct vba_device *md;
        !           844:        register ENPDEVICE      *addr;
        !           845: 
        !           846:        if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0 ||
        !           847:            (addr = (ENPDEVICE *)md->ui_addr) == (ENPDEVICE *)0)
        !           848:                return(ENODEV);
        !           849:        if (addr->enp_state != S_ENPRESET)
        !           850:                return(EACCES);  /* enp is not in reset state, don't open  */
        !           851:        if ( !enpismapped[unit] ) {
        !           852:                ioaccess(ENPmap[unit],ENPmapa[unit],ENPBPTE);
        !           853:                ++enpismapped[unit];
        !           854:        }
        !           855:        enpram[unit] = ENP_OPEN;
        !           856:        return( 0 );
        !           857: }
        !           858: 
        !           859: enpr_close(dev)
        !           860: {
        !           861:        enpram[minor(dev)] = ENP_CLOSE;
        !           862:        return( 0 );
        !           863: }
        !           864: 
        !           865: enpr_read( dev,uio )
        !           866: int dev;
        !           867: register struct uio *uio;
        !           868: {
        !           869:        register ENPDEVICE *addr;
        !           870:        register struct iovec *iov;
        !           871:        register r=0;
        !           872: 
        !           873:        if (enpram[minor(dev)] != ENP_OPEN)
        !           874:                return(EACCES);
        !           875:        if ( uio->uio_offset > RAM_SIZE )
        !           876:                return( ENODEV );
        !           877:        if ( uio->uio_offset + iov->iov_len > RAM_SIZE )
        !           878:                iov->iov_len = RAM_SIZE - uio->uio_offset;
        !           879:        addr = (ENPDEVICE *)enpinfo[ minor( dev ) ]->ui_addr;
        !           880:        iov  = uio->uio_iov;
        !           881: 
        !           882:        if( r = enpcopyout( &addr->enp_ram[ uio->uio_offset ], iov->iov_base,
        !           883:                         iov->iov_len ) )
        !           884:                 return( r );
        !           885: 
        !           886:        uio->uio_resid -= iov->iov_len;
        !           887:        iov->iov_len = 0;
        !           888: 
        !           889:        return( 0 );
        !           890: }
        !           891: 
        !           892: enpr_write( dev,uio )
        !           893: int dev;
        !           894: register struct uio *uio;
        !           895: {
        !           896:        register ENPDEVICE *addr;
        !           897:        register struct iovec *iov;
        !           898:        register r=0;
        !           899: 
        !           900:        if (enpram[minor(dev)] != ENP_OPEN)
        !           901:                return(EACCES);
        !           902:        addr = (ENPDEVICE *)enpinfo[ minor( dev ) ]->ui_addr;
        !           903:        iov  = uio->uio_iov;
        !           904: 
        !           905:        if ( uio->uio_offset > RAM_SIZE )
        !           906:                return( ENODEV );
        !           907:        if ( uio->uio_offset + iov->iov_len > RAM_SIZE )
        !           908:                iov->iov_len = RAM_SIZE - uio->uio_offset;
        !           909:        if( r = enpcopyin( iov->iov_base, &addr->enp_ram[ uio->uio_offset ],
        !           910:                        iov->iov_len ) )
        !           911:                return( r );
        !           912: 
        !           913:        uio->uio_resid -= iov->iov_len;
        !           914:        iov->iov_len = 0;
        !           915: 
        !           916:        return( 0 );
        !           917: }
        !           918: 
        !           919: enpr_ioctl( dev,cmd,arg,fflag )
        !           920: dev_t dev;
        !           921: caddr_t *arg;
        !           922: {
        !           923:        register ENPDEVICE *addr;
        !           924:        long int        v;
        !           925:        register short  *vp = (short *)&v, *sp;
        !           926:        register unit = minor(dev);
        !           927:        register struct vba_device *md;
        !           928: 
        !           929:        if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0 ||
        !           930:            (addr = (ENPDEVICE *)md->ui_addr) == (ENPDEVICE *)0)
        !           931:                return(ENODEV);
        !           932:        switch( cmd )
        !           933:        {
        !           934:                case ENPIOGO:
        !           935: /* not needed if prom based version */
        !           936: #ifdef TAHOE
        !           937:                        sp = (short *)&addr->enp_base;
        !           938:                        v = (int)addr;
        !           939:                        *sp = *vp; sp[1] = vp[1];
        !           940: #else
        !           941:                        addr->enp_base = (int)addr;
        !           942: #endif TAHOE
        !           943:                        addr->enp_intrvec = intvec[ unit ];
        !           944:                        ENP_GO( addr, ENPSTART );
        !           945:                        DELAY( 200000 );
        !           946:                        enpattach( enpinfo[ unit ] );
        !           947:                        enpinit( unit );
        !           948:                        addr->enp_state = S_ENPRUN;  /* it is running now */
        !           949: /* end of not needed */
        !           950: 
        !           951:                        break;
        !           952: 
        !           953:                case ENPIORESET:
        !           954:                        RESET_ENP( addr );
        !           955:                        addr->enp_state = S_ENPRESET;  /* it is reset now */
        !           956:                        DELAY( 100000 );
        !           957:                        break;
        !           958:        }
        !           959:        return( 0 );
        !           960: }
        !           961: 
        !           962: /* 
        !           963:  * routines to synchronize enp and host 
        !           964:  */
        !           965: 
        !           966: static
        !           967: ringinit( rp,size )
        !           968: register RING *rp;
        !           969: {
        !           970:        register int    i;
        !           971:        register short *sp; 
        !           972: 
        !           973:        rp->r_rdidx = rp->r_wrtidx = 0;
        !           974:        rp->r_size = size;
        !           975: }
        !           976: 
        !           977: static
        !           978: ringempty( rp )
        !           979: register RING *rp;
        !           980: {
        !           981:        return( rp->r_rdidx == rp->r_wrtidx );
        !           982: }
        !           983: 
        !           984: static
        !           985: ringfull( rp )
        !           986: register RING *rp;
        !           987: {
        !           988:        register short idx;
        !           989: 
        !           990:        idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
        !           991:        return( idx == rp->r_rdidx );
        !           992: }
        !           993: 
        !           994: static
        !           995: ringput( rp,v )
        !           996: register RING *rp;
        !           997: {
        !           998:        register int idx;
        !           999:        register short *vp = (short *)&v,
        !          1000:                       *sp;
        !          1001: 
        !          1002:        idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
        !          1003:        if( idx != rp->r_rdidx )
        !          1004:        {
        !          1005: #ifdef TAHOE
        !          1006:                sp = (short *)&rp->r_slot[ rp->r_wrtidx ];
        !          1007:                *sp = *vp; sp[1] = vp[1];
        !          1008: #else
        !          1009:                rp->r_slot[ rp->r_wrtidx ] = v;
        !          1010: #endif TAHOE
        !          1011:                rp->r_wrtidx = idx;
        !          1012:                if( (idx -= rp->r_rdidx) < 0 )
        !          1013:                        idx += rp->r_size;
        !          1014:                return( idx );                  /* num ring entries */
        !          1015:        }
        !          1016:        return( 0 );
        !          1017: }
        !          1018: 
        !          1019: static
        !          1020: ringget( rp )
        !          1021: register RING *rp;
        !          1022: {
        !          1023:        register int i = 0;
        !          1024:        long int v;
        !          1025:        register short *vp = (short *)&v,
        !          1026:                       *sp;
        !          1027: 
        !          1028:        if( rp->r_rdidx != rp->r_wrtidx )
        !          1029:        {
        !          1030: #ifdef TAHOE
        !          1031:                sp = (short *)&rp->r_slot[ rp->r_rdidx ];
        !          1032:                *vp = *sp; vp[1] = sp[1];
        !          1033:                i = v;
        !          1034: #else
        !          1035:                i = rp->r_slot[ rp->r_rdidx ];
        !          1036: #endif TAHOE
        !          1037:                rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1);
        !          1038:        }
        !          1039:        return( i );
        !          1040: }
        !          1041: 
        !          1042: #ifdef notdef
        !          1043: struct mbuf *
        !          1044: m_tofree( rp )
        !          1045: register RING *rp;
        !          1046: {
        !          1047:        long int v = 0;
        !          1048:        register short *vp = (short *)&v,
        !          1049:                       *sp;
        !          1050: 
        !          1051:        if( rp->r_rdidx != rp->r_wrtidx )
        !          1052:        {
        !          1053: #ifdef TAHOE
        !          1054:                sp = (short *)&rp->r_slot[ rp->r_rdidx ];
        !          1055:                *vp = *sp; vp[1] = sp[1];
        !          1056:                /* *sp = 0xffff; sp[1] = 0xffff; */
        !          1057: #else
        !          1058:                v = rp->r_slot[ rp->r_rdidx ];
        !          1059: #endif TAHOE
        !          1060:                rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1);
        !          1061:        }
        !          1062:        return( (struct mbuf *)v );
        !          1063: }
        !          1064: #endif
        !          1065: static
        !          1066: fir( rp )
        !          1067: register RING *rp;
        !          1068: {
        !          1069:        long int v;
        !          1070:        register short *vp = (short *)&v,
        !          1071:                       *sp;
        !          1072: 
        !          1073:        if( rp->r_rdidx != rp->r_wrtidx )
        !          1074: #ifdef TAHOE
        !          1075:        {
        !          1076:                sp = (short *)&rp->r_slot[ rp->r_rdidx ];
        !          1077:                *vp = *sp; vp[1] = sp[1];
        !          1078:                return( v );
        !          1079:        }
        !          1080: #else
        !          1081:                return( rp->r_slot[ rp->r_rdidx ] );
        !          1082: #endif TAHOE
        !          1083:        else   
        !          1084:                return( 0 );
        !          1085: }
        !          1086: 
        !          1087: 
        !          1088: static
        !          1089: prtbytes( addr )
        !          1090: register char *addr;
        !          1091: {
        !          1092:        register int i;
        !          1093: 
        !          1094:        for( i = 0; i < 12; i++ )
        !          1095:        {
        !          1096:                printf("%X ",*addr&0377);
        !          1097:                addr++;
        !          1098:        }
        !          1099:        printf("\n");
        !          1100: }
        !          1101: 
        !          1102: static
        !          1103: enpcopy(from, to, cnt)
        !          1104: register char *from, *to;
        !          1105: register cnt;
        !          1106: {
        !          1107:        register c;
        !          1108:        register short *f, *t;
        !          1109: 
        !          1110:        if (((int)from & 01) && ((int)to & 01)) {
        !          1111:                                        /* source & dest at odd addresses */
        !          1112:                *to++ = *from++;
        !          1113:                --cnt;
        !          1114:        }
        !          1115:        if (cnt > 1 && (((int)to & 01)==0) && (((int)from & 01)==0)) {
        !          1116:                t = (short *) to;
        !          1117:                f = (short *) from;
        !          1118:                for( c = cnt>>1; c; --c)        /* even address copy */
        !          1119:                        *t++ = *f++;
        !          1120:                cnt &= 1;
        !          1121:                if ( cnt ) {                    /* odd len */
        !          1122:                        from = (char *) f;
        !          1123:                        to   = (char *) t;
        !          1124:                        *to = *from;
        !          1125:                }
        !          1126:        }
        !          1127:        while (cnt-- > 0)       /* one of the address(es) must be odd */
        !          1128:                *to++ = *from++;
        !          1129: 
        !          1130: }
        !          1131: 
        !          1132: static
        !          1133: enpcopyin(userv, kernv, cnt)
        !          1134: {
        !          1135: 
        !          1136:        if (useracc(userv, cnt, 1)) {
        !          1137:                enpcopy( userv, kernv, cnt );
        !          1138:                return( 0 );
        !          1139:        }
        !          1140:        else    return( EFAULT );
        !          1141: }
        !          1142: 
        !          1143: 
        !          1144: static
        !          1145: enpcopyout(kernv, userv, cnt)
        !          1146: {
        !          1147: 
        !          1148:        if (useracc(userv, cnt, 0)) {
        !          1149:                enpcopy( kernv, userv, cnt );
        !          1150:                return( 0 );
        !          1151:        }
        !          1152:        else    return( EFAULT );
        !          1153: }
        !          1154: #endif

unix.superglobalmegacorp.com

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