Annotation of Net2/arch/i386/isa/if_is.c, revision 1.1.1.3

1.1.1.3 ! root        1: /*
        !             2:  * Isolan AT 4141-0 Ethernet driver
        !             3:  * Isolink 4110 
1.1       root        4:  *
1.1.1.3 ! root        5:  * By Paul Richards 
1.1       root        6:  *
1.1.1.3 ! root        7:  * Copyright (C) 1993, Paul Richards. This software may be used, modified,
        !             8:  *   copied, distributed, and sold, in both source and binary form provided
        !             9:  *   that the above copyright and these terms are retained. Under no
        !            10:  *   circumstances is the author responsible for the proper functioning
        !            11:  *   of this software, nor does the author assume any responsibility
        !            12:  *   for damages incurred with its use.
1.1       root       13:  *
1.1.1.3 ! root       14: */
1.1       root       15: 
1.1.1.3 ! root       16: /* TODO
        !            17: 
        !            18: 1) Add working multicast support
        !            19: 2) Use better allocation of memory to card
        !            20: 3) Advertise for more packets until all transmit buffers are full
        !            21: 4) Add more of the timers/counters e.g. arpcom.opackets etc.
        !            22: */
1.1       root       23: 
                     24: #include "is.h"
                     25: #if NIS > 0
                     26: 
1.1.1.3 ! root       27: #include "bpfilter.h"
        !            28: 
1.1       root       29: #include "param.h"
1.1.1.3 ! root       30: #include "errno.h"
        !            31: #include "ioctl.h"
1.1       root       32: #include "mbuf.h"
                     33: #include "socket.h"
                     34: #include "syslog.h"
                     35: 
                     36: #include "net/if.h"
1.1.1.3 ! root       37: #include "net/if_dl.h"
        !            38: #include "net/if_types.h"
1.1       root       39: #include "net/netisr.h"
                     40: 
                     41: #ifdef INET
                     42: #include "netinet/in.h"
                     43: #include "netinet/in_systm.h"
                     44: #include "netinet/in_var.h"
                     45: #include "netinet/ip.h"
                     46: #include "netinet/if_ether.h"
                     47: #endif
                     48: 
                     49: #ifdef NS
                     50: #include "netns/ns.h"
                     51: #include "netns/ns_if.h"
                     52: #endif
                     53: 
1.1.1.3 ! root       54: #if NBPFILTER > 0
        !            55: #include "net/bpf.h"
        !            56: #include "net/bpfdesc.h"
        !            57: #endif
        !            58: 
1.1       root       59: #include "i386/isa/isa_device.h"
                     60: #include "i386/isa/if_isreg.h"
                     61: #include "i386/isa/icu.h"
                     62: 
                     63: #include "vm/vm.h"
                     64: 
                     65: 
                     66: 
                     67: #define ETHER_MIN_LEN 64
1.1.1.3 ! root       68: #define ETHER_MAX_LEN   1518
        !            69: #define ETHER_ADDR_LEN  6
        !            70: 
1.1       root       71: 
                     72: /*
                     73:  * Ethernet software status per interface.
                     74:  *
                     75:  * Each interface is referenced by a network interface structure,
1.1.1.3 ! root       76:  * arpcom.ac_if, which the routing code uses to locate the interface.
1.1       root       77:  * This structure contains the output queue for the interface, its address, ...
                     78:  */
                     79: struct is_softc {
1.1.1.3 ! root       80:        struct  arpcom arpcom;          /* Ethernet common part */
        !            81:        int iobase;                     /* IO base address of card */
        !            82:        struct mds      *rd;
        !            83:        struct mds      *td;
        !            84:        unsigned char   *rbuf;
        !            85:        unsigned char   *tbuf;
1.1       root       86:        int     last_rd;
                     87:        int     last_td;
                     88:        int     no_td;
1.1.1.3 ! root       89:         caddr_t bpf;                   /* BPF "magic cookie" */
        !            90: 
1.1       root       91: } is_softc[NIS] ;
                     92: 
1.1.1.3 ! root       93: struct init_block init_block[NIS];
        !            94: 
        !            95: /* Function prototypes */
        !            96: int is_probe(),is_attach(),is_watchdog();
        !            97: int is_ioctl(),is_init(),is_start();
        !            98: 
        !            99: static inline void is_rint(int unit);
        !           100: static inline void isread(struct is_softc*, unsigned char*, int);
1.1       root      101: 
1.1.1.3 ! root      102: struct mbuf *isget();
1.1       root      103: 
1.1.1.3 ! root      104: struct isa_driver isdriver = {
        !           105:        is_probe,
        !           106:        is_attach,
        !           107:        "is"
        !           108: };
        !           109: 
        !           110: iswrcsr(unit,port,val)
        !           111:        int unit;
1.1       root      112:        u_short port;
                    113:        u_short val;
                    114: {
1.1.1.3 ! root      115:        int iobase;
        !           116: 
        !           117:        iobase = is_softc[unit].iobase;
        !           118:        outw(iobase+RAP,port);
        !           119:        outw(iobase+RDP,val);
1.1       root      120: }
                    121: 
1.1.1.3 ! root      122: u_short isrdcsr(unit,port)
        !           123:        int unit;
1.1       root      124:        u_short port;
                    125: {
1.1.1.3 ! root      126:        int iobase;
        !           127:        
        !           128:        iobase = is_softc[unit].iobase;
        !           129:        outw(iobase+RAP,port);
        !           130:        return(inw(iobase+RDP));
1.1       root      131: } 
                    132: 
1.1.1.3 ! root      133: is_probe(isa_dev)
        !           134:        struct isa_device *isa_dev;
