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

1.1     ! root        1: /*-
        !             2:  * Copyright (c) 1990 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This code is derived from software contributed to Berkeley by
        !             6:  * Tim L. Tucker.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed by the University of
        !            19:  *     California, Berkeley and its contributors.
        !            20:  * 4. Neither the name of the University nor the names of its contributors
        !            21:  *    may be used to endorse or promote products derived from this software
        !            22:  *    without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            34:  * SUCH DAMAGE.
        !            35:  *
        !            36:  *     @(#)if_we.c     7.3 (Berkeley) 5/21/91
        !            37:  */
        !            38: 
        !            39: /*
        !            40:  * Modification history
        !            41:  *
        !            42:  * 8/28/89 - Initial version(if_wd.c), Tim L Tucker
        !            43:  */
        !            44:  
        !            45: #include "we.h"
        !            46: #if    NWE > 0
        !            47: /*
        !            48:  * Western Digital 8003 ethernet/starlan adapter
        !            49:  *
        !            50:  * Supports the following interface cards:
        !            51:  * WD8003E, WD8003EBT, WD8003S, WD8003SBT, WD8013EBT
        !            52:  *
        !            53:  * The Western Digital card is one of many AT/MCA ethernet interfaces
        !            54:  * based on the National DS8390 Network Interface chip set.
        !            55:  */
        !            56: #include "param.h"
        !            57: #include "mbuf.h"
        !            58: #include "socket.h"
        !            59: #include "ioctl.h"
        !            60: #include "errno.h"
        !            61: #include "syslog.h"
        !            62: 
        !            63: #include "net/if.h"
        !            64: #include "net/netisr.h"
        !            65: 
        !            66: #ifdef INET
        !            67: #include "netinet/in.h"
        !            68: #include "netinet/in_systm.h"
        !            69: #include "netinet/in_var.h"
        !            70: #include "netinet/ip.h"
        !            71: #include "netinet/if_ether.h"
        !            72: #endif
        !            73: 
        !            74: #ifdef NS
        !            75: #include "netns/ns.h"
        !            76: #include "netns/ns_if.h"
        !            77: #endif
        !            78: 
        !            79: #include "i386/isa/if_wereg.h"
        !            80: #include "i386/isa/isa_device.h"
        !            81:  
        !            82: /*
        !            83:  * This constant should really be 60 because the we adds 4 bytes of crc.
        !            84:  * However when set to 60 our packets are ignored by deuna's , 3coms are
        !            85:  * okay ??????????????????????????????????????????
        !            86:  */
        !            87: #define ETHER_MIN_LEN 64
        !            88: #define        ETHER_ADDR_LEN 6
        !            89: #define ETHER_HDR_SIZE 14
        !            90:  
        !            91: /*
        !            92:  * Ethernet software status per interface.
        !            93:  *
        !            94:  * Each interface is referenced by a network interface structure,
        !            95:  * qe_if, which the routing code uses to locate the interface.
        !            96:  * This structure contains the output queue for the interface, its address, ...
        !            97:  */
        !            98: struct we_softc {
        !            99:        struct  arpcom we_ac;           /* Ethernet common part         */
        !           100: #define        we_if   we_ac.ac_if             /* network-visible interface    */
        !           101: #define        we_addr we_ac.ac_enaddr         /* hardware Ethernet address    */
        !           102: 
        !           103:        u_char  we_flags;               /* software state               */
        !           104: #define        WDF_RUNNING     0x01
        !           105: #define WDF_TXBUSY     0x02
        !           106: 
        !           107:        u_char  we_type;                /* interface type code          */
        !           108:        u_short we_vector;              /* interrupt vector             */
        !           109:        short   we_io_ctl_addr;         /* i/o bus address, control     */
        !           110:        short   we_io_nic_addr;         /* i/o bus address, DS8390      */
        !           111: 
        !           112:        caddr_t we_vmem_addr;           /* card RAM virtual memory base */
        !           113:        u_long  we_vmem_size;           /* card RAM bytes               */
        !           114:        caddr_t we_vmem_ring;           /* receive ring RAM vaddress    */
        !           115:        caddr_t we_vmem_end;            /* receive ring RAM end */
        !           116: } we_softc[NWE];
        !           117: 
        !           118: int    weprobe(), weattach(), weintr(), westart();
        !           119: int    weinit(), ether_output(), weioctl(), wereset(), wewatchdog();
        !           120: 
        !           121: struct isa_driver wedriver = {
        !           122:        weprobe, weattach, "we",
        !           123: };
        !           124:  
        !           125: /*
        !           126:  * Probe the WD8003 to see if it's there
        !           127:  */
        !           128: weprobe(is)
        !           129:        struct isa_device *is;
        !           130: {
        !           131:        register int i;
        !           132:        register struct we_softc *sc = &we_softc[is->id_unit];
        !           133:        union we_mem_sel wem;
        !           134:        u_char sum;
        !           135:  
        !           136:        /*
        !           137:         * Here we check the card ROM, if the checksum passes, and the
        !           138:         * type code and ethernet address check out, then we know we have
        !           139:         * a wd8003 card.
        !           140:         *
        !           141:         * Autoconfiguration: No warning message is printed on error.
        !           142:         */
        !           143:        for (sum = 0, i = 0; i < 8; ++i)
        !           144:            sum += inb(is->id_iobase + WD_ROM_OFFSET + i);
        !           145:        if (sum != WD_CHECKSUM)
        !           146:             return (0);
        !           147:        sc->we_type = inb(is->id_iobase + WD_ROM_OFFSET + 6);
        !           148:        if ((sc->we_type != WD_ETHER) && (sc->we_type != WD_STARLAN)
        !           149:        && (sc->we_type != WD_ETHER2))
        !           150:             return (0);
        !           151: 
        !           152:        /*
        !           153:         * Setup card RAM area and i/o addresses
        !           154:         * Kernel Virtual to segment C0000-DFFFF?????
        !           155:         */
        !           156:        sc->we_io_ctl_addr = is->id_iobase;
        !           157:        sc->we_io_nic_addr = sc->we_io_ctl_addr + WD_NIC_OFFSET;
        !           158:        sc->we_vector = is->id_irq;
        !           159:        sc->we_vmem_addr = (caddr_t)is->id_maddr;
        !           160:        sc->we_vmem_size = is->id_msize;
        !           161:        sc->we_vmem_ring = sc->we_vmem_addr + (WD_PAGE_SIZE * WD_TXBUF_SIZE);
        !           162:        sc->we_vmem_end = sc->we_vmem_addr + is->id_msize;
        !           163: 
        !           164:        /*
        !           165:         * Save board ROM station address
        !           166:         */
        !           167:        for (i = 0; i < ETHER_ADDR_LEN; ++i)
        !           168:            sc->we_addr[i] = inb(sc->we_io_ctl_addr + WD_ROM_OFFSET + i);
        !           169: 
        !           170:        /*
        !           171:         * Mapin interface memory, setup memory select register
        !           172:         */
        !           173:        /* wem.ms_addr = (u_long)sc->we_vmem_addr >> 13; */
        !           174:        wem.ms_addr = (u_long)(0xd0000)>> 13;
        !           175:        wem.ms_enable = 1;
        !           176:        wem.ms_reset = 0;
        !           177:        outb(sc->we_io_ctl_addr, wem.ms_byte);
        !           178: 
        !           179:        /*
        !           180:         * clear interface memory, then sum to make sure its valid
        !           181:         */
        !           182:        for (i = 0; i < sc->we_vmem_size; ++i)
        !           183:            sc->we_vmem_addr[i] = 0x0;
        !           184:        for (sum = 0, i = 0; i < sc->we_vmem_size; ++i)
        !           185:            sum += sc->we_vmem_addr[i];
        !           186:        if (sum != 0x0) {
        !           187:             printf("we%d: wd8003 dual port RAM address error\n", is->id_unit);
        !           188:            return (0);
        !           189:        }
        !           190: 
        !           191:        return (WD_IO_PORTS);
        !           192: }
        !           193:  
        !           194: /*
        !           195:  * Interface exists: make available by filling in network interface
        !           196:  * record.  System will initialize the interface when it is ready
        !           197:  * to accept packets.
        !           198:  */
        !           199: weattach(is)
        !           200:        struct isa_device *is;
        !           201: {
        !           202:        register struct we_softc *sc = &we_softc[is->id_unit];
        !           203:        register struct ifnet *ifp = &sc->we_if;
        !           204:        union we_command wecmd;
        !           205:  
        !           206:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
        !           207:        wecmd.cs_stp = 1;
        !           208:        wecmd.cs_sta = 0;
        !           209:        wecmd.cs_ps = 0;
        !           210:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           211:        /*
        !           212:         * Initialize ifnet structure
        !           213:         */
        !           214:        ifp->if_unit = is->id_unit;
        !           215:        ifp->if_name = "we" ;
        !           216:        ifp->if_mtu = ETHERMTU;
        !           217:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS ;
        !           218:        ifp->if_init = weinit;
        !           219:        ifp->if_output = ether_output;
        !           220:        ifp->if_start = westart;
        !           221:        ifp->if_ioctl = weioctl;
        !           222:        ifp->if_reset = wereset;
        !           223:        ifp->if_watchdog = wewatchdog;
        !           224:        if_attach(ifp);
        !           225:  
        !           226:        /*
        !           227:         * Banner...
        !           228:         */
        !           229:        printf(" %s address %s",
        !           230:                ((sc->we_type != WD_STARLAN) ? "ethernet" : "starlan"),
        !           231:                ether_sprintf(sc->we_addr));
        !           232: }
        !           233:  
        !           234: /*
        !           235:  * Reset of interface.
        !           236:  */
        !           237: wereset(unit, uban)
        !           238:        int unit, uban;
        !           239: {
        !           240:        if (unit >= NWE)
        !           241:                return;
        !           242:        printf("we%d: reset\n", unit);
        !           243: /*     we_softc[unit].we_flags &= ~WDF_RUNNING; */
        !           244:        weinit(unit);
        !           245: }
        !           246:  
        !           247: /*
        !           248:  * Take interface offline.
        !           249:  */
        !           250: westop(unit)
        !           251:        int unit;
        !           252: {
        !           253:        register struct we_softc *sc = &we_softc[unit];
        !           254:        union we_command wecmd;
        !           255:        int s;
        !           256:  
        !           257:        /*
        !           258:         * Shutdown DS8390
        !           259:         */
        !           260:        s = splimp();
        !           261:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
        !           262:        wecmd.cs_stp = 1;
        !           263:        wecmd.cs_sta = 0;
        !           264:        wecmd.cs_ps = 0;
        !           265:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           266:        (void) splx(s);
        !           267: }
        !           268: 
        !           269: wewatchdog(unit) {
        !           270: 
        !           271:        log(LOG_WARNING,"we%d: soft reset\n", unit);
        !           272:        westop(unit);
        !           273:        weinit(unit);
        !           274: }
        !           275: 
        !           276: static Bdry;
        !           277: /*
        !           278:  * Initialization of interface (really just DS8390). 
        !           279:  */
        !           280: weinit(unit)
        !           281:        int unit;
        !           282: {
        !           283:        register struct we_softc *sc = &we_softc[unit];
        !           284:        register struct ifnet *ifp = &sc->we_if;
        !           285:        union we_command wecmd;
        !           286:        int i, s;
        !           287:  
        !           288:        /* address not known */
        !           289:        if (ifp->if_addrlist == (struct ifaddr *)0)
        !           290:                return;
        !           291: 
        !           292:        /* already running */
        !           293:        /*if (ifp->if_flags & IFF_RUNNING) return; */
        !           294: 
        !           295:        /*
        !           296:         * Initialize DS8390 in order given in NSC NIC manual.
        !           297:         * this is stock code...please see the National manual for details.
        !           298:         */
        !           299:        s = splhigh();
        !           300: Bdry = 0;
        !           301:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
        !           302:        wecmd.cs_stp = 1;
        !           303:        wecmd.cs_sta = 0;
        !           304:        wecmd.cs_ps = 0;
        !           305:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           306:        outb(sc->we_io_nic_addr + WD_P0_DCR, WD_D_CONFIG);
        !           307:        outb(sc->we_io_nic_addr + WD_P0_RBCR0, 0);
        !           308:        outb(sc->we_io_nic_addr + WD_P0_RBCR1, 0);
        !           309:        outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_MON);
        !           310:        outb(sc->we_io_nic_addr + WD_P0_TCR, WD_T_CONFIG);
        !           311:        outb(sc->we_io_nic_addr + WD_P0_TPSR, 0);
        !           312:        outb(sc->we_io_nic_addr + WD_P0_PSTART, WD_TXBUF_SIZE);
        !           313:        outb(sc->we_io_nic_addr + WD_P0_PSTOP,
        !           314:                sc->we_vmem_size / WD_PAGE_SIZE);
        !           315:        outb(sc->we_io_nic_addr + WD_P0_BNRY, WD_TXBUF_SIZE);
        !           316:        outb(sc->we_io_nic_addr + WD_P0_ISR, 0xff);
        !           317:        outb(sc->we_io_nic_addr + WD_P0_IMR, WD_I_CONFIG);
        !           318:        wecmd.cs_ps = 1;
        !           319:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           320:        for (i = 0; i < ETHER_ADDR_LEN; ++i)
        !           321:            outb(sc->we_io_nic_addr + WD_P1_PAR0 + i, sc->we_addr[i]);
        !           322:        for (i = 0; i < ETHER_ADDR_LEN; ++i)    /* == broadcast addr */
        !           323:            outb(sc->we_io_nic_addr + WD_P1_MAR0 + i, 0xff);
        !           324:        outb(sc->we_io_nic_addr + WD_P1_CURR, WD_TXBUF_SIZE);
        !           325:        wecmd.cs_ps = 0;
        !           326:        wecmd.cs_stp = 0;
        !           327:        wecmd.cs_sta = 1;
        !           328:        wecmd.cs_rd = 0x4;
        !           329:        outb(sc->we_io_nic_addr + WD_P1_COMMAND, wecmd.cs_byte);
        !           330:        outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_CONFIG);
        !           331: 
        !           332:        /*
        !           333:         * Take the interface out of reset, program the vector, 
        !           334:         * enable interrupts, and tell the world we are up.
        !           335:         */
        !           336:        ifp->if_flags |= IFF_RUNNING;
        !           337:        sc->we_flags &= ~WDF_TXBUSY;
        !           338:        (void) splx(s);
        !           339:        westart(ifp);
        !           340: }
        !           341:  
        !           342: /*
        !           343:  * Start output on interface.
        !           344:  */
        !           345: westart(ifp)
        !           346:        struct ifnet *ifp;
        !           347: {
        !           348:        register struct we_softc *sc = &we_softc[ifp->if_unit];
        !           349:        struct mbuf *m0, *m;
        !           350:        register caddr_t buffer;
        !           351:        int len, s;
        !           352:        union we_command wecmd;
        !           353:  
        !           354:        /*
        !           355:         * The DS8390 has only one transmit buffer, if it is busy we
        !           356:         * must wait until the transmit interrupt completes.
        !           357:         */
        !           358:        s = splhigh();
        !           359:        if (sc->we_flags & WDF_TXBUSY) {
        !           360:                (void) splx(s);
        !           361:                return;
        !           362:        }
        !           363:        IF_DEQUEUE(&sc->we_if.if_snd, m);
        !           364:        if (m == 0) {
        !           365:                (void) splx(s);
        !           366:                return;
        !           367:        }
        !           368:        sc->we_flags |= WDF_TXBUSY; 
        !           369:        (void) splx(s);
        !           370: 
        !           371:        /*
        !           372:         * Copy the mbuf chain into the transmit buffer
        !           373:         */
        !           374:        buffer = sc->we_vmem_addr;
        !           375:        len = 0;
        !           376:        for (m0 = m; m != 0; m = m->m_next) {
        !           377:                bcopy(mtod(m, caddr_t), buffer, m->m_len);
        !           378:                buffer += m->m_len;
        !           379:                len += m->m_len;
        !           380:        }
        !           381: 
        !           382:        m_freem(m0);
        !           383: 
        !           384:        /*
        !           385:         * Init transmit length registers, and set transmit start flag.
        !           386:         */
        !           387:        s = splhigh();
        !           388:        len = MAX(len, ETHER_MIN_LEN);
        !           389:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
        !           390:        wecmd.cs_ps = 0;
        !           391:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           392:        outb(sc->we_io_nic_addr + WD_P0_TBCR0, len & 0xff);
        !           393:        outb(sc->we_io_nic_addr + WD_P0_TBCR1, len >> 8);
        !           394:        wecmd.cs_txp = 1;
        !           395:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           396:        (void) splx(s);
        !           397: }
        !           398:  
        !           399: /*
        !           400:  * Ethernet interface interrupt processor
        !           401:  */
        !           402: weintr(unit)
        !           403:        int unit;
        !           404: {
        !           405:        register struct we_softc *sc = &we_softc[unit];
        !           406:        union we_command wecmd;
        !           407:        union we_interrupt weisr;
        !           408: 
        !           409:        unit =0;
        !           410:  
        !           411:        /* disable onboard interrupts, then get interrupt status */
        !           412:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
        !           413:        wecmd.cs_ps = 0;
        !           414:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           415:        weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR);
        !           416: loop:
        !           417:        outb(sc->we_io_nic_addr + WD_P0_ISR, weisr.is_byte);
        !           418: 
        !           419:        /* transmit error */
        !           420:        if (weisr.is_txe) {
        !           421:                /* need to read these registers to clear status */
        !           422:                sc->we_if.if_collisions +=
        !           423:                    inb(sc->we_io_nic_addr + WD_P0_TBCR0);
        !           424:                ++sc->we_if.if_oerrors;
        !           425:        }
        !           426: 
        !           427:        /* receiver error */
        !           428:        if (weisr.is_rxe) {
        !           429:                /* need to read these registers to clear status */
        !           430:                (void) inb(sc->we_io_nic_addr + 0xD);
        !           431:                (void) inb(sc->we_io_nic_addr + 0xE);
        !           432:                (void) inb(sc->we_io_nic_addr + 0xF);
        !           433:                ++sc->we_if.if_ierrors;
        !           434:        }
        !           435: 
        !           436:        /* normal transmit complete */
        !           437:        if (weisr.is_ptx || weisr.is_txe)
        !           438:                wetint (unit);
        !           439: 
        !           440:        /* normal receive notification */
        !           441:        if (weisr.is_prx || weisr.is_rxe)
        !           442:                werint (unit);
        !           443: 
        !           444:        /* try to start transmit */
        !           445:        westart(&sc->we_if);
        !           446: 
        !           447:        /* re-enable onboard interrupts */
        !           448:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
        !           449:        wecmd.cs_ps = 0;
        !           450:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           451:        outb(sc->we_io_nic_addr + WD_P0_IMR, 0xff/*WD_I_CONFIG*/);
        !           452:        weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR);
        !           453:        if (weisr.is_byte) goto loop;
        !           454: }
        !           455:  
        !           456: /*
        !           457:  * Ethernet interface transmit interrupt.
        !           458:  */
        !           459: wetint(unit)
        !           460:        int unit;
        !           461: {
        !           462:        register struct we_softc *sc = &we_softc[unit];
        !           463: 
        !           464:        /*
        !           465:         * Do some statistics (assume page zero of NIC mapped in)
        !           466:         */
        !           467:        sc->we_flags &= ~WDF_TXBUSY; 
        !           468:        sc->we_if.if_timer = 0;
        !           469:        ++sc->we_if.if_opackets;
        !           470:        sc->we_if.if_collisions += inb(sc->we_io_nic_addr + WD_P0_TBCR0);
        !           471: }
        !           472:  
        !           473: /*
        !           474:  * Ethernet interface receiver interrupt.
        !           475:  */
        !           476: werint(unit)
        !           477:        int unit;
        !           478: {
        !           479:        register struct we_softc *sc = &we_softc[unit];
        !           480:        u_char bnry, curr;
        !           481:        long len;
        !           482:        union we_command wecmd;
        !           483:        struct we_ring *wer;
        !           484:  
        !           485:        /*
        !           486:         * Traverse the receive ring looking for packets to pass back.
        !           487:         * The search is complete when we find a descriptor not in use.
        !           488:         */
        !           489:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
        !           490:        wecmd.cs_ps = 0;
        !           491:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           492:        bnry = inb(sc->we_io_nic_addr + WD_P0_BNRY);
        !           493:        wecmd.cs_ps = 1;
        !           494:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           495:        curr = inb(sc->we_io_nic_addr + WD_P1_CURR);
        !           496: if(Bdry)
        !           497:        bnry =Bdry;
        !           498: 
        !           499:        while (bnry != curr)
        !           500:        {
        !           501:                /* get pointer to this buffer header structure */
        !           502:                wer = (struct we_ring *)(sc->we_vmem_addr + (bnry << 8));
        !           503: 
        !           504:                /* count includes CRC */
        !           505:                len = wer->we_count - 4;
        !           506:                if (len > 30 && len <= ETHERMTU+100
        !           507:                        /*&& (*(char *)wer  == 1 || *(char *) wer == 0x21)*/)
        !           508:                        weread(sc, (caddr_t)(wer + 1), len);
        !           509:                else printf("reject %d", len);
        !           510: 
        !           511: outofbufs:
        !           512:                wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
        !           513:                wecmd.cs_ps = 0;
        !           514:                outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           515: 
        !           516:                /* advance on chip Boundry register */
        !           517:                if((caddr_t) wer + WD_PAGE_SIZE - 1 > sc->we_vmem_end) {
        !           518:                        bnry = WD_TXBUF_SIZE;
        !           519:                        outb(sc->we_io_nic_addr + WD_P0_BNRY,
        !           520:                                        sc->we_vmem_size / WD_PAGE_SIZE-1);
        !           521:        
        !           522:                } else {
        !           523:                        if (len > 30 && len <= ETHERMTU+100)
        !           524:                                bnry = wer->we_next_packet;
        !           525:                        else bnry = curr;
        !           526: 
        !           527:                        /* watch out for NIC overflow, reset Boundry if invalid */
        !           528:                        if ((bnry - 1) < WD_TXBUF_SIZE) {
        !           529:                                outb(sc->we_io_nic_addr + WD_P0_BNRY,
        !           530:                                        (sc->we_vmem_size / WD_PAGE_SIZE) - 1);
        !           531:                                bnry = WD_TXBUF_SIZE;
        !           532:                        } else
        !           533:                                outb(sc->we_io_nic_addr + WD_P0_BNRY, bnry-1);
        !           534:                }
        !           535: 
        !           536:                /* refresh our copy of CURR */
        !           537:                wecmd.cs_ps = 1;
        !           538:                outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
        !           539:                curr = inb(sc->we_io_nic_addr + WD_P1_CURR);
        !           540:        }
        !           541: Bdry = bnry;
        !           542: }
        !           543: 
        !           544: #ifdef shit
        !           545: /*
        !           546:  * Process an ioctl request.
        !           547:  */
        !           548: weioctl(ifp, cmd, data)
        !           549:        register struct ifnet *ifp;
        !           550:        int cmd;
        !           551:        caddr_t data;
        !           552: {
        !           553:        struct we_softc *sc = &we_softc[ifp->if_unit];
        !           554:        struct ifaddr *ifa = (struct ifaddr *)data;
        !           555:        int s = splimp(), error = 0;
        !           556:  
        !           557:        switch (cmd) {
        !           558:  
        !           559:        case SIOCSIFADDR:
        !           560:                ifp->if_flags |= IFF_UP;
        !           561:                weinit(ifp->if_unit);
        !           562:                switch(ifa->ifa_addr->sa_family) {
        !           563: #ifdef INET
        !           564:                case AF_INET:
        !           565:                        ((struct arpcom *)ifp)->ac_ipaddr =
        !           566:                                IA_SIN(ifa)->sin_addr;
        !           567:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
        !           568:                        break;
        !           569: #endif
        !           570: #ifdef NS
        !           571:                case AF_NS:
        !           572:                    {
        !           573:                        register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
        !           574:                        
        !           575:                        if (ns_nullhost(*ina))
        !           576:                                ina->x_host = *(union ns_host *)(sc->we_addr);
        !           577:                        else
        !           578:                                wesetaddr(ina->x_host.c_host, ifp->if_unit);
        !           579:                        break;
        !           580:                    }
        !           581: #endif
        !           582:                }
        !           583:                break;
        !           584: 
        !           585:        case SIOCSIFFLAGS:
        !           586:                if (((ifp->if_flags & IFF_UP) == 0) &&
        !           587:                   (sc->we_flags & WDF_RUNNING)) {
        !           588:                        westop(ifp->if_unit);
        !           589:                } else if (((ifp->if_flags & IFF_UP) == IFF_UP) &&
        !           590:                   ((sc->we_flags & WDF_RUNNING) == 0))
        !           591:                        weinit(ifp->if_unit);
        !           592:                break;
        !           593: 
        !           594:        default:
        !           595:                error = EINVAL;
        !           596:  
        !           597:        }
        !           598:        (void) splx(s);
        !           599:        return (error);
        !           600: }
        !           601: #endif
        !           602:  
        !           603: /*
        !           604:  * Process an ioctl request.
        !           605:  */
        !           606: weioctl(ifp, cmd, data)
        !           607:        register struct ifnet *ifp;
        !           608:        int cmd;
        !           609:        caddr_t data;
        !           610: {
        !           611:        register struct ifaddr *ifa = (struct ifaddr *)data;
        !           612:        struct we_softc *sc = &we_softc[ifp->if_unit];
        !           613:        struct ifreq *ifr = (struct ifreq *)data;
        !           614:        int s = splimp(), error = 0;
        !           615: 
        !           616: 
        !           617:        switch (cmd) {
        !           618: 
        !           619:        case SIOCSIFADDR:
        !           620:                ifp->if_flags |= IFF_UP;
        !           621: 
        !           622:                switch (ifa->ifa_addr->sa_family) {
        !           623: #ifdef INET
        !           624:                case AF_INET:
        !           625:                        weinit(ifp->if_unit);   /* before arpwhohas */
        !           626:                        ((struct arpcom *)ifp)->ac_ipaddr =
        !           627:                                IA_SIN(ifa)->sin_addr;
        !           628:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
        !           629:                        break;
        !           630: #endif
        !           631: #ifdef NS
        !           632:                case AF_NS:
        !           633:                    {
        !           634:                        register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
        !           635: 
        !           636:                        if (ns_nullhost(*ina))
        !           637:                                ina->x_host = *(union ns_host *)(sc->ns_addr);
        !           638:                        else {
        !           639:                                /* 
        !           640:                                 * The manual says we can't change the address 
        !           641:                                 * while the receiver is armed,
        !           642:                                 * so reset everything
        !           643:                                 */
        !           644:                                ifp->if_flags &= ~IFF_RUNNING; 
        !           645:                                bcopy((caddr_t)ina->x_host.c_host,
        !           646:                                    (caddr_t)sc->ns_addr, sizeof(sc->ns_addr));
        !           647:                        }
        !           648:                        weinit(ifp->if_unit); /* does ne_setaddr() */
        !           649:                        break;
        !           650:                    }
        !           651: #endif
        !           652:                default:
        !           653:                        weinit(ifp->if_unit);
        !           654:                        break;
        !           655:                }
        !           656:                break;
        !           657: 
        !           658:        case SIOCSIFFLAGS:
        !           659:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !           660:                    ifp->if_flags & IFF_RUNNING) {
        !           661:                        ifp->if_flags &= ~IFF_RUNNING;
        !           662:                        westop(ifp->if_unit);
        !           663:                } else if (ifp->if_flags & IFF_UP &&
        !           664:                    (ifp->if_flags & IFF_RUNNING) == 0)
        !           665:                        weinit(ifp->if_unit);
        !           666:                break;
        !           667: 
        !           668: #ifdef notdef
        !           669:        case SIOCGHWADDR:
        !           670:                bcopy((caddr_t)sc->sc_addr, (caddr_t) &ifr->ifr_data,
        !           671:                        sizeof(sc->sc_addr));
        !           672:                break;
        !           673: #endif
        !           674: 
        !           675:        default:
        !           676:                error = EINVAL;
        !           677:        }
        !           678:        splx(s);
        !           679:        return (error);
        !           680: }
        !           681: /*
        !           682:  * set ethernet address for unit
        !           683:  */
        !           684: wesetaddr(physaddr, unit)
        !           685:        u_char *physaddr;
        !           686:        int unit;
        !           687: {
        !           688:        register struct we_softc *sc = &we_softc[unit];
        !           689:        register int i;
        !           690: 
        !           691:        /*
        !           692:         * Rewrite ethernet address, and then force restart of NIC
        !           693:         */
        !           694:        for (i = 0; i < ETHER_ADDR_LEN; i++)
        !           695:                sc->we_addr[i] = physaddr[i];
        !           696:        sc->we_flags &= ~WDF_RUNNING;
        !           697:        weinit(unit);
        !           698: }
        !           699:  
        !           700: #define        wedataaddr(sc, eh, off, type) \
        !           701:        ((type) ((caddr_t)((eh)+1)+(off) >= (sc)->we_vmem_end) ? \
        !           702:                (((caddr_t)((eh)+1)+(off))) - (sc)->we_vmem_end \
        !           703:                + (sc)->we_vmem_ring: \
        !           704:                ((caddr_t)((eh)+1)+(off)))
        !           705: /*
        !           706:  * Pass a packet to the higher levels.
        !           707:  * We deal with the trailer protocol here.
        !           708:  */
        !           709: weread(sc, buf, len)
        !           710:        register struct we_softc *sc;
        !           711:        char *buf;
        !           712:        int len;
        !           713: {
        !           714:        register struct ether_header *eh;
        !           715:        struct mbuf *m, *weget();
        !           716:        int off, resid;
        !           717: 
        !           718:        /*
        !           719:         * Deal with trailer protocol: if type is trailer type
        !           720:         * get true type from first 16-bit word past data.
        !           721:         * Remember that type was trailer by setting off.
        !           722:         */
        !           723:        eh = (struct ether_header *)buf;
        !           724:        eh->ether_type = ntohs((u_short)eh->ether_type);
        !           725:        if (eh->ether_type >= ETHERTYPE_TRAIL &&
        !           726:            eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
        !           727:                off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
        !           728:                if (off >= ETHERMTU) return;            /* sanity */
        !           729:                eh->ether_type = ntohs(*wedataaddr(sc, eh, off, u_short *));
        !           730:                resid = ntohs(*(wedataaddr(sc, eh, off+2, u_short *)));
        !           731:                if (off + resid > len) return;          /* sanity */
        !           732:                len = off + resid;
        !           733:        } else  off = 0;
        !           734: 
        !           735:        len -= sizeof(struct ether_header);
        !           736:        if (len <= 0) return;
        !           737: 
        !           738:        /*
        !           739:         * Pull packet off interface.  Off is nonzero if packet
        !           740:         * has trailing header; neget will then force this header
        !           741:         * information to be at the front, but we still have to drop
        !           742:         * the type and length which are at the front of any trailer data.
        !           743:         */
        !           744:        m = weget(buf, len, off, &sc->we_if, sc);
        !           745:        if (m == 0) return;
        !           746:        ether_input(&sc->we_if, eh, m);
        !           747: }
        !           748: 
        !           749: /*
        !           750:  * Supporting routines
        !           751:  */
        !           752: 
        !           753: /*
        !           754:  * Pull read data off a interface.
        !           755:  * Len is length of data, with local net header stripped.
        !           756:  * Off is non-zero if a trailer protocol was used, and
        !           757:  * gives the offset of the trailer information.
        !           758:  * We copy the trailer information and then all the normal
        !           759:  * data into mbufs.  When full cluster sized units are present
        !           760:  * we copy into clusters.
        !           761:  */
        !           762: struct mbuf *
        !           763: weget(buf, totlen, off0, ifp, sc)
        !           764:        caddr_t buf;
        !           765:        int totlen, off0;
        !           766:        struct ifnet *ifp;
        !           767:        struct we_softc *sc;
        !           768: {
        !           769:        struct mbuf *top, **mp, *m, *p;
        !           770:        int off = off0, len;
        !           771:        register caddr_t cp = buf;
        !           772:        char *epkt;
        !           773:        int tc =totlen;
        !           774: 
        !           775:        buf += sizeof(struct ether_header);
        !           776:        cp = buf;
        !           777:        epkt = cp + totlen;
        !           778: 
        !           779:        if (off) {
        !           780:                cp += off + 2 * sizeof(u_short);
        !           781:                totlen -= 2 * sizeof(u_short);
        !           782:        }
        !           783: 
        !           784:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           785:        if (m == 0)
        !           786:                return (0);
        !           787:        m->m_pkthdr.rcvif = ifp;
        !           788:        m->m_pkthdr.len = totlen;
        !           789:        m->m_len = MHLEN;
        !           790: 
        !           791:        top = 0;
        !           792:        mp = &top;
        !           793:        while (totlen > 0) {
        !           794:                if (top) {
        !           795:                        MGET(m, M_DONTWAIT, MT_DATA);
        !           796:                        if (m == 0) {
        !           797:                                m_freem(top);
        !           798:                                return (0);
        !           799:                        }
        !           800:                        m->m_len = MLEN;
        !           801:                }
        !           802:                len = min(totlen, epkt - cp);
        !           803:                if (len >= MINCLSIZE) {
        !           804:                        MCLGET(m, M_DONTWAIT);
        !           805:                        if (m->m_flags & M_EXT)
        !           806:                                m->m_len = len = min(len, MCLBYTES);
        !           807:                        else
        !           808:                                len = m->m_len;
        !           809:                } else {
        !           810:                        /*
        !           811:                         * Place initial small packet/header at end of mbuf.
        !           812:                         */
        !           813:                        if (len < m->m_len) {
        !           814:                                if (top == 0 && len + max_linkhdr <= m->m_len)
        !           815:                                        m->m_data += max_linkhdr;
        !           816:                                m->m_len = len;
        !           817:                        } else
        !           818:                                len = m->m_len;
        !           819:                }
        !           820: 
        !           821:                totlen -= len;
        !           822:                /* only do up to end of buffer */
        !           823:                if (cp+len > sc->we_vmem_end) {
        !           824:                        unsigned toend = sc->we_vmem_end - cp;
        !           825: 
        !           826:                        bcopy(cp, mtod(m, caddr_t), toend);
        !           827:                        cp = sc->we_vmem_ring;
        !           828:                        bcopy(cp, mtod(m, caddr_t)+toend, len - toend);
        !           829:                        cp += len - toend;
        !           830:                        epkt = cp + totlen;
        !           831:                } else {
        !           832:                        bcopy(cp, mtod(m, caddr_t), (unsigned)len);
        !           833:                        cp += len;
        !           834:                }
        !           835:                *mp = m;
        !           836:                mp = &m->m_next;
        !           837:                if (cp == epkt) {
        !           838:                        cp = buf;
        !           839:                        epkt = cp + tc;
        !           840:                }
        !           841:        }
        !           842:        return (top);
        !           843: }
        !           844: #endif

unix.superglobalmegacorp.com

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