Annotation of Net2/arch/i386/isa/if_we.c, revision 1.1.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.