1.1       root      135: {
                    136:        int val,i,s;
1.1.1.3 ! root      137:        int unit = isa_dev->id_unit ;
        !           138:        register struct is_softc *is = &is_softc[unit];
1.1       root      139: 
1.1.1.3 ! root      140:        is->iobase = isa_dev->id_iobase;
1.1       root      141: 
                    142:        /* Stop the lance chip, put it known state */   
1.1.1.3 ! root      143:        iswrcsr(unit,0,STOP);
1.1       root      144:        DELAY(100);
                    145: 
                    146:        /* is there a lance? */
1.1.1.3 ! root      147:        iswrcsr(unit,3, 0xffff);
        !           148:        if (isrdcsr(unit,3) != 7) {
        !           149:                is->iobase = 0;
1.1       root      150:                return (0);
                    151:        }
1.1.1.3 ! root      152:        iswrcsr(unit,3, 0);
1.1       root      153: 
                    154:        /* Extract board address */
1.1.1.3 ! root      155:        for(i=0;i<ETHER_ADDR_LEN;i++)
        !           156:                is->arpcom.ac_enaddr[i]=inb(is->iobase+(i*2));
1.1       root      157: 
                    158:        return (1);
                    159: }
                    160: 
                    161: 
                    162: 
                    163: /*
                    164:  * Reset of interface.
                    165:  */
1.1.1.3 ! root      166: int is_reset(int unit)
1.1       root      167: {
1.1.1.3 ! root      168:        int s;
1.1       root      169:        if (unit >= NIS)
                    170:                return;
1.1.1.3 ! root      171:        s = splnet();
1.1       root      172:        printf("is%d: reset\n", unit);
1.1.1.3 ! root      173:        is_init(unit);
        !           174:        s = splx();
1.1       root      175: }
                    176:  
                    177: /*
                    178:  * Interface exists: make available by filling in network interface
                    179:  * record.  System will initialize the interface when it is ready
                    180:  * to accept packets.  We get the ethernet address here.
                    181:  */
1.1.1.3 ! root      182: int is_attach(isa_dev)
        !           183:        struct isa_device *isa_dev;
