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

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)*/];
1.1.1.2 ! root      110:        short   ns_txstart;             /* transmitter buffer start */
        !           111:        short   ns_rxend;               /* recevier buffer end */
        !           112:        short   ns_rxbndry;             /* recevier buffer boundary */
        !           113:        short   ns_port;                /* i/o port base */
        !           114:        short   ns_mode;                /* word/byte mode */
1.1       root      115: } ne_softc[NNE] ;
                    116: #define        ENBUFSIZE       (sizeof(struct ether_header) + ETHERMTU + 2 + ETHER_MIN_LEN)
                    117: 
1.1.1.2 ! root      118: #define        PAT(n)  (0xa55a + 37*(n))
1.1       root      119: 
                    120: u_short boarddata[16];
                    121:  
                    122: neprobe(dvp)
                    123:        struct isa_device *dvp;
                    124: {
1.1.1.2 ! root      125:        int val, i, s, sum, bytemode = 1, pat;
1.1       root      126:        register struct ne_softc *ns = &ne_softc[0];
1.1.1.2 ! root      127:        register nec;
1.1       root      128: 
                    129: #ifdef lint
                    130:        neintr(0);
                    131: #endif
                    132: 
1.1.1.2 ! root      133:        nec = ns->ns_port = dvp->id_iobase;
1.1       root      134:        s = splimp();
                    135: 
1.1.1.2 ! root      136:        if (bytemode) {
        !           137:                /* Byte Transfers, Burst Mode Select, Fifo at 8 bytes */
        !           138:                ns->ns_mode = DSDC_BMS|DSDC_FT1;
        !           139:                ns->ns_txstart = TBUF8;
        !           140:                ns->ns_rxend = RBUFEND8;
        !           141:        } else {
        !           142: word:
        !           143:                /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
        !           144:                ns->ns_mode = DSDC_WTS|DSDC_BMS|DSDC_FT1;
        !           145:                ns->ns_txstart = TBUF16;
        !           146:                ns->ns_rxend = RBUFEND16;
        !           147:                bytemode = 0;
        !           148:        }
        !           149: 
1.1       root      150:        /* Reset the bastard */
1.1.1.2 ! root      151:        val = inb(nec + ne_reset);
        !           152:        DELAY(200);
        !           153:        outb(nec + ne_reset, val);
        !           154:        DELAY(200);
1.1       root      155: 
1.1.1.2 ! root      156:        outb(nec + ds_cmd, DSCM_STOP|DSCM_NODMA);
1.1       root      157:        
1.1.1.2 ! root      158:        i = 10000;
        !           159:        while ((inb(nec + ds0_isr) & DSIS_RESET) == 0 && i-- > 0);
1.1       root      160:        if (i < 0) return (0);
                    161: 
1.1.1.2 ! root      162:        outb(nec + ds0_isr, 0xff);
        !           163:        outb(nec + ds0_dcr, ns->ns_mode);
        !           164:        outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
        !           165:        DELAY(1000);
1.1       root      166: 
                    167:        /* Check cmd reg and fail if not right */
1.1.1.2 ! root      168:        if ((i = inb(nec + ds_cmd)) != (DSCM_NODMA|DSCM_PG0|DSCM_STOP))
1.1       root      169:                return(0);
                    170: 
1.1.1.2 ! root      171:        outb(nec + ds0_tcr, 0);
        !           172:        outb(nec + ds0_rcr, DSRC_MON);
        !           173:        outb(nec + ds0_pstart, (ns->ns_txstart+PKTSZ)/DS_PGSIZE);
        !           174:        outb(nec + ds0_pstop, ns->ns_rxend/DS_PGSIZE);
        !           175:        outb(nec + ds0_bnry, ns->ns_rxend/DS_PGSIZE);
        !           176:        outb(nec + ds0_imr, 0);
        !           177:        outb(nec + ds0_isr, 0);
        !           178:        outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
        !           179:        outb(nec + ds1_curr, (ns->ns_txstart+PKTSZ)/DS_PGSIZE);
        !           180:        outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
        !           181: 
1.1       root      182: 
                    183: #ifdef NEDEBUG
                    184: #define        RCON    37
1.1.1.2 ! root      185:        {       int i, rom;
1.1       root      186: 
                    187:                rom=1;
                    188:                printf("ne ram ");
                    189:                
                    190:                for (i = 0; i < 0xfff0; i+=4) {
                    191:                        pat = PAT(i);
1.1.1.2 ! root      192:                        neput(ns, &pat,i,4);
        !           193:                        nefetch(ns, &pat,i,4);
1.1       root      194:                        if (pat == PAT(i)) {
                    195:                                if (rom) {
                    196:                                        rom=0;
                    197:                                        printf(" %x", i);
                    198:                                }
                    199:                        } else {
                    200:                                if (!rom) {
                    201:                                        rom=1;
                    202:                                        printf("..%x ", i);
                    203:                                }
                    204:                        }
                    205:                        pat=0;
1.1.1.2 ! root      206:                        neput(ns, &pat,i,4);
1.1       root      207:                }
                    208:                printf("\n");
                    209:        }
                    210: #endif
                    211: 
1.1.1.2 ! root      212:        /*
        !           213:         * <groan> detect difference between units
        !           214:         * solely by where the RAM is decoded.
        !           215:         */
        !           216:        pat = PAT(0);
        !           217:        neput(ns, &pat, ns->ns_txstart, 4);
        !           218:        nefetch(ns, &pat, ns->ns_txstart, 4);
        !           219:        if (pat != PAT(0)) {
        !           220:                if (bytemode)
        !           221:                        goto word;
        !           222:                else return (0);
        !           223:        }
        !           224: 
        !           225: 
1.1       root      226:        /* Extract board address */
1.1.1.2 ! root      227:        nefetch (ns, (caddr_t)boarddata, 0, sizeof(boarddata));
        !           228: 
        !           229:        for(i=0; i < 6; i++)
        !           230:                ns->ns_addr[i] = boarddata[i];
1.1       root      231:        splx(s);
                    232:        return (1);
                    233: }
                    234: 
                    235: /*
                    236:  * Fetch from onboard ROM/RAM
                    237:  */
