Annotation of Net2/arch/i386/isa/if_ne.c, revision 1.1

1.1     ! root        1: /*-
        !             2:  * Copyright (c) 1990, 1991 William F. Jolitz.
        !             3:  * Copyright (c) 1990 The Regents of the University of California.
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  * 1. Redistributions of source code must retain the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  * 3. All advertising materials mentioning features or use of this software
        !            15:  *    must display the following acknowledgement:
        !            16:  *     This product includes software developed by the University of
        !            17:  *     California, Berkeley and its contributors.
        !            18:  * 4. Neither the name of the University nor the names of its contributors
        !            19:  *    may be used to endorse or promote products derived from this software
        !            20:  *    without specific prior written permission.
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            32:  * SUCH DAMAGE.
        !            33:  *
        !            34:  *     @(#)if_ne.c     7.4 (Berkeley) 5/21/91
        !            35:  */
        !            36: 
        !            37: /*
        !            38:  * NE2000 Ethernet driver
        !            39:  *
        !            40:  * Parts inspired from Tim Tucker's if_wd driver for the wd8003,
        !            41:  * insight on the ne2000 gained from Robert Clements PC/FTP driver.
        !            42:  */
        !            43: 
        !            44: #include "ne.h"
        !            45: #if NNE > 0
        !            46: 
        !            47: #include "param.h"
        !            48: #include "systm.h"
        !            49: #include "mbuf.h"
        !            50: #include "buf.h"
        !            51: #include "protosw.h"
        !            52: #include "socket.h"
        !            53: #include "ioctl.h"
        !            54: #include "errno.h"
        !            55: #include "syslog.h"
        !            56: 
        !            57: #include "net/if.h"
        !            58: #include "net/netisr.h"
        !            59: #include "net/route.h"
        !            60: 
        !            61: #ifdef INET
        !            62: #include "netinet/in.h"
        !            63: #include "netinet/in_systm.h"
        !            64: #include "netinet/in_var.h"
        !            65: #include "netinet/ip.h"
        !            66: #include "netinet/if_ether.h"
        !            67: #endif
        !            68: 
        !            69: #ifdef NS
        !            70: #include "netns/ns.h"
        !            71: #include "netns/ns_if.h"
        !            72: #endif
        !            73: 
        !            74: #include "i386/isa/isa_device.h"
        !            75: #include "i386/isa/if_nereg.h"
        !            76: #include "i386/isa/icu.h"
        !            77: 
        !            78: int    neprobe(), neattach(), neintr();
        !            79: int    nestart(),neinit(), ether_output(), neioctl();
        !            80: 
        !            81: struct isa_driver nedriver = {
        !            82:        neprobe, neattach, "ne",
        !            83: };
        !            84: 
        !            85: struct mbuf *neget();
        !            86: 
        !            87: #define ETHER_MIN_LEN 64
        !            88: #define ETHER_MAX_LEN 1536
        !            89: 
        !            90: /*
        !            91:  * Ethernet software status per interface.
        !            92:  *
        !            93:  * Each interface is referenced by a network interface structure,
        !            94:  * ns_if, which the routing code uses to locate the interface.
        !            95:  * This structure contains the output queue for the interface, its address, ...
        !            96:  */
        !            97: struct ne_softc {
        !            98:        struct  arpcom ns_ac;           /* Ethernet common part */
        !            99: #define        ns_if   ns_ac.ac_if             /* network-visible interface */
        !           100: #define        ns_addr ns_ac.ac_enaddr         /* hardware Ethernet address */
        !           101:        int     ns_flags;
        !           102: #define        DSF_LOCK        1               /* block re-entering enstart */
        !           103:        int     ns_oactive ;
        !           104:        int     ns_mask ;
        !           105:        int     ns_ba;                  /* byte addr in buffer ram of inc pkt */
        !           106:        int     ns_cur;                 /* current page being filled */
        !           107:        struct  prhdr   ns_ph;          /* hardware header of incoming packet*/
        !           108:        struct  ether_header ns_eh;     /* header of incoming packet */
        !           109:        u_char  ns_pb[2048 /*ETHERMTU+sizeof(long)*/];
        !           110: } ne_softc[NNE] ;
        !           111: #define        ENBUFSIZE       (sizeof(struct ether_header) + ETHERMTU + 2 + ETHER_MIN_LEN)
        !           112: 
        !           113: int nec;
        !           114: 
        !           115: u_short boarddata[16];
        !           116:  
        !           117: neprobe(dvp)
        !           118:        struct isa_device *dvp;
        !           119: {
        !           120:        int val,i,s;
        !           121:        register struct ne_softc *ns = &ne_softc[0];
        !           122: 
        !           123: #ifdef lint
        !           124:        neintr(0);
        !           125: #endif
        !           126: 
        !           127:        nec = dvp->id_iobase;
        !           128:        s = splimp();
        !           129: 
        !           130:        /* Reset the bastard */
        !           131:        val = inb(nec+ne_reset);
        !           132:        DELAY(2000000);
        !           133:        outb(nec+ne_reset,val);
        !           134: 
        !           135:        outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA);
        !           136:        
        !           137:        i = 1000000;
        !           138:        while ((inb(nec+ds0_isr)&DSIS_RESET) == 0 && i-- > 0);
        !           139:        if (i < 0) return (0);
        !           140: 
        !           141:        outb(nec+ds0_isr, 0xff);
        !           142: 
        !           143:        /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
        !           144:        outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1);
        !           145: 
        !           146:        outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
        !           147:        DELAY(10000);
        !           148: 
        !           149:        /* Check cmd reg and fail if not right */
        !           150:        if ((i=inb(nec+ds_cmd)) != (DSCM_NODMA|DSCM_PG0|DSCM_STOP))
        !           151:                return(0);
        !           152: 
        !           153:        outb(nec+ds0_tcr, 0);
        !           154:        outb(nec+ds0_rcr, DSRC_MON);
        !           155:        outb(nec+ds0_pstart, RBUF/DS_PGSIZE);
        !           156:        outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE);
        !           157:        outb(nec+ds0_bnry, RBUFEND/DS_PGSIZE);
        !           158:        outb(nec+ds0_imr, 0);
        !           159:        outb(nec+ds0_isr, 0);
        !           160:        outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
        !           161:        outb(nec+ds1_curr, RBUF/DS_PGSIZE);
        !           162:        outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
        !           163: 
        !           164: #ifdef NEDEBUG
        !           165: #define        PAT(n)  (0xa55a + 37*(n))
        !           166: #define        RCON    37
        !           167:        {       int i, rom, pat;
        !           168: 
        !           169:                rom=1;
        !           170:                printf("ne ram ");
        !           171:                
        !           172:                for (i = 0; i < 0xfff0; i+=4) {
        !           173:                        pat = PAT(i);
        !           174:                        neput(&pat,i,4);
        !           175:                        nefetch(&pat,i,4);
        !           176:                        if (pat == PAT(i)) {
        !           177:                                if (rom) {
        !           178:                                        rom=0;
        !           179:                                        printf(" %x", i);
        !           180:                                }
        !           181:                        } else {
        !           182:                                if (!rom) {
        !           183:                                        rom=1;
        !           184:                                        printf("..%x ", i);
        !           185:                                }
        !           186:                        }
        !           187:                        pat=0;
        !           188:                        neput(&pat,i,4);
        !           189:                }
        !           190:                printf("\n");
        !           191:        }
        !           192: #endif
        !           193: 
        !           194:        /* Extract board address */
        !           195:        nefetch ((caddr_t)boarddata, 0, sizeof(boarddata));
        !           196:        for(i=0; i < 6; i++)  ns->ns_addr[i] = boarddata[i];
        !           197:        splx(s);
        !           198:        return (1);
        !           199: }
        !           200: 
        !           201: /*
        !           202:  * Fetch from onboard ROM/RAM
        !           203:  */
        !           204: nefetch (up, ad, len) caddr_t up; {
        !           205:        u_char cmd;
        !           206: 
        !           207:        cmd = inb(nec+ds_cmd);
        !           208:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
        !           209: 
        !           210:        /* Setup remote dma */
        !           211:        outb (nec+ds0_isr, DSIS_RDC);
        !           212:        outb (nec+ds0_rbcr0, len);
        !           213:        outb (nec+ds0_rbcr1, len>>8);
        !           214:        outb (nec+ds0_rsar0, ad);
        !           215:        outb (nec+ds0_rsar1, ad>>8);
        !           216: 
        !           217:        /* Execute & extract from card */
        !           218:        outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START);
        !           219:        insw (nec+ne_data, up, len/2);
        !           220: 
        !           221:        /* Wait till done, then shutdown feature */
        !           222:        while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) ;
        !           223:        outb (nec+ds0_isr, DSIS_RDC);
        !           224:        outb (nec+ds_cmd, cmd);
        !           225: }
        !           226: 
        !           227: /*
        !           228:  * Put to onboard RAM
        !           229:  */
        !           230: neput (up, ad, len) caddr_t up; {
        !           231:        u_char cmd;
        !           232: 
        !           233:        cmd = inb(nec+ds_cmd);
        !           234:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
        !           235: 
        !           236:        /* Setup for remote dma */
        !           237:        outb (nec+ds0_isr, DSIS_RDC);
        !           238:        if(len&1) len++;                /* roundup to words */
        !           239:        outb (nec+ds0_rbcr0, len);
        !           240:        outb (nec+ds0_rbcr1, len>>8);
        !           241:        outb (nec+ds0_rsar0, ad);
        !           242:        outb (nec+ds0_rsar1, ad>>8);
        !           243: 
        !           244:        /* Execute & stuff to card */
        !           245:        outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START);
        !           246:        outsw (nec+ne_data, up, len/2);
        !           247:        
        !           248:        /* Wait till done, then shutdown feature */
        !           249:        while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) ;
        !           250:        outb (nec+ds0_isr, DSIS_RDC);
        !           251:        outb (nec+ds_cmd, cmd);
        !           252: }
        !           253: 
        !           254: /*
        !           255:  * Reset of interface.
        !           256:  */
        !           257: nereset(unit, uban)
        !           258:        int unit, uban;
        !           259: {
        !           260:        if (unit >= NNE)
        !           261:                return;
        !           262:        printf("ne%d: reset\n", unit);
        !           263:        ne_softc[unit].ns_flags &= ~DSF_LOCK;
        !           264:        neinit(unit);
        !           265: }
        !           266:  
        !           267: /*
        !           268:  * Interface exists: make available by filling in network interface
        !           269:  * record.  System will initialize the interface when it is ready
        !           270:  * to accept packets.  We get the ethernet address here.
        !           271:  */
        !           272: neattach(dvp)
        !           273:        struct isa_device *dvp;
        !           274: {
        !           275:        int unit = dvp->id_unit;
        !           276:        register struct ne_softc *ns = &ne_softc[unit];
        !           277:        register struct ifnet *ifp = &ns->ns_if;
        !           278: 
        !           279:        ifp->if_unit = unit;
        !           280:        ifp->if_name = nedriver.name ;
        !           281:        ifp->if_mtu = ETHERMTU;
        !           282:        printf (" ethernet address %s", ether_sprintf(ns->ns_addr)) ;
        !           283:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
        !           284:        ifp->if_init = neinit;
        !           285:        ifp->if_output = ether_output;
        !           286:        ifp->if_start = nestart;
        !           287:        ifp->if_ioctl = neioctl;
        !           288:        ifp->if_reset = nereset;
        !           289:        ifp->if_watchdog = 0;
        !           290:        if_attach(ifp);
        !           291: }
        !           292: 
        !           293: /*
        !           294:  * Initialization of interface; set up initialization block
        !           295:  * and transmit/receive descriptor rings.
        !           296:  */
        !           297: neinit(unit)
        !           298:        int unit;
        !           299: {
        !           300:        register struct ne_softc *ns = &ne_softc[unit];
        !           301:        struct ifnet *ifp = &ns->ns_if;
        !           302:        int s;
        !           303:        register i; char *cp;
        !           304: 
        !           305:        if (ifp->if_addrlist == (struct ifaddr *)0) return;
        !           306:        if (ifp->if_flags & IFF_RUNNING) return;
        !           307: 
        !           308:        s = splimp();
        !           309: 
        !           310:        /* set physical address on ethernet */
        !           311:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
        !           312:        for (i=0 ; i < 6 ; i++) outb(nec+ds1_par0+i,ns->ns_addr[i]);
        !           313: 
        !           314:        /* clr logical address hash filter for now */
        !           315:        for (i=0 ; i < 8 ; i++) outb(nec+ds1_mar0+i,0xff);
        !           316: 
        !           317:        /* init regs */
        !           318:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
        !           319:        outb (nec+ds0_rbcr0, 0);
        !           320:        outb (nec+ds0_rbcr1, 0);
        !           321:        outb (nec+ds0_imr, 0);
        !           322:        outb (nec+ds0_isr, 0xff);
        !           323: 
        !           324:        /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
        !           325:        outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1);
        !           326:        outb(nec+ds0_tcr, 0);
        !           327:        outb (nec+ds0_rcr, DSRC_MON);
        !           328:        outb (nec+ds0_tpsr, 0);
        !           329:        outb(nec+ds0_pstart, RBUF/DS_PGSIZE);
        !           330:        outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE);
        !           331:        outb(nec+ds0_bnry, RBUF/DS_PGSIZE);
        !           332:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
        !           333:        outb(nec+ds1_curr, RBUF/DS_PGSIZE);
        !           334:        ns->ns_cur = RBUF/DS_PGSIZE;
        !           335:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
        !           336:        outb (nec+ds0_rcr, DSRC_AB);
        !           337:        outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1);
        !           338:        outb (nec+ds0_imr, 0xff);
        !           339: 
        !           340:        ns->ns_if.if_flags |= IFF_RUNNING;
        !           341:        ns->ns_oactive = 0; ns->ns_mask = ~0;
        !           342:        nestart(ifp);
        !           343:        splx(s);
        !           344: }
        !           345: 
        !           346: /*
        !           347:  * Setup output on interface.
        !           348:  * Get another datagram to send off of the interface queue,
        !           349:  * and map it to the interface before starting the output.
        !           350:  * called only at splimp or interrupt level.
        !           351:  */
        !           352: nestart(ifp)
        !           353:        struct ifnet *ifp;
        !           354: {
        !           355:        register struct ne_softc *ns = &ne_softc[ifp->if_unit];
        !           356:        struct mbuf *m0, *m;
        !           357:        int buffer;
        !           358:        int len = 0, i, total,t;
        !           359: 
        !           360:        /*
        !           361:         * The DS8390 has only one transmit buffer, if it is busy we
        !           362:         * must wait until the transmit interrupt completes.
        !           363:         */
        !           364:        outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);
        !           365: 
        !           366:        if (ns->ns_flags & DSF_LOCK)
        !           367:                return;
        !           368: 
        !           369:        if (inb(nec+ds_cmd) & DSCM_TRANS)
        !           370:                return;
        !           371: 
        !           372:        if ((ns->ns_if.if_flags & IFF_RUNNING) == 0)
        !           373:                return;
        !           374: 
        !           375:        IF_DEQUEUE(&ns->ns_if.if_snd, m);
        !           376:  
        !           377:        if (m == 0)
        !           378:                return;
        !           379: 
        !           380:        /*
        !           381:         * Copy the mbuf chain into the transmit buffer
        !           382:         */
        !           383: 
        !           384:        ns->ns_flags |= DSF_LOCK;       /* prevent entering nestart */
        !           385:        buffer = TBUF; len = i = 0;
        !           386:        t = 0;
        !           387:        for (m0 = m; m != 0; m = m->m_next)
        !           388:                t += m->m_len;
        !           389:                
        !           390:        m = m0;
        !           391:        total = t;
        !           392:        for (m0 = m; m != 0; ) {
        !           393:                
        !           394:                if (m->m_len&1 && t > m->m_len) {
        !           395:                        neput(mtod(m, caddr_t), buffer, m->m_len - 1);
        !           396:                        t -= m->m_len - 1;
        !           397:                        buffer += m->m_len - 1;
        !           398:                        m->m_data += m->m_len - 1;
        !           399:                        m->m_len = 1;
        !           400:                        m = m_pullup(m, 2);
        !           401:                } else {
        !           402:                        neput(mtod(m, caddr_t), buffer, m->m_len);
        !           403:                        buffer += m->m_len;
        !           404:                        t -= m->m_len;
        !           405:                        MFREE(m, m0);
        !           406:                        m = m0;
        !           407:                }
        !           408:        }
        !           409: 
        !           410:        /*
        !           411:         * Init transmit length registers, and set transmit start flag.
        !           412:         */
        !           413: 
        !           414:        len = total;
        !           415:        if (len < ETHER_MIN_LEN) len = ETHER_MIN_LEN;
        !           416:        outb(nec+ds0_tbcr0,len&0xff);
        !           417:        outb(nec+ds0_tbcr1,(len>>8)&0xff);
        !           418:        outb(nec+ds0_tpsr, TBUF/DS_PGSIZE);
        !           419:        outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);
        !           420: }
        !           421: 
        !           422: /* buffer successor/predecessor in ring? */
        !           423: #define succ(n) (((n)+1 >= RBUFEND/DS_PGSIZE) ? RBUF/DS_PGSIZE : (n)+1)
        !           424: #define pred(n) (((n)-1 < RBUF/DS_PGSIZE) ? RBUFEND/DS_PGSIZE-1 : (n)-1)
        !           425: 
        !           426: /*
        !           427:  * Controller interrupt.
        !           428:  */
        !           429: neintr(unit)
        !           430: {
        !           431:        register struct ne_softc *ns = &ne_softc[unit];
        !           432:        u_char cmd,isr;
        !           433: 
        !           434:        /* Save cmd, clear interrupt */
        !           435:        cmd = inb (nec+ds_cmd);
        !           436: loop:
        !           437:        isr = inb (nec+ds0_isr);
        !           438:        outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);
        !           439:        outb(nec+ds0_isr, isr);
        !           440: 
        !           441:        /* Receiver error */
        !           442:        if (isr & DSIS_RXE) {
        !           443:                /* need to read these registers to clear status */
        !           444:                (void) inb(nec+ ds0_rsr);
        !           445:                (void) inb(nec+ 0xD);
        !           446:                (void) inb(nec + 0xE);
        !           447:                (void) inb(nec + 0xF);
        !           448:                ns->ns_if.if_ierrors++;
        !           449:        }
        !           450: 
        !           451:        /* We received something; rummage thru tiny ring buffer */
        !           452:        if (isr & (DSIS_RX|DSIS_RXE|DSIS_ROVRN)) {
        !           453:                u_char pend,lastfree;
        !           454: 
        !           455:                outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
        !           456:                pend = inb(nec+ds1_curr);
        !           457:                outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
        !           458:                lastfree = inb(nec+ds0_bnry);
        !           459: 
        !           460:                /* Have we wrapped? */
        !           461:                if (lastfree >= RBUFEND/DS_PGSIZE)
        !           462:                        lastfree = RBUF/DS_PGSIZE;
        !           463:                if (pend < lastfree && ns->ns_cur < pend)
        !           464:                        lastfree = ns->ns_cur;
        !           465:                else    if (ns->ns_cur > lastfree)
        !           466:                        lastfree = ns->ns_cur;
        !           467: 
        !           468:                /* Something in the buffer? */
        !           469:                while (pend != lastfree) {
        !           470:                        u_char nxt;
        !           471: 
        !           472:                        /* Extract header from microcephalic board */
        !           473:                        nefetch(&ns->ns_ph,lastfree*DS_PGSIZE,
        !           474:                                sizeof(ns->ns_ph));
        !           475:                        ns->ns_ba = lastfree*DS_PGSIZE+sizeof(ns->ns_ph);
        !           476: 
        !           477:                        /* Incipient paranoia */
        !           478:                        if (ns->ns_ph.pr_status == DSRS_RPC ||
        !           479:                                /* for dequna's */
        !           480:                                ns->ns_ph.pr_status == 0x21)
        !           481:                                nerecv (ns);
        !           482: #ifdef NEDEBUG
        !           483:                        else  {
        !           484:                                printf("cur %x pnd %x lfr %x ",
        !           485:                                        ns->ns_cur, pend, lastfree);
        !           486:                                printf("nxt %x len %x ", ns->ns_ph.pr_nxtpg,
        !           487:                                        (ns->ns_ph.pr_sz1<<8)+ ns->ns_ph.pr_sz0);
        !           488:                                printf("Bogus Sts %x\n", ns->ns_ph.pr_status);  
        !           489:                        }
        !           490: #endif
        !           491: 
        !           492:                        nxt = ns->ns_ph.pr_nxtpg ;
        !           493: 
        !           494:                        /* Sanity check */
        !           495:                        if ( nxt >= RBUF/DS_PGSIZE && nxt <= RBUFEND/DS_PGSIZE
        !           496:                                && nxt <= pend)
        !           497:                                ns->ns_cur = nxt;
        !           498:                        else    ns->ns_cur = nxt = pend;
        !           499: 
        !           500:                        /* Set the boundaries */
        !           501:                        lastfree = nxt;
        !           502:                        outb(nec+ds0_bnry, pred(nxt));
        !           503:                        outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
        !           504:                        pend = inb(nec+ds1_curr);
        !           505:                        outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
        !           506:                }
        !           507:                outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
        !           508:        }
        !           509: 
        !           510:        /* Transmit error */
        !           511:        if (isr & DSIS_TXE) {
        !           512:                ns->ns_flags &= ~DSF_LOCK;
        !           513:                /* Need to read these registers to clear status */
        !           514:                ns->ns_if.if_collisions += inb(nec+ds0_tbcr0);
        !           515:                ns->ns_if.if_oerrors++;
        !           516:        }
        !           517: 
        !           518:        /* Packet Transmitted */
        !           519:        if (isr & DSIS_TX) {
        !           520:                ns->ns_flags &= ~DSF_LOCK;
        !           521:                ++ns->ns_if.if_opackets;
        !           522:                ns->ns_if.if_collisions += inb(nec+ds0_tbcr0);
        !           523:        }
        !           524: 
        !           525:        /* Receiver ovverun? */
        !           526:        if (isr & DSIS_ROVRN) {
        !           527:                log(LOG_ERR, "ne%d: error: isr %x\n", ns-ne_softc, isr
        !           528:                        /*, DSIS_BITS*/);
        !           529:                outb(nec+ds0_rbcr0, 0);
        !           530:                outb(nec+ds0_rbcr1, 0);
        !           531:                outb(nec+ds0_tcr, DSTC_LB0);
        !           532:                outb(nec+ds0_rcr, DSRC_MON);
        !           533:                outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
        !           534:                outb(nec+ds0_rcr, DSRC_AB);
        !           535:                outb(nec+ds0_tcr, 0);
        !           536:        }
        !           537: 
        !           538:        /* Any more to send? */
        !           539:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
        !           540:        nestart(&ns->ns_if);
        !           541:        outb (nec+ds_cmd, cmd);
        !           542:        outb (nec+ds0_imr, 0xff);
        !           543: 
        !           544:        /* Still more to do? */
        !           545:        isr = inb (nec+ds0_isr);
        !           546:        if(isr) goto loop;
        !           547: }
        !           548: 
        !           549: /*
        !           550:  * Ethernet interface receiver interface.
        !           551:  * If input error just drop packet.
        !           552:  * Otherwise examine packet to determine type.  If can't determine length
        !           553:  * from type, then have to drop packet.  Othewise decapsulate
        !           554:  * packet based on type and pass to type specific higher-level
        !           555:  * input routine.
        !           556:  */
        !           557: nerecv(ns)
        !           558:        register struct ne_softc *ns;
        !           559: {
        !           560:        int len,i;
        !           561: 
        !           562:        ns->ns_if.if_ipackets++;
        !           563:        len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8);
        !           564:        if(len < ETHER_MIN_LEN || len > ETHER_MAX_LEN)
        !           565:                return;
        !           566: 
        !           567:        /* this need not be so torturous - one/two bcopys at most into mbufs */
        !           568:        nefetch(ns->ns_pb, ns->ns_ba, min(len,DS_PGSIZE-sizeof(ns->ns_ph)));
        !           569:        if (len > DS_PGSIZE-sizeof(ns->ns_ph)) {
        !           570:                int l = len - (DS_PGSIZE-sizeof(ns->ns_ph)), b ;
        !           571:                u_char *p = ns->ns_pb + (DS_PGSIZE-sizeof(ns->ns_ph));
        !           572: 
        !           573:                if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46;
        !           574:                b = ns->ns_cur*DS_PGSIZE;
        !           575:                
        !           576:                while (l >= DS_PGSIZE) {
        !           577:                        nefetch(p, b, DS_PGSIZE);
        !           578:                        p += DS_PGSIZE; l -= DS_PGSIZE;
        !           579:                        if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46;
        !           580:                        b = ns->ns_cur*DS_PGSIZE;
        !           581:                }
        !           582:                if (l > 0)
        !           583:                        nefetch(p, b, l);
        !           584:        }
        !           585:        /* don't forget checksum! */
        !           586:        len -= sizeof(struct ether_header) + sizeof(long);
        !           587:                        
        !           588:        neread(ns,(caddr_t)(ns->ns_pb), len);
        !           589: }
        !           590: 
        !           591: /*
        !           592:  * Pass a packet to the higher levels.
        !           593:  * We deal with the trailer protocol here.
        !           594:  */
        !           595: neread(ns, buf, len)
        !           596:        register struct ne_softc *ns;
        !           597:        char *buf;
        !           598:        int len;
        !           599: {
        !           600:        register struct ether_header *eh;
        !           601:        struct mbuf *m;
        !           602:        int off, resid;
        !           603:        register struct ifqueue *inq;
        !           604: 
        !           605:        /*
        !           606:         * Deal with trailer protocol: if type is trailer type
        !           607:         * get true type from first 16-bit word past data.
        !           608:         * Remember that type was trailer by setting off.
        !           609:         */
        !           610:        eh = (struct ether_header *)buf;
        !           611:        eh->ether_type = ntohs((u_short)eh->ether_type);
        !           612: #define        nedataaddr(eh, off, type)       ((type)(((caddr_t)((eh)+1)+(off))))
        !           613:        if (eh->ether_type >= ETHERTYPE_TRAIL &&
        !           614:            eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
        !           615:                off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
        !           616:                if (off >= ETHERMTU) return;            /* sanity */
        !           617:                eh->ether_type = ntohs(*nedataaddr(eh, off, u_short *));
        !           618:                resid = ntohs(*(nedataaddr(eh, off+2, u_short *)));
        !           619:                if (off + resid > len) return;          /* sanity */
        !           620:                len = off + resid;
        !           621:        } else  off = 0;
        !           622: 
        !           623:        if (len == 0) return;
        !           624: 
        !           625:        /*
        !           626:         * Pull packet off interface.  Off is nonzero if packet
        !           627:         * has trailing header; neget will then force this header
        !           628:         * information to be at the front, but we still have to drop
        !           629:         * the type and length which are at the front of any trailer data.
        !           630:         */
        !           631:        m = neget(buf, len, off, &ns->ns_if);
        !           632:        if (m == 0) return;
        !           633: 
        !           634:        ether_input(&ns->ns_if, eh, m);
        !           635: }
        !           636: 
        !           637: /*
        !           638:  * Supporting routines
        !           639:  */
        !           640: 
        !           641: /*
        !           642:  * Pull read data off a interface.
        !           643:  * Len is length of data, with local net header stripped.
        !           644:  * Off is non-zero if a trailer protocol was used, and
        !           645:  * gives the offset of the trailer information.
        !           646:  * We copy the trailer information and then all the normal
        !           647:  * data into mbufs.  When full cluster sized units are present
        !           648:  * we copy into clusters.
        !           649:  */
        !           650: struct mbuf *
        !           651: neget(buf, totlen, off0, ifp)
        !           652:        caddr_t buf;
        !           653:        int totlen, off0;
        !           654:        struct ifnet *ifp;
        !           655: {
        !           656:        struct mbuf *top, **mp, *m, *p;
        !           657:        int off = off0, len;
        !           658:        register caddr_t cp = buf;
        !           659:        char *epkt;
        !           660: 
        !           661:        buf += sizeof(struct ether_header);
        !           662:        cp = buf;
        !           663:        epkt = cp + totlen;
        !           664: 
        !           665: 
        !           666:        if (off) {
        !           667:                cp += off + 2 * sizeof(u_short);
        !           668:                totlen -= 2 * sizeof(u_short);
        !           669:        }
        !           670: 
        !           671:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           672:        if (m == 0)
        !           673:                return (0);
        !           674:        m->m_pkthdr.rcvif = ifp;
        !           675:        m->m_pkthdr.len = totlen;
        !           676:        m->m_len = MHLEN;
        !           677: 
        !           678:        top = 0;
        !           679:        mp = &top;
        !           680:        while (totlen > 0) {
        !           681:                if (top) {
        !           682:                        MGET(m, M_DONTWAIT, MT_DATA);
        !           683:                        if (m == 0) {
        !           684:                                m_freem(top);
        !           685:                                return (0);
        !           686:                        }
        !           687:                        m->m_len = MLEN;
        !           688:                }
        !           689:                len = min(totlen, epkt - cp);
        !           690:                if (len >= MINCLSIZE) {
        !           691:                        MCLGET(m, M_DONTWAIT);
        !           692:                        if (m->m_flags & M_EXT)
        !           693:                                m->m_len = len = min(len, MCLBYTES);
        !           694:                        else
        !           695:                                len = m->m_len;
        !           696:                } else {
        !           697:                        /*
        !           698:                         * Place initial small packet/header at end of mbuf.
        !           699:                         */
        !           700:                        if (len < m->m_len) {
        !           701:                                if (top == 0 && len + max_linkhdr <= m->m_len)
        !           702:                                        m->m_data += max_linkhdr;
        !           703:                                m->m_len = len;
        !           704:                        } else
        !           705:                                len = m->m_len;
        !           706:                }
        !           707:                bcopy(cp, mtod(m, caddr_t), (unsigned)len);
        !           708:                cp += len;
        !           709:                *mp = m;
        !           710:                mp = &m->m_next;
        !           711:                totlen -= len;
        !           712:                if (cp == epkt)
        !           713:                        cp = buf;
        !           714:        }
        !           715:        return (top);
        !           716: }
        !           717: 
        !           718: /*
        !           719:  * Process an ioctl request.
        !           720:  */
        !           721: neioctl(ifp, cmd, data)
        !           722:        register struct ifnet *ifp;
        !           723:        int cmd;
        !           724:        caddr_t data;
        !           725: {
        !           726:        register struct ifaddr *ifa = (struct ifaddr *)data;
        !           727:        struct ne_softc *ns = &ne_softc[ifp->if_unit];
        !           728:        struct ifreq *ifr = (struct ifreq *)data;
        !           729:        int s = splimp(), error = 0;
        !           730: 
        !           731: 
        !           732:        switch (cmd) {
        !           733: 
        !           734:        case SIOCSIFADDR:
        !           735:                ifp->if_flags |= IFF_UP;
        !           736: 
        !           737:                switch (ifa->ifa_addr->sa_family) {
        !           738: #ifdef INET
        !           739:                case AF_INET:
        !           740:                        neinit(ifp->if_unit);   /* before arpwhohas */
        !           741:                        ((struct arpcom *)ifp)->ac_ipaddr =
        !           742:                                IA_SIN(ifa)->sin_addr;
        !           743:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
        !           744:                        break;
        !           745: #endif
        !           746: #ifdef NS
        !           747:                case AF_NS:
        !           748:                    {
        !           749:                        register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
        !           750: 
        !           751:                        if (ns_nullhost(*ina))
        !           752:                                ina->x_host = *(union ns_host *)(ns->ns_addr);
        !           753:                        else {
        !           754:                                /* 
        !           755:                                 * The manual says we can't change the address 
        !           756:                                 * while the receiver is armed,
        !           757:                                 * so reset everything
        !           758:                                 */
        !           759:                                ifp->if_flags &= ~IFF_RUNNING; 
        !           760:                                bcopy((caddr_t)ina->x_host.c_host,
        !           761:                                    (caddr_t)ns->ns_addr, sizeof(ns->ns_addr));
        !           762:                        }
        !           763:                        neinit(ifp->if_unit); /* does ne_setaddr() */
        !           764:                        break;
        !           765:                    }
        !           766: #endif
        !           767:                default:
        !           768:                        neinit(ifp->if_unit);
        !           769:                        break;
        !           770:                }
        !           771:                break;
        !           772: 
        !           773:        case SIOCSIFFLAGS:
        !           774:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !           775:                    ifp->if_flags & IFF_RUNNING) {
        !           776:                        ifp->if_flags &= ~IFF_RUNNING;
        !           777:                        outb(nec+ds_cmd,DSCM_STOP|DSCM_NODMA);
        !           778:                } else if (ifp->if_flags & IFF_UP &&
        !           779:                    (ifp->if_flags & IFF_RUNNING) == 0)
        !           780:                        neinit(ifp->if_unit);
        !           781:                break;
        !           782: 
        !           783: #ifdef notdef
        !           784:        case SIOCGHWADDR:
        !           785:                bcopy((caddr_t)ns->ns_addr, (caddr_t) &ifr->ifr_data,
        !           786:                        sizeof(ns->ns_addr));
        !           787:                break;
        !           788: #endif
        !           789: 
        !           790:        default:
        !           791:                error = EINVAL;
        !           792:        }
        !           793:        splx(s);
        !           794:        return (error);
        !           795: }
        !           796: #endif

unix.superglobalmegacorp.com

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