1.1       root      184: {
1.1.1.3 ! root      185:        int unit = isa_dev->id_unit;
        !           186:        struct is_softc *is = &is_softc[unit];
        !           187:        struct ifnet *ifp = &is->arpcom.ac_if;
        !           188:         struct ifaddr *ifa;
        !           189:         struct sockaddr_dl *sdl;
        !           190: 
1.1       root      191: 
                    192: 
                    193:        ifp->if_unit = unit;
                    194:        ifp->if_name = isdriver.name ;
                    195:        ifp->if_mtu = ETHERMTU;
                    196:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
1.1.1.3 ! root      197:        ifp->if_init = is_init;
1.1       root      198:        ifp->if_output = ether_output;
1.1.1.3 ! root      199:        ifp->if_start = is_start;
        !           200:        ifp->if_ioctl = is_ioctl;
        !           201:        ifp->if_reset = is_reset;
        !           202:        ifp->if_watchdog = is_watchdog;
        !           203: 
        !           204:        /* Set up DMA */
        !           205:        isa_dmacascade(isa_dev->id_drq);
        !           206: 
1.1       root      207:        if_attach(ifp);
1.1.1.2   root      208: 
1.1.1.3 ! root      209: /*
        !           210:          * Search down the ifa address list looking for the AF_LINK type
        !           211: entry
        !           212:          */
        !           213:         ifa = ifp->if_addrlist;
        !           214:         while ((ifa != 0) && (ifa->ifa_addr != 0) &&
        !           215:             (ifa->ifa_addr->sa_family != AF_LINK))
        !           216:                 ifa = ifa->ifa_next;
        !           217: 
        !           218:         /*
        !           219:          * If we find an AF_LINK type entry, we will fill
        !           220:         * in the hardware address for this interface.
        !           221:          */
        !           222:         if ((ifa != 0) && (ifa->ifa_addr != 0)) {
        !           223:                 /*
        !           224:                  * Fill in the link level address for this interface
        !           225:                  */
        !           226:                 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
        !           227:                 sdl->sdl_type = IFT_ETHER;
        !           228:                 sdl->sdl_alen = ETHER_ADDR_LEN;
        !           229:                 sdl->sdl_slen = 0;
        !           230:                 bcopy(is->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN);
        !           231:         }
        !           232: 
        !           233:        printf ("is%d: address %s\n", unit,
        !           234:                ether_sprintf(is->arpcom.ac_enaddr)) ;
        !           235: 
        !           236: #if NBPFILTER > 0
        !           237:         bpfattach(&is->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
        !           238: #endif
        !           239: }
        !           240: 
        !           241: int
        !           242: is_watchdog(unit)
        !           243:         int unit;
        !           244: {
        !           245:         log(LOG_ERR, "is%d: device timeout\n", unit);
        !           246: 
        !           247:         is_reset(unit);
1.1       root      248: }
                    249: 
                    250: 
                    251: /* Lance initialisation block set up */
1.1.1.3 ! root      252: init_mem(unit)
        !           253:        int unit;
1.1       root      254: {
                    255:        int i;
                    256:        u_long temp;
1.1.1.3 ! root      257:        struct is_softc *is = &is_softc[unit];
1.1       root      258: 
                    259:        /* Allocate memory */
                    260: /* Temporary hack, will use kmem_alloc in future */
                    261: #define MAXMEM ((NRBUF+NTBUF)*(BUFSIZE) + (NRBUF+NTBUF)*sizeof(struct mds) + 8)
1.1.1.3 ! root      262: static u_char lance_mem[NIS][MAXMEM];
1.1       root      263: 
                    264: 
                    265:        /* Align message descriptors on quad word boundary 
                    266:                (this is essential) */
                    267: 
1.1.1.3 ! root      268:        temp = (u_long) &lance_mem[unit];
1.1       root      269:        temp = (temp+8) - (temp%8);
1.1.1.3 ! root      270:        is->rd = (struct mds *) temp;
        !           271:        is->td = (struct mds *) (temp + (NRBUF*sizeof(struct mds)));
1.1       root      272:        temp += (NRBUF+NTBUF) * sizeof(struct mds);
                    273: 
1.1.1.3 ! root      274:        init_block[unit].mode = 0;
1.1       root      275:        
                    276: 
1.1.1.3 ! root      277: 
        !           278:        init_block[unit].rdra = kvtop(is->rd);
        !           279:        init_block[unit].rlen = ((kvtop(is->rd) >> 16) & 0xff) | (RLEN<<13);
        !           280:        init_block[unit].tdra = kvtop(is->td);
        !           281:        init_block[unit].tlen = ((kvtop(is->td) >> 16) & 0xff) | (TLEN<<13);
1.1       root      282: 
                    283:        /* Set up receive ring descriptors */
1.1.1.3 ! root      284:        is->rbuf = (unsigned char *)temp;
1.1       root      285:        for (i=0; i<NRBUF; i++) {
1.1.1.3 ! root      286:                (is->rd+i)->addr = kvtop(temp);
        !           287:                (is->rd+i)->flags= ((kvtop(temp) >> 16) & 0xff) | OWN;
        !           288:                (is->rd+i)->bcnt = -BUFSIZE;
        !           289:                (is->rd+i)->mcnt = 0;
1.1       root      290:                temp += BUFSIZE;
                    291:        }
                    292: 
                    293:        /* Set up transmit ring descriptors */
1.1.1.3 ! root      294:        is->tbuf = (unsigned char *)temp;
        !           295: #if ISDEBUG > 4
        !           296:        printf("rd = %x,td = %x, rbuf = %x, tbuf = %x,td+1=%x\n",is->rd,is->td,is->rbuf,is->tbuf,is->td+1);
1.1       root      297: #endif
                    298:        for (i=0; i<NTBUF; i++) {
1.1.1.3 ! root      299:                (is->td+i)->addr = kvtop(temp);
        !           300:                (is->td+i)->flags= ((kvtop(temp) >> 16) & 0xff);
        !           301:                (is->td+i)->bcnt = 0;
        !           302:                (is->td+i)->mcnt = 0;
1.1       root      303:                temp += BUFSIZE;
                    304:        }
                    305: 
                    306: }
                    307: 
                    308: /*
                    309:  * Initialization of interface; set up initialization block
                    310:  * and transmit/receive descriptor rings.
                    311:  */
1.1.1.3 ! root      312: is_init(unit)
1.1       root      313:        int unit;
                    314: {
1.1.1.3 ! root      315:        register struct is_softc *is = &is_softc[unit];
        !           316:        struct ifnet *ifp = &is->arpcom.ac_if;
1.1       root      317:        int s;
                    318:        register i;
                    319: 
1.1.1.3 ! root      320:        /* Address not known */
1.1       root      321:        if (ifp->if_addrlist == (struct ifaddr *)0) return;
                    322: 
1.1.1.3 ! root      323:        s = splnet();
        !           324:        is->last_rd = is->last_td = is->no_td = 0;
1.1       root      325: 
                    326:        /* Set up lance's memory area */
1.1.1.3 ! root      327:        init_mem(unit);
1.1       root      328: 
                    329:        /* Stop Lance to get access to other registers */
1.1.1.3 ! root      330:        iswrcsr(unit,0,STOP);
        !           331: 
        !           332:        /* Get ethernet address */
        !           333:        for (i=0; i<ETHER_ADDR_LEN; i++) 
        !           334:                init_block[unit].padr[i] = is->arpcom.ac_enaddr[i];
        !           335: 
        !           336: #if NBPFILTER > 0
        !           337:         /*
        !           338:          * Initialize multicast address hashing registers to accept
        !           339:          *       all multicasts (only used when in promiscuous mode)
        !           340:          */
        !           341:         for (i = 0; i < 8; ++i)
        !           342:                init_block[unit].ladrf[i] = 0xff;
        !           343: #endif
        !           344: 
1.1       root      345: 
                    346:        /* I wish I knew what this was */
1.1.1.3 ! root      347:        iswrcsr(unit,3,0);
1.1       root      348: 
                    349:        /* Give lance the physical address of its memory area */
1.1.1.3 ! root      350:        iswrcsr(unit,1,kvtop(&init_block[unit]));
        !           351:        iswrcsr(unit,2,(kvtop(&init_block[unit]) >> 16) & 0xff);
1.1       root      352: 
                    353:        /* OK, let's try and initialise the Lance */
1.1.1.3 ! root      354:        iswrcsr(unit,0,INIT);
1.1       root      355: 
                    356:        /* Wait for initialisation to finish */
                    357:        for(i=0; i<1000; i++){
1.1.1.3 ! root      358:                if (isrdcsr(unit,0)&IDON)
1.1       root      359:                        break;
                    360:        }
1.1.1.3 ! root      361:        if (isrdcsr(unit,0)&IDON) {
1.1       root      362:                /* Start lance */
1.1.1.3 ! root      363:                iswrcsr(unit,0,STRT|IDON|INEA);
        !           364:                ifp->if_flags |= IFF_RUNNING;
        !           365:                ifp->if_flags &= ~IFF_OACTIVE;
        !           366: 
        !           367:                is_start(ifp);
1.1       root      368:        }
                    369:        else 
1.1.1.3 ! root      370:                printf("is%d: card failed to initialise\n", unit);
1.1       root      371:        
1.1.1.3 ! root      372:         (void) splx(s);
1.1       root      373: }
                    374: 
                    375: /*
                    376:  * Setup output on interface.
                    377:  * Get another datagram to send off of the interface queue,
                    378:  * and map it to the interface before starting the output.
                    379:  * called only at splimp or interrupt level.
                    380:  */
1.1.1.3 ! root      381: is_start(ifp)
1.1       root      382:        struct ifnet *ifp;
                    383: {
1.1.1.3 ! root      384:        int unit = ifp->if_unit;
        !           385:        register struct is_softc *is = &is_softc[unit];
1.1       root      386:        struct mbuf *m0, *m;
                    387:        unsigned char *buffer;
                    388:        u_short len;
                    389:        int i;
                    390:        struct mds *cdm;
                    391: 
                    392: 
1.1.1.3 ! root      393:        if ((is->arpcom.ac_if.if_flags & IFF_RUNNING) == 0)
1.1       root      394:                return;
                    395: 
                    396:        do {
1.1.1.3 ! root      397:                cdm = (is->td + is->last_td);
1.1       root      398:                if (cdm->flags&OWN)
                    399:                        return;
                    400:        
1.1.1.3 ! root      401:                IF_DEQUEUE(&is->arpcom.ac_if.if_snd, m);
1.1       root      402: 
                    403:                if (m == 0)
                    404:                        return;
                    405: 
                    406:                /*
                    407:                * Copy the mbuf chain into the transmit buffer
                    408:                */
                    409: 
1.1.1.3 ! root      410:                buffer = is->tbuf+(BUFSIZE*is->last_td);
1.1       root      411:                len=0;
                    412:                for (m0=m; m != 0; m=m->m_next) {
                    413:                        bcopy(mtod(m,caddr_t),buffer,m->m_len);
                    414:                        buffer += m->m_len;
                    415:                        len += m->m_len;
                    416:                }
1.1.1.3 ! root      417: #if NBPFILTER > 0
        !           418:         if (is->bpf) {
        !           419:                 u_short etype;
        !           420:                 int off, datasize, resid;
        !           421:                 struct ether_header *eh;
        !           422:                 struct trailer_header {
        !           423:                         u_short ether_type;
        !           424:                         u_short ether_residual;
        !           425:                 } trailer_header;
        !           426:                 char ether_packet[ETHER_MAX_LEN];
        !           427:                 char *ep;
        !           428: 
        !           429:                 ep = ether_packet;
        !           430: 
        !           431:                 /*
        !           432:                  * We handle trailers below:
        !           433:                  * Copy ether header first, then residual data,
        !           434:                  * then data. Put all this in a temporary buffer
        !           435:                  * 'ether_packet' and send off to bpf. Since the
        !           436:                  * system has generated this packet, we assume
        !           437:                  * that all of the offsets in the packet are
        !           438:                  * correct; if they're not, the system will almost
        !           439:                  * certainly crash in m_copydata.
        !           440:                  * We make no assumptions about how the data is
        !           441:                  * arranged in the mbuf chain (i.e. how much
        !           442:                  * data is in each mbuf, if mbuf clusters are
        !           443:                  * used, etc.), which is why we use m_copydata
        !           444:                  * to get the ether header rather than assume
        !           445:                  * that this is located in the first mbuf.
        !           446:                  */
        !           447:                 /* copy ether header */
        !           448:                 m_copydata(m0, 0, sizeof(struct ether_header), ep);
        !           449:                 eh = (struct ether_header *) ep;
        !           450:                 ep += sizeof(struct ether_header);
        !           451:                 etype = ntohs(eh->ether_type);
        !           452:                 if (etype >= ETHERTYPE_TRAIL &&
        !           453:                     etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
        !           454:                         datasize = ((etype - ETHERTYPE_TRAIL) << 9);
        !           455:                         off = datasize + sizeof(struct ether_header);
        !           456: 
        !           457:                         /* copy trailer_header into a data structure */
        !           458:                         m_copydata(m0, off, sizeof(struct trailer_header),
        !           459:                                 &trailer_header.ether_type);
        !           460: 
        !           461:                         /* copy residual data */
        !           462:                        resid = trailer_header.ether_residual -
        !           463:                                sizeof(struct trailer_header);
        !           464:                        resid = ntohs(resid);
        !           465:                         m_copydata(m0, off+sizeof(struct trailer_header),
        !           466:                                 resid, ep);
        !           467:                         ep += resid;
        !           468: 
        !           469:                         /* copy data */
        !           470:                         m_copydata(m0, sizeof(struct ether_header),
        !           471:                                 datasize, ep);
        !           472:                         ep += datasize;
        !           473: 
        !           474:                         /* restore original ether packet type */
        !           475:                         eh->ether_type = trailer_header.ether_type;
        !           476: 
        !           477:                         bpf_tap(is->bpf, ether_packet, ep - ether_packet);
        !           478:                 } else
        !           479:                         bpf_mtap(is->bpf, m0);
        !           480:         }
        !           481: #endif
        !           482: 
1.1       root      483:                
                    484:                m_freem(m0);
                    485:                len = MAX(len,ETHER_MIN_LEN);
                    486: 
                    487:                /*
                    488:                * Init transmit registers, and set transmit start flag.
                    489:                */
                    490: 
                    491:                cdm->flags |= (OWN|STP|ENP);
                    492:                cdm->bcnt = -len;
                    493:                cdm->mcnt = 0;
1.1.1.3 ! root      494: #if ISDEBUG > 3
        !           495:                xmit_print(unit,is->last_td);
1.1       root      496: #endif
                    497:                
1.1.1.3 ! root      498:                iswrcsr(unit,0,TDMD|INEA);
        !           499:                if (++is->last_td >= NTBUF)
        !           500:                        is->last_td=0;
        !           501:                }while(++is->no_td < NTBUF);
        !           502:                is->no_td = NTBUF;
        !           503:                is->arpcom.ac_if.if_flags |= IFF_OACTIVE;       
        !           504: #if ISDEBUG >4
        !           505:        printf("no_td = %x, last_td = %x\n",is->no_td, is->last_td);
1.1       root      506: #endif
                    507:                return(0);      
                    508: }
                    509: 
                    510: 
                    511: /*
                    512:  * Controller interrupt.
                    513:  */
                    514: isintr(unit)
                    515: {
1.1.1.3 ! root      516:        register struct is_softc *is = &is_softc[unit];
1.1       root      517:        u_short isr;
                    518: 
1.1.1.3 ! root      519:        while((isr=isrdcsr(unit,0))&INTR) {
1.1       root      520:                if (isr&ERR) {
1.1.1.3 ! root      521:                        if (isr&BABL){
        !           522:                                printf("is%d: BABL\n",unit);
        !           523:                                is->arpcom.ac_if.if_oerrors++;
        !           524:                        }
        !           525:                        if (isr&CERR) {
        !           526:                                printf("is%d: CERR\n",unit);
        !           527:                                is->arpcom.ac_if.if_collisions++;
        !           528:                        }
        !           529:                        if (isr&MISS) {
        !           530:                                printf("is%d: MISS\n",unit);
        !           531:                                is->arpcom.ac_if.if_ierrors++;
        !           532:                        }
1.1       root      533:                        if (isr&MERR)
1.1.1.3 ! root      534:                                printf("is%d: MERR\n",unit);
        !           535:                        iswrcsr(unit,0,BABL|CERR|MISS|MERR|INEA);
1.1       root      536:                }
1.1.1.3 ! root      537:                if (!(isr&RXON)) {
        !           538:                        printf("is%d: !(isr&RXON)\n", unit);
        !           539:                        is->arpcom.ac_if.if_ierrors++;
        !           540:                        is_reset(unit);
1.1       root      541:                        return(1);
                    542:                }
1.1.1.3 ! root      543:                if (!(isr&TXON)) {
        !           544:                        printf("is%d: !(isr&TXON)\n", unit);
        !           545:                        is->arpcom.ac_if.if_oerrors++;
        !           546:                        is_reset(unit);
1.1       root      547:                        return(1);
                    548:                }
1.1.1.3 ! root      549: 
1.1       root      550:                if (isr&RINT) {
1.1.1.3 ! root      551:                        /* reset watchdog timer */
        !           552:                        is->arpcom.ac_if.if_timer = 0;
        !           553:                        is_rint(unit);
1.1       root      554:                }
                    555:                if (isr&TINT) {
1.1.1.3 ! root      556:                        /* reset watchdog timer */
        !           557:                        is->arpcom.ac_if.if_timer = 0;
        !           558:                        iswrcsr(unit,0,TINT|INEA);
1.1       root      559:                        istint(unit);
                    560:                }
                    561:        }
                    562: }
                    563: 
                    564: istint(unit) 
                    565:        int unit;
                    566: {
                    567:        struct is_softc *is = &is_softc[unit];
1.1.1.3 ! root      568:        register struct ifnet *ifp = &is->arpcom.ac_if;
1.1       root      569:        int i,loopcount=0;
                    570:        struct mds *cdm;
                    571: 
1.1.1.3 ! root      572:        is->arpcom.ac_if.if_opackets++;
1.1       root      573:        do {
                    574:                if ((i=is->last_td - is->no_td) < 0)
                    575:                        i+=NTBUF;
1.1.1.3 ! root      576:                cdm = (is->td+i);
        !           577: #if ISDEBUG >4
1.1       root      578:        printf("Trans cdm = %x\n",cdm);
                    579: #endif
                    580:                if (cdm->flags&OWN) {
                    581:                        if (loopcount)
                    582:                                break;
                    583:                        return;
                    584:                }
                    585:                loopcount++;    
1.1.1.3 ! root      586:                is->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
1.1       root      587:        }while(--is->no_td > 0);
1.1.1.3 ! root      588:        is_start(ifp);  
1.1       root      589:        
                    590: }
                    591: 
                    592: #define NEXTRDS \
1.1.1.3 ! root      593:        if (++rmd == NRBUF) rmd=0, cdm=is->rd; else ++cdm
1.1       root      594:        
1.1.1.3 ! root      595: /* only called from one place, so may as well integrate */
        !           596: static inline void is_rint(int unit)
1.1       root      597: {
                    598:        register struct is_softc *is=&is_softc[unit];
                    599:        register int rmd = is->last_rd;
1.1.1.3 ! root      600:        struct mds *cdm = (is->rd + rmd);
1.1       root      601: 
                    602:        /* Out of sync with hardware, should never happen */
                    603:        
                    604:        if (cdm->flags & OWN) {
1.1.1.3 ! root      605:                printf("is%d: error: out of sync\n",unit);
        !           606:                iswrcsr(unit,0,RINT|INEA);
1.1       root      607:                return;
                    608:        }
                    609: 
                    610:        /* Process all buffers with valid data */
                    611:        while (!(cdm->flags&OWN)) {
                    612:                /* Clear interrupt to avoid race condition */
1.1.1.3 ! root      613:                iswrcsr(unit,0,RINT|INEA);
1.1       root      614:                if (cdm->flags&ERR) {
                    615:                        if (cdm->flags&FRAM)
1.1.1.3 ! root      616:                                printf("is%d: FRAM\n",unit);
1.1       root      617:                        if (cdm->flags&OFLO)
1.1.1.3 ! root      618:                                printf("is%d: OFLO\n",unit);
1.1       root      619:                        if (cdm->flags&CRC)
1.1.1.3 ! root      620:                                printf("is%d: CRC\n",unit);
1.1       root      621:                        if (cdm->flags&RBUFF)
1.1.1.3 ! root      622:                                printf("is%d: RBUFF\n",unit);
1.1       root      623:                }else 
                    624:                if (cdm->flags&(STP|ENP) != (STP|ENP)) {
                    625:                        do {
1.1.1.3 ! root      626:                                iswrcsr(unit,0,RINT|INEA);
1.1       root      627:                                cdm->mcnt = 0;
                    628:                                cdm->flags |= OWN;      
                    629:                                NEXTRDS;
                    630:                        }while (!(cdm->flags&(OWN|ERR|STP|ENP)));
                    631:                        is->last_rd = rmd;
1.1.1.3 ! root      632:                        printf("is%d: Chained buffer\n",unit);
1.1       root      633:                        if ((cdm->flags & (OWN|ERR|STP|ENP)) != ENP) {
1.1.1.3 ! root      634:                                is_reset(unit);
1.1       root      635:                                return;
                    636:                        }
                    637:                }else
                    638:                        {
1.1.1.3 ! root      639: #if ISDEBUG >2
        !           640:        recv_print(unit,is->last_rd);
1.1       root      641: #endif
1.1.1.3 ! root      642:                        isread(is,is->rbuf+(BUFSIZE*rmd),(int)cdm->mcnt);
        !           643:                        is->arpcom.ac_if.if_ipackets++;
1.1       root      644:                        }
                    645:                        
                    646:                cdm->flags |= OWN;
                    647:                cdm->mcnt = 0;
                    648:                NEXTRDS;
1.1.1.3 ! root      649: #if ISDEBUG >4
1.1       root      650:        printf("is->last_rd = %x, cdm = %x\n",is->last_rd,cdm);
                    651: #endif
                    652:        } /* while */
                    653:        is->last_rd = rmd;
1.1.1.3 ! root      654: } /* is_rint */
        !           655: 
1.1       root      656: 
                    657: /*
                    658:  * Pass a packet to the higher levels.
                    659:  * We deal with the trailer protocol here.
                    660:  */
1.1.1.3 ! root      661: static inline void 
        !           662: isread(struct is_softc *is, unsigned char *buf, int len)
        !           663: {
        !           664:         register struct ether_header *eh;
        !           665:         struct mbuf *m;
        !           666:         int off, resid;
        !           667:         register struct ifqueue *inq;
        !           668: 
        !           669:         /*
        !           670:          * Deal with trailer protocol: if type is trailer type
        !           671:          * get true type from first 16-bit word past data.
        !           672:          * Remember that type was trailer by setting off.
        !           673:          */
        !           674:         eh = (struct ether_header *)buf;
        !           675:         eh->ether_type = ntohs((u_short)eh->ether_type);
        !           676:         len = len - sizeof(struct ether_header) - 4;
        !           677: #define nedataaddr(eh, off, type)       ((type)(((caddr_t)((eh)+1)+(off))))
        !           678:         if (eh->ether_type >= ETHERTYPE_TRAIL &&
        !           679:             eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
        !           680:                 off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
        !           681:                 if (off >= ETHERMTU) return;            /* sanity */
        !           682:                 eh->ether_type = ntohs(*nedataaddr(eh, off, u_short *));
        !           683:                 resid = ntohs(*(nedataaddr(eh, off+2, u_short *)));
        !           684:                 if (off + resid > len) return;          /* sanity */
        !           685:                 len = off + resid;
        !           686:         } else  off = 0;
        !           687: 
        !           688:         if (len == 0) return;
        !           689: 
        !           690:         /*
        !           691:          * Pull packet off interface.  Off is nonzero if packet
        !           692:          * has trailing header; neget will then force this header
        !           693:          * information to be at the front, but we still have to drop
        !           694:          * the type and length which are at the front of any trailer data.
        !           695:          */
        !           696:         is->arpcom.ac_if.if_ipackets++;
        !           697:         m = isget(buf, len, off, &is->arpcom.ac_if);
        !           698:         if (m == 0) return;
        !           699: #if NBPFILTER > 0
        !           700:         /*
        !           701:          * Check if there's a BPF listener on this interface.
        !           702:          * If so, hand off the raw packet to bpf. 
        !           703:          */
        !           704:         if (is->bpf) {
        !           705:                 bpf_mtap(is->bpf, m);
        !           706: 
        !           707:                 /*
        !           708:                  * Note that the interface cannot be in promiscuous mode if
        !           709:                  * there are no BPF listeners.  And if we are in promiscuous
        !           710:                  * mode, we have to check if this packet is really ours.
        !           711:                  *
        !           712:                  * XXX This test does not support multicasts.
        !           713:                  */
        !           714:                 if ((is->arpcom.ac_if.if_flags & IFF_PROMISC) &&
        !           715:                         bcmp(eh->ether_dhost, is->arpcom.ac_enaddr,
        !           716:                                 sizeof(eh->ether_dhost)) != 0 &&
        !           717:                         bcmp(eh->ether_dhost, etherbroadcastaddr,
        !           718:                                 sizeof(eh->ether_dhost)) != 0) {
        !           719: 
        !           720:                         m_freem(m);
        !           721:                         return;
        !           722:                 }
        !           723:         }
        !           724: #endif
1.1       root      725: 
1.1.1.3 ! root      726: 
        !           727:         ether_input(&is->arpcom.ac_if, eh, m);
1.1       root      728: }
                    729: 
                    730: /*
                    731:  * Supporting routines
                    732:  */
                    733: 
                    734: /*
                    735:  * Pull read data off a interface.
                    736:  * Len is length of data, with local net header stripped.
                    737:  * Off is non-zero if a trailer protocol was used, and
                    738:  * gives the offset of the trailer information.
                    739:  * We copy the trailer information and then all the normal
                    740:  * data into mbufs.  When full cluster sized units are present
                    741:  * we copy into clusters.
                    742:  */
                    743: struct mbuf *
                    744: isget(buf, totlen, off0, ifp)
1.1.1.3 ! root      745:         caddr_t buf;
        !           746:         int totlen, off0;
        !           747:         struct ifnet *ifp;
        !           748: {
        !           749:         struct mbuf *top, **mp, *m, *p;
        !           750:         int off = off0, len;
        !           751:         register caddr_t cp = buf;
        !           752:         char *epkt;
        !           753: 
        !           754:         buf += sizeof(struct ether_header);
        !           755:         cp = buf;
        !           756:         epkt = cp + totlen;
        !           757: 
        !           758: 
        !           759:         if (off) {
        !           760:                 cp += off + 2 * sizeof(u_short);
        !           761:                 totlen -= 2 * sizeof(u_short);
        !           762:         }
        !           763: 
        !           764:         MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           765:         if (m == 0)
        !           766:                 return (0);
        !           767:         m->m_pkthdr.rcvif = ifp;
        !           768:         m->m_pkthdr.len = totlen;
        !           769:         m->m_len = MHLEN;
        !           770:         top = 0;
        !           771:         mp = &top;
        !           772:         while (totlen > 0) {
        !           773:                 if (top) {
        !           774:                         MGET(m, M_DONTWAIT, MT_DATA);
        !           775:                         if (m == 0) {
        !           776:                                 m_freem(top);
        !           777:                                 return (0);
        !           778:                         }
        !           779:                         m->m_len = MLEN;
        !           780:                 }
        !           781:                 len = min(totlen, epkt - cp);
        !           782:                 if (len >= MINCLSIZE) {
        !           783:                         MCLGET(m, M_DONTWAIT);
        !           784:                         if (m->m_flags & M_EXT)
        !           785:                                 m->m_len = len = min(len, MCLBYTES);
        !           786:                         else
        !           787:                                 len = m->m_len;
        !           788:                 } else {
        !           789:                         /*
        !           790:                          * Place initial small packet/header at end of mbuf.
        !           791:                          */
        !           792:                         if (len < m->m_len) {
        !           793:                                 if (top == 0 && len + max_linkhdr <= m->m_len)
        !           794:                                         m->m_data += max_linkhdr;
        !           795:                                 m->m_len = len;
        !           796:                         } else
        !           797:                                 len = m->m_len;
        !           798:                 }
        !           799:                 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
        !           800:                 cp += len;
        !           801:                 *mp = m;
        !           802:                 mp = &m->m_next;
        !           803:                 totlen -= len;
        !           804:                 if (cp == epkt)
        !           805:                         cp = buf;
        !           806:         }
        !           807:         return (top);
1.1       root      808: }
                    809: 
1.1.1.3 ! root      810: 
1.1       root      811: /*
                    812:  * Process an ioctl request.
                    813:  */
1.1.1.3 ! root      814: is_ioctl(ifp, cmd, data)
1.1       root      815:        register struct ifnet *ifp;
                    816:        int cmd;
                    817:        caddr_t data;
                    818: {
                    819:        register struct ifaddr *ifa = (struct ifaddr *)data;
1.1.1.3 ! root      820:        int unit = ifp->if_unit;
        !           821:        struct is_softc *is = &is_softc[unit];
1.1       root      822:        struct ifreq *ifr = (struct ifreq *)data;
1.1.1.3 ! root      823:        int s, error = 0;
1.1       root      824: 
1.1.1.3 ! root      825:        s = splnet();
1.1       root      826: 
                    827:        switch (cmd) {
                    828: 
                    829:        case SIOCSIFADDR:
                    830:                ifp->if_flags |= IFF_UP;
                    831: 
                    832:                switch (ifa->ifa_addr->sa_family) {
                    833: #ifdef INET
                    834:                case AF_INET:
1.1.1.3 ! root      835:                        is_init(ifp->if_unit);  /* before arpwhohas */
        !           836:                         /*
        !           837:                          * See if another station has *our* IP address.
        !           838:                          * i.e.: There is an address conflict! If a
        !           839:                          * conflict exists, a message is sent to the
        !           840:                          * console.
        !           841:                          */
1.1       root      842:                        ((struct arpcom *)ifp)->ac_ipaddr =
                    843:                                IA_SIN(ifa)->sin_addr;
                    844:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
                    845:                        break;
                    846: #endif
                    847: #ifdef NS
1.1.1.3 ! root      848:                 /*
        !           849:                  * XXX - This code is probably wrong
        !           850:                  */
1.1       root      851:                case AF_NS:
                    852:                    {
1.1.1.3 ! root      853:                        register struct arpcom.ac_enaddr *ina = &(IA_SNS(ifa)->sns_addr);
1.1       root      854: 
                    855:                        if (ns_nullhost(*ina))
1.1.1.3 ! root      856:                                ina->x_host = *(union ns_host *)(is->arpcom.ac_enaddr);
1.1       root      857:                        else {
                    858:                                /* 
                    859:                                 */
                    860:                                bcopy((caddr_t)ina->x_host.c_host,
1.1.1.3 ! root      861:                                    (caddr_t)is->arpcom.ac_enaddr, sizeof(is->arpcom.ac_enaddr));
1.1       root      862:                        }
1.1.1.3 ! root      863:                         /*
        !           864:                          * Set new address
        !           865:                          */
        !           866:                        is_init(ifp->if_unit); 
1.1       root      867:                        break;
                    868:                    }
                    869: #endif
                    870:                default:
1.1.1.3 ! root      871:                        is_init(ifp->if_unit);
1.1       root      872:                        break;
                    873:                }
                    874:                break;
                    875: 
                    876:        case SIOCSIFFLAGS:
1.1.1.3 ! root      877:                 /*
        !           878:                  * If interface is marked down and it is running, then stop it
        !           879:                  */
1.1       root      880:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    881:                    ifp->if_flags & IFF_RUNNING) {
1.1.1.3 ! root      882:                        iswrcsr(unit,0,STOP);
1.1       root      883:                        ifp->if_flags &= ~IFF_RUNNING;
1.1.1.3 ! root      884:                } else {
        !           885:                 /*
        !           886:                  * If interface is marked up and it is stopped, then start it
        !           887:                  */
        !           888:                        if ((ifp->if_flags & IFF_UP) &&
        !           889:                                (ifp->if_flags & IFF_RUNNING) == 0)
        !           890:                        is_init(ifp->if_unit);
        !           891:                 }
        !           892: #if NBPFILTER > 0
        !           893:                 if (ifp->if_flags & IFF_PROMISC) {
        !           894:                         /*
        !           895:                          * Set promiscuous mode on interface.
        !           896:                          *      XXX - for multicasts to work, we would need to
        !           897:                          *              write 1's in all bits of multicast
        !           898:                          *              hashing array. For now we assume that
        !           899:                          *              this was done in is_init().
        !           900:                          */
        !           901:                         init_block[unit].mode = PROM;  
        !           902:                 } else
        !           903:                         /*
        !           904:                          * XXX - for multicasts to work, we would need to
        !           905:                          *      rewrite the multicast hashing array with the
        !           906:                          *      proper hash (would have been destroyed above).
        !           907:                          */
        !           908:                        { /* Don't know about this */};
        !           909: #endif
1.1       root      910:                break;
                    911: 
                    912: #ifdef notdef
                    913:        case SIOCGHWADDR:
1.1.1.3 ! root      914:                bcopy((caddr_t)is->arpcom.ac_enaddr, (caddr_t) &ifr->ifr_data,
        !           915:                        sizeof(is->arpcom.ac_enaddr));
1.1       root      916:                break;
                    917: #endif
                    918: 
                    919:        default:
                    920:                error = EINVAL;
                    921:        }
1.1.1.3 ! root      922:        (void) splx(s);
1.1       root      923:        return (error);
                    924: }
                    925: 