1.1.1.2 ! root      238: nefetch (ns, up, ad, len) struct ne_softc *ns; caddr_t up; {
1.1       root      239:        u_char cmd;
1.1.1.2 ! root      240:        register nec = ns->ns_port;
        !           241:        int counter = 100000;
1.1       root      242: 
1.1.1.2 ! root      243:        cmd = inb (nec + ds_cmd);
        !           244:        outb (nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
1.1       root      245: 
                    246:        /* Setup remote dma */
1.1.1.2 ! root      247:        outb (nec + ds0_isr, DSIS_RDC);
        !           248: 
        !           249:        if ((ns->ns_mode & DSDC_WTS) && len&1)
        !           250:                len++;          /* roundup to words */
        !           251: 
1.1       root      252:        outb (nec+ds0_rbcr0, len);
                    253:        outb (nec+ds0_rbcr1, len>>8);
                    254:        outb (nec+ds0_rsar0, ad);
                    255:        outb (nec+ds0_rsar1, ad>>8);
                    256: 
                    257:        /* Execute & extract from card */
                    258:        outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START);
1.1.1.2 ! root      259: 
        !           260:        if (ns->ns_mode & DSDC_WTS)
        !           261:                insw (nec+ne_data, up, len/2);
        !           262:        else
        !           263:                insb (nec+ne_data, up, len);
1.1       root      264: 
                    265:        /* Wait till done, then shutdown feature */
1.1.1.2 ! root      266:        while ((inb (nec+ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
        !           267:                ;
1.1       root      268:        outb (nec+ds0_isr, DSIS_RDC);
                    269:        outb (nec+ds_cmd, cmd);
                    270: }
                    271: 
                    272: /*
                    273:  * Put to onboard RAM
                    274:  */
1.1.1.2 ! root      275: neput (ns, up, ad, len) struct ne_softc *ns; caddr_t up; {
1.1       root      276:        u_char cmd;
1.1.1.2 ! root      277:        register nec = ns->ns_port;
        !           278:        int counter = 100000;
1.1       root      279: 
                    280:        cmd = inb(nec+ds_cmd);
                    281:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
                    282: 
                    283:        /* Setup for remote dma */
                    284:        outb (nec+ds0_isr, DSIS_RDC);
1.1.1.2 ! root      285: 
        !           286:        if ((ns->ns_mode & DSDC_WTS) && len&1)
        !           287:                len++;          /* roundup to words */
        !           288: 
1.1       root      289:        outb (nec+ds0_rbcr0, len);
                    290:        outb (nec+ds0_rbcr1, len>>8);
                    291:        outb (nec+ds0_rsar0, ad);
                    292:        outb (nec+ds0_rsar1, ad>>8);
                    293: 
                    294:        /* Execute & stuff to card */
                    295:        outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START);
1.1.1.2 ! root      296:        if (ns->ns_mode & DSDC_WTS)
        !           297:                outsw (nec+ne_data, up, len/2);
        !           298:        else
        !           299:                outsb (nec+ne_data, up, len);
1.1       root      300:        
                    301:        /* Wait till done, then shutdown feature */
1.1.1.2 ! root      302:        while ((inb (nec+ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
        !           303:                ;
1.1       root      304:        outb (nec+ds0_isr, DSIS_RDC);
                    305:        outb (nec+ds_cmd, cmd);
                    306: }
                    307: 
                    308: /*
                    309:  * Reset of interface.
                    310:  */
                    311: nereset(unit, uban)
                    312:        int unit, uban;
                    313: {
                    314:        if (unit >= NNE)
                    315:                return;
                    316:        printf("ne%d: reset\n", unit);
                    317:        ne_softc[unit].ns_flags &= ~DSF_LOCK;
                    318:        neinit(unit);
                    319: }
                    320:  
                    321: /*
                    322:  * Interface exists: make available by filling in network interface
                    323:  * record.  System will initialize the interface when it is ready
                    324:  * to accept packets.  We get the ethernet address here.
                    325:  */
                    326: neattach(dvp)
                    327:        struct isa_device *dvp;
                    328: {
                    329:        int unit = dvp->id_unit;
                    330:        register struct ne_softc *ns = &ne_softc[unit];
                    331:        register struct ifnet *ifp = &ns->ns_if;
                    332: 
                    333:        ifp->if_unit = unit;
                    334:        ifp->if_name = nedriver.name ;
                    335:        ifp->if_mtu = ETHERMTU;
                    336:        printf (" ethernet address %s", ether_sprintf(ns->ns_addr)) ;
                    337:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
                    338:        ifp->if_init = neinit;
                    339:        ifp->if_output = ether_output;
                    340:        ifp->if_start = nestart;
                    341:        ifp->if_ioctl = neioctl;
                    342:        ifp->if_reset = nereset;
                    343:        ifp->if_watchdog = 0;
                    344:        if_attach(ifp);
                    345: }
                    346: 
                    347: /*
                    348:  * Initialization of interface; set up initialization block
                    349:  * and transmit/receive descriptor rings.
                    350:  */
                    351: neinit(unit)
                    352:        int unit;
                    353: {
                    354:        register struct ne_softc *ns = &ne_softc[unit];
                    355:        struct ifnet *ifp = &ns->ns_if;
                    356:        int s;
1.1.1.2 ! root      357:        int i; char *cp;
        !           358:        register nec = ns->ns_port;
1.1       root      359: 
                    360:        if (ifp->if_addrlist == (struct ifaddr *)0) return;
                    361:        if (ifp->if_flags & IFF_RUNNING) return;
                    362: 
                    363:        s = splimp();
                    364: 
                    365:        /* set physical address on ethernet */
                    366:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
                    367:        for (i=0 ; i < 6 ; i++) outb(nec+ds1_par0+i,ns->ns_addr[i]);
                    368: 
                    369:        /* clr logical address hash filter for now */
                    370:        for (i=0 ; i < 8 ; i++) outb(nec+ds1_mar0+i,0xff);
                    371: 
                    372:        /* init regs */
                    373:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
                    374:        outb (nec+ds0_rbcr0, 0);
                    375:        outb (nec+ds0_rbcr1, 0);
                    376:        outb (nec+ds0_imr, 0);
                    377:        outb (nec+ds0_isr, 0xff);
                    378: 
1.1.1.2 ! root      379:        /* Word Transfer select, Burst Mode Select, Fifo at 8 bytes */
        !           380:        outb(nec+ds0_dcr, ns->ns_mode);
        !           381: 
1.1       root      382:        outb(nec+ds0_tcr, 0);
                    383:        outb (nec+ds0_rcr, DSRC_MON);
                    384:        outb (nec+ds0_tpsr, 0);
1.1.1.2 ! root      385:        outb(nec+ds0_pstart, (ns->ns_txstart+PKTSZ)/DS_PGSIZE);
        !           386:        outb(nec+ds0_pstop, ns->ns_rxend/DS_PGSIZE);
        !           387:        outb(nec+ds0_bnry, (ns->ns_txstart+PKTSZ)/DS_PGSIZE);
1.1       root      388:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
1.1.1.2 ! root      389:        outb(nec+ds1_curr, (ns->ns_txstart+PKTSZ)/DS_PGSIZE);
        !           390:        ns->ns_cur = (ns->ns_txstart+PKTSZ)/DS_PGSIZE;
1.1       root      391:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
                    392:        outb (nec+ds0_rcr, DSRC_AB);
1.1.1.2 ! root      393:        outb(nec+ds0_dcr, ns->ns_mode);
1.1       root      394:        outb (nec+ds0_imr, 0xff);
                    395: 
                    396:        ns->ns_if.if_flags |= IFF_RUNNING;
1.1.1.2 ! root      397:        ns->ns_flags &= ~DSF_LOCK;
1.1       root      398:        ns->ns_oactive = 0; ns->ns_mask = ~0;
                    399:        nestart(ifp);
                    400:        splx(s);
                    401: }
                    402: 
                    403: /*
                    404:  * Setup output on interface.
                    405:  * Get another datagram to send off of the interface queue,
                    406:  * and map it to the interface before starting the output.
                    407:  * called only at splimp or interrupt level.
                    408:  */
                    409: nestart(ifp)
                    410:        struct ifnet *ifp;
                    411: {
                    412:        register struct ne_softc *ns = &ne_softc[ifp->if_unit];
                    413:        struct mbuf *m0, *m;
                    414:        int buffer;
                    415:        int len = 0, i, total,t;
1.1.1.2 ! root      416:        register nec = ns->ns_port;
1.1       root      417: 
                    418:        /*
                    419:         * The DS8390 has only one transmit buffer, if it is busy we
                    420:         * must wait until the transmit interrupt completes.
                    421:         */
                    422:        outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);
                    423: 
                    424:        if (ns->ns_flags & DSF_LOCK)
                    425:                return;
                    426: 
                    427:        if (inb(nec+ds_cmd) & DSCM_TRANS)
                    428:                return;
                    429: 
                    430:        if ((ns->ns_if.if_flags & IFF_RUNNING) == 0)
                    431:                return;
                    432: 
                    433:        IF_DEQUEUE(&ns->ns_if.if_snd, m);
                    434:  
                    435:        if (m == 0)
                    436:                return;
                    437: 
                    438:        /*
                    439:         * Copy the mbuf chain into the transmit buffer
                    440:         */
                    441: 
                    442:        ns->ns_flags |= DSF_LOCK;       /* prevent entering nestart */
1.1.1.2 ! root      443:        buffer = ns->ns_txstart; len = i = 0;
1.1       root      444:        t = 0;
                    445:        for (m0 = m; m != 0; m = m->m_next)
                    446:                t += m->m_len;
                    447:                
                    448:        m = m0;
                    449:        total = t;
                    450:        for (m0 = m; m != 0; ) {
                    451:                
                    452:                if (m->m_len&1 && t > m->m_len) {
1.1.1.2 ! root      453:                        neput(ns, mtod(m, caddr_t), buffer, m->m_len - 1);
1.1       root      454:                        t -= m->m_len - 1;
                    455:                        buffer += m->m_len - 1;
                    456:                        m->m_data += m->m_len - 1;
                    457:                        m->m_len = 1;
                    458:                        m = m_pullup(m, 2);
                    459:                } else {
1.1.1.2 ! root      460:                        neput(ns, mtod(m, caddr_t), buffer, m->m_len);
1.1       root      461:                        buffer += m->m_len;
                    462:                        t -= m->m_len;
                    463:                        MFREE(m, m0);
                    464:                        m = m0;
                    465:                }
                    466:        }
                    467: 
                    468:        /*
                    469:         * Init transmit length registers, and set transmit start flag.
                    470:         */
                    471: 
                    472:        len = total;
                    473:        if (len < ETHER_MIN_LEN) len = ETHER_MIN_LEN;
                    474:        outb(nec+ds0_tbcr0,len&0xff);
                    475:        outb(nec+ds0_tbcr1,(len>>8)&0xff);
1.1.1.2 ! root      476:        outb(nec+ds0_tpsr, ns->ns_txstart/DS_PGSIZE);
1.1       root      477:        outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);
                    478: }
                    479: 
                    480: /* buffer successor/predecessor in ring? */
1.1.1.2 ! root      481: #define succ(n) (((n)+1 >= ns->ns_rxend/DS_PGSIZE) ? (ns->ns_txstart+PKTSZ)/DS_PGSIZE : (n)+1)
        !           482: #define pred(n) (((n)-1 < (ns->ns_txstart+PKTSZ)/DS_PGSIZE) ? ns->ns_rxend/DS_PGSIZE-1 : (n)-1)
1.1       root      483: 
                    484: /*
                    485:  * Controller interrupt.
                    486:  */
                    487: neintr(unit)
                    488: {
                    489:        register struct ne_softc *ns = &ne_softc[unit];
                    490:        u_char cmd,isr;
1.1.1.2 ! root      491:        register nec = ns->ns_port;
1.1       root      492: 
                    493:        /* Save cmd, clear interrupt */
                    494:        cmd = inb (nec+ds_cmd);
                    495: loop:
                    496:        isr = inb (nec+ds0_isr);
                    497:        outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);
                    498:        outb(nec+ds0_isr, isr);
                    499: 
                    500:        /* Receiver error */
                    501:        if (isr & DSIS_RXE) {
                    502:                /* need to read these registers to clear status */
                    503:                (void) inb(nec+ ds0_rsr);
                    504:                (void) inb(nec+ 0xD);
                    505:                (void) inb(nec + 0xE);
                    506:                (void) inb(nec + 0xF);
                    507:                ns->ns_if.if_ierrors++;
                    508:        }
                    509: 
                    510:        /* We received something; rummage thru tiny ring buffer */
                    511:        if (isr & (DSIS_RX|DSIS_RXE|DSIS_ROVRN)) {
                    512:                u_char pend,lastfree;
                    513: 
                    514:                outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
                    515:                pend = inb(nec+ds1_curr);
                    516:                outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
                    517:                lastfree = inb(nec+ds0_bnry);
                    518: 
                    519:                /* Have we wrapped? */
1.1.1.2 ! root      520:                if (lastfree >= ns->ns_rxend/DS_PGSIZE)
        !           521:                        lastfree = (ns->ns_txstart+PKTSZ)/DS_PGSIZE;
1.1       root      522:                if (pend < lastfree && ns->ns_cur < pend)
                    523:                        lastfree = ns->ns_cur;
                    524:                else    if (ns->ns_cur > lastfree)
                    525:                        lastfree = ns->ns_cur;
                    526: 
                    527:                /* Something in the buffer? */
                    528:                while (pend != lastfree) {
                    529:                        u_char nxt;
                    530: 
                    531:                        /* Extract header from microcephalic board */
1.1.1.2 ! root      532:                        nefetch(ns, &ns->ns_ph,lastfree*DS_PGSIZE,
1.1       root      533:                                sizeof(ns->ns_ph));
                    534:                        ns->ns_ba = lastfree*DS_PGSIZE+sizeof(ns->ns_ph);
                    535: 
                    536:                        /* Incipient paranoia */
                    537:                        if (ns->ns_ph.pr_status == DSRS_RPC ||
                    538:                                /* for dequna's */
                    539:                                ns->ns_ph.pr_status == 0x21)
                    540:                                nerecv (ns);
                    541: #ifdef NEDEBUG
                    542:                        else  {
                    543:                                printf("cur %x pnd %x lfr %x ",
                    544:                                        ns->ns_cur, pend, lastfree);
                    545:                                printf("nxt %x len %x ", ns->ns_ph.pr_nxtpg,
                    546:                                        (ns->ns_ph.pr_sz1<<8)+ ns->ns_ph.pr_sz0);
                    547:                                printf("Bogus Sts %x\n", ns->ns_ph.pr_status);  
                    548:                        }
                    549: #endif
                    550: 
                    551:                        nxt = ns->ns_ph.pr_nxtpg ;
                    552: 
                    553:                        /* Sanity check */
1.1.1.2 ! root      554:                        if ( nxt >= (ns->ns_txstart+PKTSZ)/DS_PGSIZE
        !           555:                                && nxt <= ns->ns_rxend/DS_PGSIZE && nxt <= pend)
1.1       root      556:                                ns->ns_cur = nxt;
                    557:                        else    ns->ns_cur = nxt = pend;
                    558: 
                    559:                        /* Set the boundaries */
                    560:                        lastfree = nxt;
                    561:                        outb(nec+ds0_bnry, pred(nxt));
                    562:                        outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
                    563:                        pend = inb(nec+ds1_curr);
                    564:                        outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
                    565:                }
                    566:                outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
                    567:        }
                    568: 
                    569:        /* Transmit error */
                    570:        if (isr & DSIS_TXE) {
                    571:                ns->ns_flags &= ~DSF_LOCK;
                    572:                /* Need to read these registers to clear status */
                    573:                ns->ns_if.if_collisions += inb(nec+ds0_tbcr0);
                    574:                ns->ns_if.if_oerrors++;
                    575:        }
                    576: 
                    577:        /* Packet Transmitted */
                    578:        if (isr & DSIS_TX) {
                    579:                ns->ns_flags &= ~DSF_LOCK;
                    580:                ++ns->ns_if.if_opackets;
                    581:                ns->ns_if.if_collisions += inb(nec+ds0_tbcr0);
                    582:        }
                    583: 
                    584:        /* Receiver ovverun? */
                    585:        if (isr & DSIS_ROVRN) {
                    586:                log(LOG_ERR, "ne%d: error: isr %x\n", ns-ne_softc, isr
                    587:                        /*, DSIS_BITS*/);
                    588:                outb(nec+ds0_rbcr0, 0);
                    589:                outb(nec+ds0_rbcr1, 0);
                    590:                outb(nec+ds0_tcr, DSTC_LB0);
                    591:                outb(nec+ds0_rcr, DSRC_MON);
                    592:                outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
                    593:                outb(nec+ds0_rcr, DSRC_AB);
                    594:                outb(nec+ds0_tcr, 0);
                    595:        }
                    596: 
                    597:        /* Any more to send? */
                    598:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
                    599:        nestart(&ns->ns_if);
                    600:        outb (nec+ds_cmd, cmd);
                    601:        outb (nec+ds0_imr, 0xff);
                    602: 
                    603:        /* Still more to do? */
                    604:        isr = inb (nec+ds0_isr);
                    605:        if(isr) goto loop;
                    606: }
                    607: 
                    608: /*
                    609:  * Ethernet interface receiver interface.
                    610:  * If input error just drop packet.
                    611:  * Otherwise examine packet to determine type.  If can't determine length
                    612:  * from type, then have to drop packet.  Othewise decapsulate
                    613:  * packet based on type and pass to type specific higher-level
                    614:  * input routine.
                    615:  */
                    616: nerecv(ns)
                    617:        register struct ne_softc *ns;
                    618: {
                    619:        int len,i;
                    620: 
                    621:        ns->ns_if.if_ipackets++;
                    622:        len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8);
                    623:        if(len < ETHER_MIN_LEN || len > ETHER_MAX_LEN)
                    624:                return;
                    625: 
                    626:        /* this need not be so torturous - one/two bcopys at most into mbufs */
1.1.1.2 ! root      627:        nefetch(ns, ns->ns_pb, ns->ns_ba, min(len,DS_PGSIZE-sizeof(ns->ns_ph)));
1.1       root      628:        if (len > DS_PGSIZE-sizeof(ns->ns_ph)) {
                    629:                int l = len - (DS_PGSIZE-sizeof(ns->ns_ph)), b ;
                    630:                u_char *p = ns->ns_pb + (DS_PGSIZE-sizeof(ns->ns_ph));
                    631: 
                    632:                if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46;
                    633:                b = ns->ns_cur*DS_PGSIZE;
                    634:                
                    635:                while (l >= DS_PGSIZE) {
1.1.1.2 ! root      636:                        nefetch(ns, p, b, DS_PGSIZE);
1.1       root      637:                        p += DS_PGSIZE; l -= DS_PGSIZE;
                    638:                        if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46;
                    639:                        b = ns->ns_cur*DS_PGSIZE;
                    640:                }
                    641:                if (l > 0)
1.1.1.2 ! root      642:                        nefetch(ns, p, b, l);
1.1       root      643:        }
                    644:        /* don't forget checksum! */
                    645:        len -= sizeof(struct ether_header) + sizeof(long);
                    646:                        
                    647:        neread(ns,(caddr_t)(ns->ns_pb), len);
                    648: }
                    649: 
                    650: /*
                    651:  * Pass a packet to the higher levels.
                    652:  * We deal with the trailer protocol here.
                    653:  */
                    654: neread(ns, buf, len)
                    655:        register struct ne_softc *ns;
                    656:        char *buf;
                    657:        int len;
                    658: {
                    659:        register struct ether_header *eh;
                    660:        struct mbuf *m;
                    661:        int off, resid;
                    662:        register struct ifqueue *inq;
                    663: 
                    664:        /*
                    665:         * Deal with trailer protocol: if type is trailer type
                    666:         * get true type from first 16-bit word past data.
                    667:         * Remember that type was trailer by setting off.
                    668:         */
                    669:        eh = (struct ether_header *)buf;
                    670:        eh->ether_type = ntohs((u_short)eh->ether_type);
                    671: #define        nedataaddr(eh, off, type)       ((type)(((caddr_t)((eh)+1)+(off))))
                    672:        if (eh->ether_type >= ETHERTYPE_TRAIL &&
                    673:            eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
                    674:                off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
                    675:                if (off >= ETHERMTU) return;            /* sanity */
                    676:                eh->ether_type = ntohs(*nedataaddr(eh, off, u_short *));
                    677:                resid = ntohs(*(nedataaddr(eh, off+2, u_short *)));
                    678:                if (off + resid > len) return;          /* sanity */
                    679:                len = off + resid;
                    680:        } else  off = 0;
                    681: 
                    682:        if (len == 0) return;
                    683: 
                    684:        /*
                    685:         * Pull packet off interface.  Off is nonzero if packet
                    686:         * has trailing header; neget will then force this header
                    687:         * information to be at the front, but we still have to drop
                    688:         * the type and length which are at the front of any trailer data.
                    689:         */
                    690:        m = neget(buf, len, off, &ns->ns_if);
                    691:        if (m == 0) return;
                    692: 
                    693:        ether_input(&ns->ns_if, eh, m);
                    694: }
                    695: 
                    696: /*
                    697:  * Supporting routines
                    698:  */
                    699: 
                    700: /*
                    701:  * Pull read data off a interface.
                    702:  * Len is length of data, with local net header stripped.
                    703:  * Off is non-zero if a trailer protocol was used, and
                    704:  * gives the offset of the trailer information.
                    705:  * We copy the trailer information and then all the normal
                    706:  * data into mbufs.  When full cluster sized units are present
                    707:  * we copy into clusters.
                    708:  */
                    709: struct mbuf *
                    710: neget(buf, totlen, off0, ifp)
                    711:        caddr_t buf;
                    712:        int totlen, off0;
                    713:        struct ifnet *ifp;
                    714: {
                    715:        struct mbuf *top, **mp, *m, *p;
                    716:        int off = off0, len;
                    717:        register caddr_t cp = buf;
                    718:        char *epkt;
                    719: 
                    720:        buf += sizeof(struct ether_header);
                    721:        cp = buf;
                    722:        epkt = cp + totlen;
                    723: 
                    724: 
                    725:        if (off) {
                    726:                cp += off + 2 * sizeof(u_short);
                    727:                totlen -= 2 * sizeof(u_short);
                    728:        }
                    729: 
                    730:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                    731:        if (m == 0)
                    732:                return (0);
                    733:        m->m_pkthdr.rcvif = ifp;
                    734:        m->m_pkthdr.len = totlen;
                    735:        m->m_len = MHLEN;
                    736: 
                    737:        top = 0;
                    738:        mp = &top;
                    739:        while (totlen > 0) {
                    740:                if (top) {
                    741:                        MGET(m, M_DONTWAIT, MT_DATA);
                    742:                        if (m == 0) {
                    743:                                m_freem(top);
                    744:                                return (0);
                    745:                        }
                    746:                        m->m_len = MLEN;
                    747:                }
                    748:                len = min(totlen, epkt - cp);
                    749:                if (len >= MINCLSIZE) {
                    750:                        MCLGET(m, M_DONTWAIT);
                    751:                        if (m->m_flags & M_EXT)
                    752:                                m->m_len = len = min(len, MCLBYTES);
                    753:                        else
                    754:                                len = m->m_len;
                    755:                } else {
                    756:                        /*
                    757:                         * Place initial small packet/header at end of mbuf.
                    758:                         */
                    759:                        if (len < m->m_len) {
                    760:                                if (top == 0 && len + max_linkhdr <= m->m_len)
                    761:                                        m->m_data += max_linkhdr;
                    762:                                m->m_len = len;
                    763:                        } else
                    764:                                len = m->m_len;
                    765:                }
                    766:                bcopy(cp, mtod(m, caddr_t), (unsigned)len);
                    767:                cp += len;
                    768:                *mp = m;
                    769:                mp = &m->m_next;
                    770:                totlen -= len;
                    771:                if (cp == epkt)
                    772:                        cp = buf;
                    773:        }
                    774:        return (top);
                    775: }
                    776: 
                    777: /*
                    778:  * Process an ioctl request.
                    779:  */
                    780: neioctl(ifp, cmd, data)
                    781:        register struct ifnet *ifp;
                    782:        int cmd;
                    783:        caddr_t data;
                    784: {
                    785:        register struct ifaddr *ifa = (struct ifaddr *)data;
                    786:        struct ne_softc *ns = &ne_softc[ifp->if_unit];
                    787:        struct ifreq *ifr = (struct ifreq *)data;
                    788:        int s = splimp(), error = 0;
                    789: 
                    790: 
                    791:        switch (cmd) {
                    792: 
                    793:        case SIOCSIFADDR:
                    794:                ifp->if_flags |= IFF_UP;
                    795: 
                    796:                switch (ifa->ifa_addr->sa_family) {
                    797: #ifdef INET
                    798:                case AF_INET:
                    799:                        neinit(ifp->if_unit);   /* before arpwhohas */
                    800:                        ((struct arpcom *)ifp)->ac_ipaddr =
                    801:                                IA_SIN(ifa)->sin_addr;
                    802:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
                    803:                        break;
                    804: #endif
                    805: #ifdef NS
                    806:                case AF_NS:
                    807:                    {
                    808:                        register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
                    809: 
                    810:                        if (ns_nullhost(*ina))
                    811:                                ina->x_host = *(union ns_host *)(ns->ns_addr);
                    812:                        else {
                    813:                                /* 
                    814:                                 * The manual says we can't change the address 
                    815:                                 * while the receiver is armed,
                    816:                                 * so reset everything
                    817:                                 */
                    818:                                ifp->if_flags &= ~IFF_RUNNING; 
                    819:                                bcopy((caddr_t)ina->x_host.c_host,
                    820:                                    (caddr_t)ns->ns_addr, sizeof(ns->ns_addr));
                    821:                        }
                    822:                        neinit(ifp->if_unit); /* does ne_setaddr() */
                    823:                        break;
                    824:                    }
                    825: #endif
                    826:                default:
                    827:                        neinit(ifp->if_unit);
                    828:                        break;
                    829:                }
                    830:                break;
                    831: 
                    832:        case SIOCSIFFLAGS:
                    833:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    834:                    ifp->if_flags & IFF_RUNNING) {
                    835:                        ifp->if_flags &= ~IFF_RUNNING;
1.1.1.2 ! root      836:                        outb(ns->ns_port + ds_cmd, DSCM_STOP|DSCM_NODMA);
1.1       root      837:                } else if (ifp->if_flags & IFF_UP &&
                    838:                    (ifp->if_flags & IFF_RUNNING) == 0)
                    839:                        neinit(ifp->if_unit);
                    840:                break;
                    841: 
                    842: #ifdef notdef
                    843:        case SIOCGHWADDR:
                    844:                bcopy((caddr_t)ns->ns_addr, (caddr_t) &ifr->ifr_data,
                    845:                        sizeof(ns->ns_addr));
                    846:                break;
                    847: #endif
                    848: 
                    849:        default:
                    850:                error = EINVAL;
                    851:        }
                    852:        splx(s);
                    853:        return (error);
                    854: }
                    855: #endif

unix.superglobalmegacorp.com

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