1.1.1.3 ! root      926: recv_print(unit,no)
        !           927:        int unit,no;
1.1       root      928: {
1.1.1.3 ! root      929:        register struct is_softc *is=&is_softc[unit];
1.1       root      930:        struct mds *rmd;
1.1.1.3 ! root      931:        int len,i,printed=0;
1.1       root      932:        
1.1.1.3 ! root      933:        rmd = (is->rd+no);
1.1       root      934:        len = rmd->mcnt;
1.1.1.3 ! root      935:        printf("is%d: Receive buffer %d, len = %d\n",unit,no,len);
        !           936:        printf("is%d: Status %x\n",unit,isrdcsr(unit,0));
        !           937:        for (i=0; i<len; i++) {
        !           938:                if (!printed) {
        !           939:                        printed=1;
        !           940:                        printf("is%d: data: ", unit);
        !           941:                }
        !           942:                printf("%x ",*(is->rbuf+(BUFSIZE*no)+i));
        !           943:        }
        !           944:        if (printed)
        !           945:                printf("\n");
1.1       root      946: }
                    947:                
1.1.1.3 ! root      948: xmit_print(unit,no)
        !           949:        int unit,no;
1.1       root      950: {
1.1.1.3 ! root      951:        register struct is_softc *is=&is_softc[unit];
1.1       root      952:        struct mds *rmd;
1.1.1.3 ! root      953:        int i, printed=0;
1.1       root      954:        u_short len;
                    955:        
1.1.1.3 ! root      956:        rmd = (is->td+no);
1.1       root      957:        len = -(rmd->bcnt);
1.1.1.3 ! root      958:        printf("is%d: Transmit buffer %d, len = %d\n",unit,no,len);
        !           959:        printf("is%d: Status %x\n",unit,isrdcsr(unit,0));
        !           960:        printf("is%d: addr %x, flags %x, bcnt %x, mcnt %x\n",
        !           961:                unit,rmd->addr,rmd->flags,rmd->bcnt,rmd->mcnt);
        !           962:        for (i=0; i<len; i++)  {
        !           963:                if (!printed) {
        !           964:                        printed = 1;
        !           965:                        printf("is%d: data: ", unit);
        !           966:                }
        !           967:                printf("%x ",*(is->tbuf+(BUFSIZE*no)+i));
        !           968:        }
        !           969:        if (printed)
        !           970:                printf("\n");
1.1       root      971: }
                    972:                
                    973: #endif

unix.superglobalmegacorp.com

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