Annotation of Gnu-Mach/chips/lance.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1993-1989 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  * 
        !             6:  * Permission to use, copy, modify and distribute this software and its
        !             7:  * documentation is hereby granted, provided that both the copyright
        !             8:  * notice and this permission notice appear in all copies of the
        !             9:  * software, derivative works or modified versions, and any portions
        !            10:  * thereof, and that both notices appear in supporting documentation.
        !            11:  * 
        !            12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            15:  * 
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  * 
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Science
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  * 
        !            23:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            24:  * the rights to redistribute these changes.
        !            25:  */
        !            26: /*
        !            27:  *     File:   lance.c
        !            28:  *     Author: Robert V. Baron & Alessandro Forin
        !            29:  *     Date:   5/90
        !            30:  *
        !            31:  *     Driver for the DEC LANCE Ethernet Controller.
        !            32:  */
        !            33: 
        !            34: /*
        !            35:  
        !            36:   Byte ordering issues.
        !            37: 
        !            38:   The lance sees data naturally as half word (16 bit) quantitites. 
        !            39:   Bit 2 (BSWP) in control register 3 (CSR3) controls byte swapping.
        !            40:   To quote the spec:
        !            41: 
        !            42:   02   BSWP    BYTE SWAP allows the chip to 
        !            43:                operate in systems that consdier bits (15:08) of data pointers
        !            44:                by an even addressa and bits (7:0) to be pointed by an 
        !            45:                odd address.
        !            46: 
        !            47:                When BSWP=1, the chip will swap the high and low bytes on DMA
        !            48:                data transfers between the silo and bus memory. Only data from
        !            49:                silo transfers is swapped; the Initialization Block data and 
        !            50:                the Descriptor Ring entries are NOT swapped. (emphasis theirs)
        !            51:   
        !            52: 
        !            53:   So on systems with BYTE_MSF=1, the BSWP bit should be set. Note,
        !            54:   however, that all shorts in the descriptor ring and initialization
        !            55:   block need to be swapped. The BITFIELD macros in lance.h handle this
        !            56:   magic.
        !            57: 
        !            58: */
        !            59: 
        !            60: #include <ln.h>
        !            61: #if     NLN > 0
        !            62: #include <platforms.h>
        !            63: 
        !            64: /*
        !            65:  * AMD Am7990 LANCE (Ethernet Interface)
        !            66:  */
        !            67: #include <sys/ioctl.h>
        !            68: #include <vm/vm_kern.h>
        !            69: 
        !            70: #include <machine/machspl.h>           /* spl definitions */
        !            71: #include <kern/time_out.h>
        !            72: #include <sys/syslog.h>
        !            73: #include <ipc/ipc_port.h>
        !            74: #include <ipc/ipc_kmsg.h>
        !            75: 
        !            76: #include <device/device_types.h>
        !            77: #include <device/errno.h>
        !            78: #include <device/io_req.h>
        !            79: #include <device/if_hdr.h>
        !            80: #include <device/if_ether.h>
        !            81: #include <device/net_status.h>
        !            82: #include <device/net_io.h>
        !            83: 
        !            84: #ifdef FLAMINGO
        !            85: #define se_reg_type unsigned int
        !            86: #endif
        !            87: 
        !            88: #include <chips/lance.h>
        !            89: #include <chips/busses.h>
        !            90: 
        !            91: #define private static
        !            92: #define public
        !            93: 
        !            94: typedef struct se_softc *se_softc_t; /* move above prototypes */
        !            95: 
        !            96: void se_write_reg(); /* forwards */
        !            97: void se_read();
        !            98: void se_rint();
        !            99: void se_tint();
        !           100: 
        !           101: private vm_offset_t se_Hmem_nogap(), se_Hmem_gap16();
        !           102: private vm_offset_t se_malloc();
        !           103: 
        !           104: 
        !           105: /* This config section should go into a separate file */
        !           106: 
        !           107: #ifdef  LUNA88K
        !           108: # include <luna88k/board.h>
        !           109: # define MAPPED 1
        !           110:   #undef bcopy
        !           111:   extern void bcopy(), bzero();
        !           112: 
        !           113: #define wbflush()
        !           114: #define Hmem(lna)      (vm_offset_t)((lna) + sc->lnbuf)
        !           115: #define Lmem(lna)      (vm_offset_t)((lna) + sc->lnoffset)
        !           116: 
        !           117: #define SPACE (TRI_PORT_RAM_SPACE>>1)
        !           118: private struct se_switch se_switch[] = {
        !           119:        {   LANCE_ADDR - TRI_PORT_RAM,  /* pointer */
        !           120:            SPACE /* host side */, 
        !           121:            SPACE /* lance side */, 
        !           122:            - TRI_PORT_RAM,
        !           123:            0, /* romstride */
        !           124:            0, /* ramstride */
        !           125:            SPACE, 
        !           126:            /* desc_copyin */   bcopy,
        !           127:            /* desc_copyout */  bcopy,
        !           128:            /* data_copyin */   bcopy,
        !           129:            /* data_copyout */  bcopy,
        !           130:            /* bzero */         bzero,
        !           131:            /* mapaddr */       se_Hmem_nogap,
        !           132:            /* mapoffs */       se_Hmem_nogap
        !           133:       },
        !           134: };
        !           135: 
        !           136: #endif
        !           137: 
        !           138: #ifdef DECSTATION
        !           139: #include <mips/mips_cpu.h>
        !           140: #include <mips/PMAX/pmad_aa.h>
        !           141: 
        !           142: #define        MAPPED 1
        !           143: 
        !           144: /*
        !           145:  * The LANCE buffer memory as seen from the Pmax cpu is funny.
        !           146:  * It is viewed as short words (16bits), spaced at word (32bits)
        !           147:  * intervals.  The same applies to the registers.  From the LANCE
        !           148:  * point of view memory is instead contiguous.
        !           149:  * The ROM that contains the station address is in the space belonging
        !           150:  * to the clock/battery backup memory.  This space is again 16 bits
        !           151:  * in a 32bit envelope.  And the ether address is stored in the "high"
        !           152:  * byte of 6 consecutive quantities.
        !           153:  *
        !           154:  * But Pmaxen and 3maxen (and..) map lance space differently.
        !           155:  * This requires dynamic adaptation of the driver, which
        !           156:  * is done via the following switches.
        !           157:  * For convenience, the switch holds information about
        !           158:  * the location of the lance control registers as well.
        !           159:  * This could be either absolute (pmax) or relative to
        !           160:  * some register base (3max, turbochannel)
        !           161:  */
        !           162: void copyin_gap16(), copyout_gap16(), bzero_gap16();
        !           163: extern void bcopy(), bzero();
        !           164: void copyin_gap32(), copyout_gap32();
        !           165: 
        !           166: private struct se_switch se_switch[] = {
        !           167: /* pmax */
        !           168:        { 0x00000000, 0x01000000, 0x0, 0x05000000, 8, 16, 64*1024, 
        !           169:          copyin_gap16, copyout_gap16, copyin_gap16, copyout_gap16,
        !           170:          bzero_gap16, se_Hmem_gap16, se_Hmem_gap16},
        !           171: /* 3max */
        !           172:        { PMAD_OFFSET_LANCE, PMAD_OFFSET_RAM, PMAD_OFFSET_RAM, PMAD_OFFSET_ROM,
        !           173:          16, 0, PMAD_RAM_SIZE,
        !           174:          bcopy, bcopy, bcopy, bcopy, bzero, se_Hmem_nogap, se_Hmem_nogap},
        !           175: /* 3min */
        !           176: /* XXX re-use other 64k */
        !           177:        { 0/*later*/, 0/*later*/, 0x0, 0/*later*/, 0, 128, 64*1024,
        !           178:          copyin_gap16, copyout_gap16, copyin_gap32, copyout_gap32,
        !           179:          bzero_gap16, se_Hmem_gap16, se_Hmem_nogap},
        !           180: };
        !           181: 
        !           182: /*
        !           183:  * "lna" is what se_malloc hands back.  They are offsets using
        !           184:  * the sizing that the Lance would use. The Lance space is
        !           185:  * mapped somewhere in the I/O space, as indicated by the softc.
        !           186:  * Hence we have these two macros:
        !           187:  */
        !           188: /* H & L are not hi and lo but
        !           189:    H = HOST  == addresses for host to reference board memory
        !           190:    L = LOCAL == addresses on board
        !           191:  */
        !           192: #define Hmem(lna)      (vm_offset_t)((se_sw->mapaddr)(lna) + sc->lnbuf)
        !           193: #define Lmem(lna)      (vm_offset_t)((vm_offset_t)lna + sc->lnoffset)
        !           194: #endif /*DECSTATION*/
        !           195: 
        !           196: 
        !           197: #ifdef VAXSTATION
        !           198: #include <vax/ka3100.h>
        !           199: 
        !           200: #define wbflush()
        !           201: 
        !           202: void xzero(x, l) vm_offset_t x; int l; { blkclr(x, l); }
        !           203: void xcopy(f, t, l) vm_offset_t f, t; int l; { bcopy(f, t, l); }
        !           204: 
        !           205: private struct se_switch se_switch[] = {
        !           206:        /* pvax sees contiguous bits in lower 16Meg of memory */
        !           207:        { 0, 0, 0, 0, 0, 0, 64*1024,
        !           208:          xcopy, xcopy, xcopy, xcopy, xzero, se_Hmem_nogap, se_Hmem_nogap},
        !           209: };
        !           210: 
        !           211: /*
        !           212:  * "lna" is what se_malloc hands back.  They are offsets using
        !           213:  * the sizing that the Lance would use. The Lance space is
        !           214:  * mapped somewhere in the I/O space, as indicated by the softc.
        !           215:  * Hence we have these two macros:
        !           216:  */
        !           217: /* H & L are not hi and lo but
        !           218:    H = HOST  == addresses for host to reference board memory
        !           219:    L = LOCAL == addresses on board
        !           220:  */
        !           221:        /*
        !           222:         * This does not deal with > 16 Meg physical memory, where
        !           223:         * Hmem != Lmem
        !           224:         */
        !           225: #define Hmem(lna)      (vm_offset_t)((lna) + sc->lnbuf)
        !           226: #define Lmem(lna)      (vm_offset_t)((lna) + sc->lnoffset)
        !           227: 
        !           228: #endif /*VAXSTATION*/
        !           229: 
        !           230: 
        !           231: #ifdef FLAMINGO
        !           232: #include <alpha/alpha_cpu.h>
        !           233: 
        !           234: /* XXX might be wrong, mostly stolen from kmin */
        !           235: extern void copyin_gap16(), copyout_gap16(), bzero_gap16();
        !           236: extern void copyin_gap32(), copyout_gap32();
        !           237: extern void bcopy(), bzero();
        !           238: 
        !           239: private struct se_switch se_switch[] = {
        !           240: /* XXX re-use other 64k */
        !           241:        { 0/*later*/, 0/*later*/, 0x0, 0/*later*/, 0, 128, 64*1024,
        !           242:          copyin_gap16, copyout_gap16, copyin_gap32, copyout_gap32,
        !           243:          bzero_gap16, se_Hmem_gap16, se_Hmem_nogap},
        !           244: };
        !           245: 
        !           246: /*
        !           247:  * "lna" is what se_malloc hands back.  They are offsets using
        !           248:  * the sizing that the Lance would use. The Lance space is
        !           249:  * mapped somewhere in the I/O space, as indicated by the softc.
        !           250:  * Hence we have these two macros:
        !           251:  */
        !           252: /* H & L are not hi and lo but
        !           253:    H = HOST  == addresses for host to reference board memory
        !           254:    L = LOCAL == addresses on board
        !           255:  */
        !           256: #define Hmem(lna)      (vm_offset_t)((se_sw->mapaddr)(lna) + sc->lnbuf)
        !           257: #define Lmem(lna)      (vm_offset_t)((vm_offset_t)lna + sc->lnoffset)
        !           258: #endif /*FLAMINGO*/
        !           259: 
        !           260: 
        !           261: /*
        !           262:  * Map a lance-space offset into an host-space one
        !           263:  */
        !           264: private vm_offset_t se_Hmem_nogap( vm_offset_t lna) { return lna;}
        !           265: private vm_offset_t se_Hmem_gap16( vm_offset_t lna) { return lna << 1;}
        !           266: 
        !           267: /*
        !           268:  * Memory addresses for LANCE are 24 bits wide.
        !           269:  */
        !           270: #define Addr_lo(y)     ((unsigned short)((vm_offset_t)(y) & 0xffff))
        !           271: #define        Addr_hi(y)      ((unsigned short)(((vm_offset_t)(y)>>16) & 0xff))
        !           272: 
        !           273: #define        LN_MEMORY_SIZE  (se_sw->ramsize)
        !           274: 
        !           275: /* XXX to accomodate heterogeneity this should be made per-drive */
        !           276: /* XXX and then some more */
        !           277: 
        !           278: struct se_switch *se_sw = se_switch;
        !           279: 
        !           280: void set_se_switch(n)
        !           281: int n;
        !           282: {
        !           283:        se_sw = &se_switch[n];
        !           284: }
        !           285: 
        !           286: #ifndef LUNA88K
        !           287: void setse_switch(n, r, b, l, o)
        !           288:        vm_offset_t     r, b, l, o;
        !           289:        int             n;
        !           290: {
        !           291:        se_switch[n].regspace = r;
        !           292:        se_switch[n].bufspace = b;
        !           293:        se_switch[n].ln_bufspace = l;
        !           294:        se_switch[n].romspace = o;
        !           295: 
        !           296:        /* make sure longword aligned */
        !           297:        if (se_switch[n].bufspace & 0x7) {
        !           298:                se_switch[n].bufspace = (se_switch[n].bufspace+0x7) & ~0x7;
        !           299:        }
        !           300: 
        !           301:        set_se_switch(n);
        !           302: }
        !           303: #endif
        !           304: 
        !           305: /*
        !           306:  * Autoconf info
        !           307:  */
        !           308: 
        !           309: private vm_offset_t se_std[NLN] = { 0 };
        !           310: private struct bus_device *se_info[NLN];
        !           311: private int se_probe();
        !           312: private void se_attach();
        !           313: 
        !           314: struct bus_driver se_driver =
        !           315:        { se_probe, 0, se_attach, 0, se_std, "se", se_info, };
        !           316: 
        !           317: /*
        !           318:  * Externally visible functions
        !           319:  */
        !           320: char   *se_unprobed_addr = 0;
        !           321: void   se_intr();                              /* kernel */
        !           322: 
        !           323: int    se_open(), se_output(), se_get_status(),        /* user */
        !           324:        se_set_status(), se_setinput(), se_restart();
        !           325: 
        !           326: /*
        !           327:  *
        !           328:  * Internal functions & definitions
        !           329:  *
        !           330:  */
        !           331: 
        !           332: private        int se_probe();
        !           333: private  void se_init();
        !           334: private        void init_lance_space();
        !           335: private  void se_desc_set_status();
        !           336: private  volatile long *se_desc_alloc();       /* must be aligned! */
        !           337: void   se_start();
        !           338: private        void copy_from_lance();
        !           339: private        int copy_to_lance();
        !           340: 
        !           341: int se_verbose = 0;    /* debug flag */
        !           342: 
        !           343: #define RLOG   4               /* 2**4 = 16  receive descriptors */
        !           344: #define TLOG   4               /* 2**4 = 16  transmit descriptors */
        !           345: #define NRCV   (1<<RLOG)       /* Receive descriptors */
        !           346: #define NXMT   (1<<TLOG)       /* Transmit descriptors */
        !           347: 
        !           348: #define        LN_BUFFER_SIZE  (0x800-0x80)
        !           349: 
        !           350: /*
        !           351:  * Ethernet software status per interface.
        !           352:  *
        !           353:  * Each interface is referenced by a network interface structure,
        !           354:  * is_if, which contains the output queue for the interface, its address, ...
        !           355:  */
        !           356: int se_loopback_hack = 1;
        !           357: 
        !           358: struct se_softc {
        !           359:        struct  ifnet   is_if;          /* generic interface header     */
        !           360:        unsigned char   is_addr[6];             /* ethernet hardware address    */
        !           361:        unsigned short  pad;
        !           362:        se_reg_t                lnregs;         /* Lance registers      */
        !           363:        vm_offset_t             lnbuf;          /* Lance memory, Host offset */
        !           364:        vm_offset_t             lnoffset;       /* Lance memory, Lance offset */
        !           365:        vm_offset_t             lnrom;
        !           366:        vm_offset_t             lnsbrk;         /* Lance memory allocator */
        !           367:        vm_offset_t             lninit_block;   /* Init block address   */
        !           368:        se_desc_t               lnrring[NRCV];  /* Receive  ring desc. */
        !           369:        volatile long           *lnrbuf[NRCV];  /* Receive  buffers */
        !           370:        se_desc_t               lntring[NXMT];  /* Transmit ring desc. */
        !           371:        volatile long           *lntbuf[NXMT];  /* Transmit buffers */
        !           372: 
        !           373:        int     rcv_last;               /* Rcv buffer last read         */
        !           374: 
        !           375:        io_req_t tpkt[NXMT+1];          /* Xmt pkt queue                */
        !           376:        int     xmt_count;              /* Xmt queue size               */
        !           377:        int     xmt_last;               /* Xmt queue head (insert)      */
        !           378:        int     xmt_complete;           /* Xmt queue tail (remove)      */
        !           379: 
        !           380:        int     se_flags;               /* Flags for SIOCSIFFLAGS       */
        !           381:        int     counters[4];            /* error counters */
        !           382: #define bablcnt  counters[0]
        !           383: #define misscnt  counters[1]
        !           384: #define merrcnt  counters[2]
        !           385: #define rstrtcnt counters[3]
        !           386: } se_softc_data[NLN];
        !           387: 
        !           388: se_softc_t     se_softc[NLN];          /* quick access */
        !           389: 
        !           390: /*
        !           391:  * Probe the Lance to see if it's there
        !           392:  */
        !           393: private int se_open_state = 0;
        !           394: 
        !           395: private int se_probe(
        !           396:        vm_offset_t reg,
        !           397:        register struct bus_device *ui)
        !           398: {
        !           399:        register se_softc_t sc;
        !           400:        se_reg_t        rdp, rap;
        !           401:        int             unit = ui->unit;
        !           402: 
        !           403:        /*
        !           404:         * See if the interface is there by reading the lance CSR.  On pmaxen
        !           405:         * and 3maxen this is superfluous, but.. 
        !           406:         */
        !           407:        rdp = (se_reg_t) (reg + se_sw->regspace);
        !           408: #ifdef DECSTATION
        !           409:        if (check_memory(rdp, 0))
        !           410:                return 0;
        !           411: #endif /*DECSTATION*/
        !           412: #ifdef MAPPED
        !           413:        SE_probe(reg,ui);
        !           414: #endif /*MAPPED*/
        !           415:        rap = rdp + 2;          /* XXX might not be true in the future XXX */
        !           416:                                /* rdp and rap are "shorts" on consecutive
        !           417:                                   "long" word boundaries */
        !           418: 
        !           419:        /*
        !           420:         * Bind this interface to the softc. 
        !           421:         */
        !           422:        sc = &se_softc_data[unit];
        !           423:        se_softc[unit] = sc;
        !           424:        sc->lnregs      = (se_reg_t) (reg + se_sw->regspace);
        !           425:        sc->lnbuf       = (vm_offset_t) (reg + se_sw->bufspace);
        !           426:        sc->lnoffset    = (vm_offset_t) (se_sw->ln_bufspace);
        !           427:        sc->lnrom       = (vm_offset_t) (reg + se_sw->romspace);
        !           428: 
        !           429:        /*
        !           430:         * Reset the interface, and make sure we really do it! (the 3max
        !           431:         * seems quite stubborn about these registers) 
        !           432:         */
        !           433:        se_write_reg(rap, CSR0_SELECT, CSR0_SELECT, "RAP");
        !           434:        se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0");
        !           435: 
        !           436:        /*
        !           437:         * Allocate lance RAM buffer memory 
        !           438:         */
        !           439:        init_lance_space(sc);
        !           440: 
        !           441:        /*
        !           442:         * Initialize the chip
        !           443:         *
        !           444:         * NOTE: From now on we will only touch csr0
        !           445:         */
        !           446:        if (se_ship_init_block(sc, unit))
        !           447:                return 0;
        !           448: 
        !           449:        /*
        !           450:         * Tell the world we are alive and well 
        !           451:         */
        !           452:        se_open_state++;
        !           453:        return 1;
        !           454: }
        !           455: 
        !           456: int se_ship_init_block(
        !           457:        register se_softc_t sc,
        !           458:        int             unit)
        !           459: {
        !           460:        se_reg_t        rdp = sc->lnregs;
        !           461:        se_reg_t        rap;
        !           462:        register int    i = 0;
        !           463: 
        !           464:        rap = rdp + 2;          /* XXX might not be true in the future XXX */
        !           465: 
        !           466:        /*
        !           467:         * Load LANCE control block. 
        !           468:         */
        !           469: 
        !           470: #ifdef LUNA88K
        !           471:        /* turn on byte swap bit in csr3, set bcon bit - as in 2.5 */
        !           472:        se_write_reg(rap, CSR3_SELECT, CSR3_SELECT, "RAP");
        !           473:        se_write_reg(rdp, LN_CSR3_BSWP|LN_CSR3_BCON, 
        !           474:                          LN_CSR3_BSWP|LN_CSR3_BCON, "csr3"); 
        !           475: #endif
        !           476:        
        !           477:        se_write_reg(rap, CSR1_SELECT, CSR1_SELECT, "RAP");
        !           478:        se_write_reg(rdp, Addr_lo(Lmem(sc->lninit_block)),
        !           479:                     Addr_lo(Lmem(sc->lninit_block)), "csr1");
        !           480: 
        !           481:        se_write_reg(rap, CSR2_SELECT, CSR2_SELECT, "RAP");
        !           482:        se_write_reg(rdp, Addr_hi(Lmem(sc->lninit_block)),
        !           483:                     Addr_hi(Lmem(sc->lninit_block)), "csr2");
        !           484: 
        !           485:        /*
        !           486:         * Start the INIT sequence now
        !           487:         */
        !           488:        se_write_reg(rap, CSR0_SELECT, CSR0_SELECT, "RAP");
        !           489:        *rdp = (LN_CSR0_IDON | LN_CSR0_INIT);
        !           490:        wbflush();
        !           491: 
        !           492:        /* give it plenty of time to settle */
        !           493:        while (i++ < 10000) {
        !           494:                delay(100);
        !           495:                if ((*rdp & LN_CSR0_IDON) != 0)
        !           496:                        break;
        !           497:        }
        !           498:        /* make sure got out okay */
        !           499:        if ((*rdp & LN_CSR0_IDON) == 0) {
        !           500:                printf("se%d: cannot initialize\n", unit);
        !           501:                if (*rdp & LN_CSR0_ERR)
        !           502:                        printf("se%d: initialization error, csr = %04x\n",
        !           503:                               unit, (*rdp & 0xffff));
        !           504:                return 1;
        !           505:        }
        !           506:        /*
        !           507:         * Do not enable interrupts just yet. 
        !           508:         */
        !           509:        /* se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0"); */
        !           510: 
        !           511:        return 0;
        !           512: }
        !           513:  
        !           514: void
        !           515: se_write_reg(
        !           516:        register se_reg_t       regptr,
        !           517:        register int            val,
        !           518:        register int            result,
        !           519:        char                    *regname)
        !           520: {
        !           521:        register int    i = 0;
        !           522: 
        !           523:        while ((unsigned short)(*regptr) != (unsigned short)result) {
        !           524:                *regptr = (se_reg_type)val;
        !           525:                wbflush();
        !           526:                if (++i > 10000) {
        !           527:                        printf("se: %s did not settle (to x%x): x%x\n",
        !           528:                               regname, result, (unsigned short)(*regptr));
        !           529:                        return;
        !           530:                }
        !           531:                delay(100);
        !           532:        }
        !           533: }
        !           534: 
        !           535: unsigned short
        !           536: se_read_reg(
        !           537:        register se_reg_t regptr)
        !           538: {
        !           539:        return (unsigned short) (*regptr);
        !           540: }
        !           541: 
        !           542: private void
        !           543: init_lance_space(
        !           544:        register se_softc_t sc)
        !           545: {
        !           546:        register int    lptr;                   /* Generic lance pointer */
        !           547:        se_desc_t       ringaddr;
        !           548:        long           *rom_eaddress = (long *) sc->lnrom;
        !           549:        int             i;
        !           550:        struct se_init_block    init_block;
        !           551: 
        !           552:        /*
        !           553:         * Allocate local RAM buffer memory for the init block,
        !           554:         * fill in our local copy then copyout.
        !           555:         */
        !           556: 
        !           557:        sc->lninit_block = se_malloc(sc, sizeof (struct se_init_block));
        !           558: 
        !           559:        /*
        !           560:         * Set values on stack, then copyout en-masse
        !           561:         */
        !           562:        bzero(&init_block, sizeof(init_block));
        !           563:        init_block.mode = 0;
        !           564: 
        !           565:        /* byte swapping between host and lance */
        !           566: 
        !           567:        init_block.phys_addr_low = ((rom_eaddress[0]>>se_sw->romstride)&0xff) |
        !           568:                              (((rom_eaddress[1]>>se_sw->romstride)&0xff) << 8);
        !           569:        init_block.phys_addr_med = ((rom_eaddress[2]>>se_sw->romstride)&0xff) |
        !           570:                              (((rom_eaddress[3]>>se_sw->romstride)&0xff) << 8);
        !           571:        init_block.phys_addr_high = ((rom_eaddress[4]>>se_sw->romstride)&0xff) |
        !           572:                              (((rom_eaddress[5]>>se_sw->romstride)&0xff) << 8);
        !           573: 
        !           574:        /*
        !           575:         * Allocate both descriptor rings at once.
        !           576:         * Note that the quadword alignment requirement is
        !           577:         * inherent in the way we perform allocation,
        !           578:         * but it does depend on the size of the init block.
        !           579:         */
        !           580:        lptr = se_malloc(sc, sizeof (struct se_desc) * (NXMT + NRCV));
        !           581: 
        !           582:        /*
        !           583:         * Initialize the buffer descriptors
        !           584:         */
        !           585:        init_block.recv_ring_pointer_lo = Addr_lo(Lmem(lptr));
        !           586:        init_block.recv_ring_pointer_hi = Addr_hi(Lmem(lptr));
        !           587:        init_block.recv_ring_len = RLOG;
        !           588: 
        !           589:        for ( i = 0; i < NRCV ; i++, lptr += sizeof(struct se_desc)) {
        !           590:                ringaddr = (se_desc_t)Hmem(lptr);
        !           591:                sc->lnrring[i] = ringaddr;
        !           592:                sc->lnrbuf[i] = se_desc_alloc (sc, ringaddr);
        !           593:        }
        !           594: 
        !           595:        init_block.xmit_ring_pointer_lo = Addr_lo(Lmem(lptr));
        !           596:        init_block.xmit_ring_pointer_hi = Addr_hi(Lmem(lptr));
        !           597:        init_block.xmit_ring_len = TLOG;
        !           598: 
        !           599:        for ( i = 0 ; i < NXMT ; i++, lptr += sizeof(struct se_desc)) {
        !           600:                ringaddr = (se_desc_t)Hmem(lptr);
        !           601:                sc->lntring[i] = ringaddr;
        !           602:                sc->lntbuf[i] = se_desc_alloc (sc, ringaddr);
        !           603:        }
        !           604: 
        !           605:        /*
        !           606:         * No logical address filtering
        !           607:         */
        !           608:        init_block.logical_addr_filter0 = 0;
        !           609:        init_block.logical_addr_filter1 = 0;
        !           610:        init_block.logical_addr_filter2 = 0;
        !           611:        init_block.logical_addr_filter3 = 0;
        !           612: 
        !           613:        /*
        !           614:         * Move init block into lance space
        !           615:         */
        !           616:        (se_sw->desc_copyout)((vm_offset_t)&init_block, Hmem(sc->lninit_block), sizeof(init_block));
        !           617:        wbflush();
        !           618: }
        !           619: 
        !           620: /*
        !           621:  * Interface exists: make available by filling in network interface
        !           622:  * record.  System will initialize the interface when it is ready
        !           623:  * to accept packets.
        !           624:  */
        !           625: private void
        !           626: se_attach(
        !           627:        register struct bus_device *ui)
        !           628: {
        !           629:        unsigned char         *enaddr;
        !           630:        struct ifnet   *ifp;
        !           631:        long           *rom_eaddress;
        !           632:        int             unit = ui->unit;
        !           633:        se_softc_t      sc = se_softc[unit];
        !           634: 
        !           635:        rom_eaddress = (long *) sc->lnrom;
        !           636: 
        !           637:        /*
        !           638:         * Read the address from the prom and save it. 
        !           639:         */
        !           640:        enaddr = sc->is_addr;
        !           641:        enaddr[0] = (unsigned char) ((rom_eaddress[0] >> se_sw->romstride) & 0xff);
        !           642:        enaddr[1] = (unsigned char) ((rom_eaddress[1] >> se_sw->romstride) & 0xff);
        !           643:        enaddr[2] = (unsigned char) ((rom_eaddress[2] >> se_sw->romstride) & 0xff);
        !           644:        enaddr[3] = (unsigned char) ((rom_eaddress[3] >> se_sw->romstride) & 0xff);
        !           645:        enaddr[4] = (unsigned char) ((rom_eaddress[4] >> se_sw->romstride) & 0xff);
        !           646:        enaddr[5] = (unsigned char) ((rom_eaddress[5] >> se_sw->romstride) & 0xff);
        !           647: 
        !           648:        printf(": %x-%x-%x-%x-%x-%x",
        !           649:               (rom_eaddress[0] >> se_sw->romstride) & 0xff,
        !           650:               (rom_eaddress[1] >> se_sw->romstride) & 0xff,
        !           651:               (rom_eaddress[2] >> se_sw->romstride) & 0xff,
        !           652:               (rom_eaddress[3] >> se_sw->romstride) & 0xff,
        !           653:               (rom_eaddress[4] >> se_sw->romstride) & 0xff,
        !           654:               (rom_eaddress[5] >> se_sw->romstride) & 0xff);
        !           655: 
        !           656:        /*
        !           657:         * Initialize the standard interface descriptor 
        !           658:         */
        !           659:        ifp = &sc->is_if;
        !           660:        ifp->if_unit = unit;
        !           661:        ifp->if_header_size = sizeof(struct ether_header);
        !           662:        ifp->if_header_format = HDR_ETHERNET;
        !           663:        ifp->if_address_size = 6;
        !           664:        ifp->if_mtu = ETHERMTU;
        !           665:        ifp->if_flags |= IFF_BROADCAST;
        !           666: 
        !           667:        ifp->if_address = (char *) enaddr;
        !           668: 
        !           669:        if_init_queues(ifp);
        !           670: #ifdef MAPPED
        !           671:        SE_attach(ui);
        !           672: #endif /*MAPPED*/
        !           673: 
        !           674: }
        !           675: 
        !           676: /*
        !           677:  * Use a different hardware address for interface
        !           678:  */
        !           679: void
        !           680: se_setaddr(
        !           681:        unsigned char   eaddr[6],
        !           682:        int             unit)
        !           683: {
        !           684:        register se_softc_t sc = se_softc[unit];
        !           685:        struct se_init_block    init_block;
        !           686: 
        !           687:        /*
        !           688:         * Modify initialization block accordingly
        !           689:         */
        !           690:        (se_sw->desc_copyin) (Hmem(sc->lninit_block), (vm_offset_t)&init_block, sizeof(init_block));
        !           691:        bcopy(eaddr, &init_block.phys_addr_low, sizeof(*eaddr));
        !           692:        (se_sw->desc_copyout)((vm_offset_t)&init_block, Hmem(sc->lninit_block), sizeof(init_block));
        !           693:        /*
        !           694:         * Make a note of it
        !           695:         */
        !           696:        bcopy(eaddr, sc->is_addr, sizeof(*eaddr));
        !           697: 
        !           698:        /*
        !           699:         * Restart the interface
        !           700:         */
        !           701:        se_restart(&sc->is_if);
        !           702:        se_init(unit);
        !           703: }
        !           704: 
        !           705: /*
        !           706:  * Restart interface
        !           707:  *
        !           708:  * We use this internally on those errors that hang the chip,
        !           709:  * not sure yet what use the MI code will make of it.
        !           710:  *
        !           711:  * After stopping the chip and effectively turning off the interface
        !           712:  * we release all pending buffers and cause the chip to init
        !           713:  * itself.  We do not enable interrupts here.
        !           714:  */
        !           715: int
        !           716: se_restart( register struct ifnet *ifp )
        !           717: {
        !           718:        register se_softc_t sc = se_softc[ifp->if_unit];
        !           719:        se_reg_t        rdp;
        !           720:        register int    i;
        !           721: 
        !           722:        rdp = sc->lnregs;
        !           723: 
        !           724:        /*
        !           725:         * stop the chip 
        !           726:         */
        !           727:        se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0");
        !           728: 
        !           729:        /*
        !           730:         * stop network activity 
        !           731:         */
        !           732:        if (ifp->if_flags & IFF_RUNNING) {
        !           733:                ifp->if_flags &= ~(IFF_UP | IFF_RUNNING);
        !           734:                sc->se_flags &= ~(IFF_UP | IFF_RUNNING);
        !           735:        }
        !           736:        sc->rstrtcnt++;
        !           737: 
        !           738:        if (se_verbose)
        !           739:                printf("se%d: %d restarts\n", ifp->if_unit, sc->rstrtcnt);
        !           740: 
        !           741:        /*
        !           742:         * free up any buffers currently in use 
        !           743:         */
        !           744:        for (i = 0; i < NXMT; i++)
        !           745:                if (sc->tpkt[i]) {
        !           746:                        iodone(sc->tpkt[i]);
        !           747:                        sc->tpkt[i] = (io_req_t) 0;
        !           748:                }
        !           749:        /*
        !           750:         * INIT the chip again, no need to reload init block address. 
        !           751:         */
        !           752:        se_ship_init_block(sc, ifp->if_unit);
        !           753: 
        !           754:        return (0);
        !           755: }
        !           756: 
        !           757: /*
        !           758:  * Initialize the interface.
        !           759:  */
        !           760: private void
        !           761: se_init( int unit )
        !           762: {
        !           763:        register se_softc_t      sc = se_softc[unit];
        !           764:        register se_desc_t      *rp;
        !           765:        register struct ifnet   *ifp = &sc->is_if;
        !           766:        se_reg_t        rdp;
        !           767:        short           mode;
        !           768:        spl_t           s;
        !           769:        int             i;
        !           770: 
        !           771:        if (ifp->if_flags & IFF_RUNNING)
        !           772:                return;
        !           773: 
        !           774:        rdp = sc->lnregs;
        !           775: 
        !           776:        /*
        !           777:         * Init the buffer descriptors and indexes for each of the rings. 
        !           778:         */
        !           779:        for (i = 0, rp = sc->lnrring; i < NRCV; i++, rp++)
        !           780:                se_desc_set_status(*rp, LN_RSTATE_OWN);
        !           781: 
        !           782:        for (i = 0, rp = sc->lntring; i < NXMT; i++, rp++)
        !           783:                se_desc_set_status(*rp, 0);
        !           784: 
        !           785:        sc->xmt_count = sc->xmt_complete = sc->xmt_last = sc->rcv_last = 0;
        !           786: 
        !           787:        /*
        !           788:         * Deal with loopback mode operation 
        !           789:         */
        !           790:        s = splimp();
        !           791: 
        !           792:        (se_sw->desc_copyin) (Hmem(sc->lninit_block), (vm_offset_t)&mode, sizeof(mode));
        !           793: 
        !           794:        if (ifp->if_flags & IFF_LOOPBACK
        !           795:            && ((mode & LN_MODE_LOOP) == 0)) {
        !           796:                /* if not already in loopback mode, do external loopback */
        !           797:                mode &= ~LN_MODE_INTL;
        !           798:                mode |= LN_MODE_LOOP;
        !           799:                (se_sw->desc_copyout) ((vm_offset_t)&mode, Hmem(sc->lninit_block), sizeof(mode));
        !           800:                se_restart(ifp);
        !           801:                se_init(ifp->if_unit);
        !           802:                splx(s);
        !           803:                return;
        !           804:        }
        !           805: 
        !           806:        ifp->if_flags |= (IFF_UP | IFF_RUNNING);
        !           807:        sc->se_flags |= (IFF_UP | IFF_RUNNING);
        !           808: 
        !           809:        /*
        !           810:         * Start the Lance and enable interrupts 
        !           811:         */
        !           812:        *rdp = (LN_CSR0_STRT | LN_CSR0_INEA);
        !           813:        wbflush();
        !           814: 
        !           815:        /*
        !           816:         * See if anything is already queued 
        !           817:         */
        !           818:        se_start(unit);
        !           819:        splx(s);
        !           820: }
        !           821: 
        !           822: 
        !           823: /*
        !           824:  * Shut off the lance
        !           825:  */
        !           826: void
        !           827: se_stop(int unit)
        !           828: {
        !           829:        se_reg_t        rdp = se_softc[unit]->lnregs;
        !           830: 
        !           831:        se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0");
        !           832: }
        !           833: 
        !           834: 
        !           835: /*
        !           836:  * Open the device, declaring the interface up
        !           837:  * and enabling lance interrupts.
        !           838:  */
        !           839: /*ARGSUSED*/
        !           840: int
        !           841: se_open(
        !           842:        int     unit,
        !           843:        int     flag)
        !           844: {
        !           845:        register se_softc_t     sc = se_softc[unit];
        !           846: 
        !           847:        if (unit >= NLN)
        !           848:                return EINVAL;
        !           849:        if (!se_open_state)
        !           850:                return ENXIO;
        !           851: 
        !           852:        sc->is_if.if_flags |= IFF_UP;
        !           853:        se_open_state++;
        !           854:        se_init(unit);
        !           855:        return (0);
        !           856: }
        !           857: 
        !           858: #ifdef MAPPED
        !           859: int se_use_mapped_interface[NLN];
        !           860: #endif /*MAPPED*/
        !           861: 
        !           862: void
        !           863: se_normal(int unit)
        !           864: {
        !           865: #ifdef MAPPED
        !           866:        se_use_mapped_interface[unit] = 0;
        !           867: #endif /*MAPPED*/
        !           868:        if (se_softc[unit]) {
        !           869:                se_restart((struct ifnet *)se_softc[unit]);
        !           870:                se_init(unit);
        !           871:        }
        !           872: }
        !           873: 
        !           874: /*
        !           875:  * Ethernet interface interrupt routine
        !           876:  */
        !           877: void
        !           878: se_intr(
        !           879:        int     unit,
        !           880:        spl_t   spllevel)
        !           881: {
        !           882:        register se_softc_t      sc = se_softc[unit];
        !           883:        se_reg_t                 rdp;
        !           884:        register struct ifnet   *ifp = &sc->is_if;
        !           885:        register unsigned short  csr;
        !           886: 
        !           887: #ifdef MAPPED
        !           888:        if (se_use_mapped_interface[unit])
        !           889:        {
        !           890:                SE_intr(unit,spllevel);
        !           891:                return;
        !           892:        }
        !           893: #endif /*MAPPED*/
        !           894: 
        !           895:        if (se_open_state < 2) { /* Stray, or not open for business */
        !           896:                rdp = (sc ? sc->lnregs : (se_reg_t)se_unprobed_addr);
        !           897:                *rdp |= LN_CSR0_STOP;
        !           898:                wbflush();
        !           899:                return;
        !           900:        }
        !           901:        rdp = sc->lnregs;
        !           902: 
        !           903:        /*
        !           904:         * Read the CSR and process any error condition.
        !           905:         * Later on, restart the lance by writing back
        !           906:         * the CSR (for set-to-clear bits).
        !           907:         */
        !           908:        csr = *rdp;             /* pick up the csr */
        !           909: 
        !           910:        /* drop spurious interrupts */
        !           911:        if ((csr & LN_CSR0_INTR) == 0)
        !           912:          return;
        !           913: 
        !           914: #ifdef DECSTATION
        !           915:        splx(spllevel); /* drop priority now */
        !           916: #endif /*DECSTATION*/
        !           917: again:
        !           918:        /*
        !           919:         * Check for errors first
        !           920:         */
        !           921:        if ( csr & LN_CSR0_ERR ) {
        !           922:                if (csr & LN_CSR0_MISS) {
        !           923:                        /*
        !           924:                         * Stop the chip to prevent a corrupt packet from
        !           925:                         * being transmitted.  There is a known problem with
        !           926:                         * missed packet errors causing corrupted data to
        !           927:                         * be transmitted to the same host as was just
        !           928:                         * transmitted, with a valid crc appended to the
        !           929:                         * packet.  The only solution is to stop the chip,
        !           930:                         * which will clear the Lance silo, thus preventing
        !           931:                         * the corrupt data from being sent.
        !           932:                         */
        !           933:                        se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0");
        !           934: 
        !           935:                        sc->misscnt++;
        !           936:                        if (se_verbose) {
        !           937:                                int me = 0, lance = 0, index;
        !           938:                                struct se_desc r;
        !           939:                                for (index = 0; index < NRCV; index++) {
        !           940:                                        (se_sw->desc_copyin)(
        !           941:                                            (vm_offset_t)sc->lnrring[index],
        !           942:                                            (vm_offset_t)&r,
        !           943:                                            sizeof(r));
        !           944:                                        if (r.status & LN_RSTATE_OWN)
        !           945:                                                lance++;
        !           946:                                        else
        !           947:                                                me++;
        !           948:                                }
        !           949:                                printf("se%d: missed packet (%d) csr = %x, Lance %x, me %x\n",
        !           950:                                        unit, sc->misscnt, csr, lance, me);
        !           951:                        }
        !           952:                        se_restart(ifp);
        !           953:                        se_init(unit);
        !           954:                        return;
        !           955:                }
        !           956:                if (csr & LN_CSR0_BABL) {
        !           957:                        sc->bablcnt++;
        !           958:                        if (se_verbose)
        !           959:                            printf("se%d: xmt timeout (%d)\n",
        !           960:                                   unit, sc->bablcnt);
        !           961:                }
        !           962:                if (csr & LN_CSR0_MERR) {
        !           963:                        sc->merrcnt++;
        !           964:                        printf("se%d: memory error (%d)\n",
        !           965:                                   unit, sc->merrcnt);
        !           966: 
        !           967:                        if (((csr & LN_CSR0_RXON) == 0)
        !           968:                            || ((csr & LN_CSR0_TXON) == 0)) {
        !           969:                                se_restart(ifp);
        !           970:                                se_init(unit);
        !           971:                                return;
        !           972:                        }
        !           973:                }
        !           974:        }
        !           975: 
        !           976:        *rdp = LN_CSR0_INEA | (csr & LN_CSR0_WTC);
        !           977:        wbflush();
        !           978: 
        !           979:        if ( csr & LN_CSR0_RINT )
        !           980:                se_rint( unit );
        !           981: 
        !           982:        if ( csr & LN_CSR0_TINT )
        !           983:                se_tint( unit );
        !           984: 
        !           985:        if ((csr = *rdp) & (LN_CSR0_RINT | LN_CSR0_TINT))
        !           986:                goto again;
        !           987: }
        !           988:  
        !           989: /*
        !           990:  * Handle a transmitter complete interrupt.
        !           991:  */
        !           992: void
        !           993: se_tint(int unit)
        !           994: {
        !           995:        register se_softc_t sc = se_softc[unit];
        !           996:        register        index;
        !           997:        register        status;
        !           998:        io_req_t        request;
        !           999:        struct se_desc  r;
        !          1000: 
        !          1001:        /*
        !          1002:         * Free up descriptors for all packets in queue for which
        !          1003:         * transmission is complete.  Start from queue tail, stop at first
        !          1004:         * descriptor we do not OWN, or which is in an inconsistent state
        !          1005:         * (lance still working). 
        !          1006:         */
        !          1007: 
        !          1008:        while ((sc->xmt_complete != sc->xmt_last) && (sc->xmt_count > 0)) {
        !          1009: 
        !          1010:                index = sc->xmt_complete;
        !          1011:                (se_sw->desc_copyin) ((vm_offset_t)sc->lntring[index],
        !          1012:                                      (vm_offset_t)&r, sizeof(r));
        !          1013:                status = r.status;
        !          1014: 
        !          1015:                /*
        !          1016:                 * Does lance still own it ? 
        !          1017:                 */
        !          1018:                if (status & LN_TSTATE_OWN)
        !          1019:                        break;
        !          1020: 
        !          1021:                /*
        !          1022:                 * Packet sent allright, release queue slot.
        !          1023:                 */
        !          1024:                request = sc->tpkt[index];
        !          1025:                sc->tpkt[index] = (io_req_t) 0;
        !          1026:                sc->xmt_complete = ++index & (NXMT - 1);
        !          1027:                --sc->xmt_count;
        !          1028: 
        !          1029:                sc->is_if.if_opackets++;
        !          1030:                if (status & (LN_TSTATE_DEF|LN_TSTATE_ONE|LN_TSTATE_MORE))
        !          1031:                        sc->is_if.if_collisions++;
        !          1032: 
        !          1033:                /*
        !          1034:                 * Check for transmission errors. 
        !          1035:                 */
        !          1036:                if (!se_loopback_hack && status & LN_TSTATE_ERR) {
        !          1037:                        sc->is_if.if_oerrors++;
        !          1038:                        if (se_verbose)
        !          1039:                                printf("se%d: xmt error (x%x)\n", unit, r.status2);
        !          1040: 
        !          1041:                        if (r.status2 & (LN_TSTATE2_RTRY|LN_TSTATE2_LCOL))
        !          1042:                                sc->is_if.if_collisions++;
        !          1043: 
        !          1044:                        /*
        !          1045:                         * Restart chip on errors that disable the
        !          1046:                         * transmitter. 
        !          1047:                         */
        !          1048:                        iodone(request);
        !          1049:                        if (r.status2 & LN_TSTATE2_DISABLE) {
        !          1050:                                register struct ifnet *ifp = &sc->is_if;
        !          1051:                                se_restart(ifp);
        !          1052:                                se_init(ifp->if_unit);
        !          1053:                                return;
        !          1054:                        }
        !          1055:                } else if (request) {
        !          1056:                        /*
        !          1057:                         * If this was a broadcast packet loop it back.
        !          1058:                         * Signal successful transmission of the packet. 
        !          1059:                         */
        !          1060:                        register struct ether_header *eh;
        !          1061:                        register int    i;
        !          1062: 
        !          1063:                        eh = (struct ether_header *) request->io_data;
        !          1064:                        /* ether broadcast address is in the spec */
        !          1065:                        for (i = 0; (i < 6) && (eh->ether_dhost[i] == 0xff); i++)
        !          1066:                                ; /* nop */
        !          1067:                        /* sending to ourselves makes sense sometimes */
        !          1068:                        if (i != 6 && se_loopback_hack)
        !          1069:                                for (i = 0;
        !          1070:                                     (i < 6) && (eh->ether_dhost[i] == sc->is_addr[i]);
        !          1071:                                     i++)
        !          1072:                                ; /* nop */
        !          1073:                        if (i == 6)
        !          1074:                                se_read(sc, 0, request->io_count, request);
        !          1075:                        iodone(request);
        !          1076:                }
        !          1077:        }
        !          1078:        /*
        !          1079:         * Dequeue next transmit request, if any. 
        !          1080:         */
        !          1081:        if (sc->xmt_count <= 0)
        !          1082:                se_start(unit);
        !          1083: }
        !          1084:  
        !          1085: /*
        !          1086:  * Handle a receiver complete interrupt.
        !          1087:  */
        !          1088: void
        !          1089: se_rint(int unit)
        !          1090: {
        !          1091:        register se_softc_t     sc = se_softc[unit];
        !          1092:        register        index, first, len;
        !          1093:        unsigned char          status, status1;
        !          1094:        int             ring_cnt;
        !          1095:        struct se_desc  r;
        !          1096: 
        !          1097:        /*
        !          1098:         * Starting from where we left off, look around the receive ring and
        !          1099:         * pass on all complete packets. 
        !          1100:         */
        !          1101: 
        !          1102:        for (;; sc->rcv_last = ++index & (NRCV - 1)) {
        !          1103: 
        !          1104:                /*
        !          1105:                 * Read in current descriptor 
        !          1106:                 */
        !          1107: read_descriptor:
        !          1108:                (se_sw->desc_copyin) ((vm_offset_t)sc->lnrring[sc->rcv_last],
        !          1109:                                      (vm_offset_t)&r, sizeof(r));
        !          1110:                status = r.status;
        !          1111:                if (status & LN_RSTATE_OWN)
        !          1112:                        break;
        !          1113:                first = index = sc->rcv_last;
        !          1114: 
        !          1115:                /*
        !          1116:                 * If not the start of a packet, error 
        !          1117:                 */
        !          1118:                if (!(status & LN_RSTATE_STP)) {
        !          1119:                    if (se_verbose)
        !          1120:                            printf("se%d: Rring #%d, status=%x !STP\n",
        !          1121:                                   unit, index, status);
        !          1122:                        break;
        !          1123:                }
        !          1124:                /*
        !          1125:                 * See if packet is chained (should not) by looking at
        !          1126:                 * the last descriptor (OWN clear and ENP set).
        !          1127:                 * Remember the status info in this last descriptor. 
        !          1128:                 */
        !          1129:                ring_cnt = 1, status1 = status;
        !          1130:                while (((status1 & (LN_RSTATE_ERR | LN_RSTATE_OWN | LN_RSTATE_ENP)) == 0) &&
        !          1131:                       (ring_cnt++ <= NRCV)) {
        !          1132:                        struct se_desc  r1;
        !          1133:                        index = (index + 1) & (NRCV - 1);
        !          1134:                        (se_sw->desc_copyin) ((vm_offset_t)sc->lnrring[index],
        !          1135:                                              (vm_offset_t)&r1, sizeof(r1));
        !          1136:                        status1 = r1.status;
        !          1137:                }
        !          1138: 
        !          1139:                /*
        !          1140:                 * Chained packet (--> illegally sized!); re-init the
        !          1141:                 * descriptors involved and ignore this bogus packet.  I
        !          1142:                 * donno how, but it really happens that we get these
        !          1143:                 * monsters. 
        !          1144:                 */
        !          1145:                if (ring_cnt > 1) {
        !          1146:                        /*
        !          1147:                         * Return all descriptors to lance 
        !          1148:                         */
        !          1149:                        se_desc_set_status(sc->lnrring[first], LN_RSTATE_OWN);
        !          1150:                        while (first != index) {
        !          1151:                                first = (first + 1) & (NRCV - 1);
        !          1152:                                se_desc_set_status(sc->lnrring[first], LN_RSTATE_OWN);
        !          1153:                        }
        !          1154:                        if ((status1 & LN_RSTATE_ERR) && se_verbose)
        !          1155:                                printf("se%d: rcv error %x (chained)\n", unit, status1);
        !          1156:                        continue;
        !          1157:                }
        !          1158: 
        !          1159:                /*
        !          1160:                 * Good packets must be owned by us and have the end of
        !          1161:                 * packet flag.  And nothing else. 
        !          1162:                 */
        !          1163:                if ((status & ~LN_RSTATE_STP) == LN_RSTATE_ENP) {
        !          1164:                        sc->is_if.if_ipackets++;
        !          1165: 
        !          1166:                        if ((len = r.message_size) == 0)
        !          1167:                                /* race seen on pmaxen: the lance
        !          1168:                                 * has not updated the size yet ??
        !          1169:                                 */
        !          1170:                                goto read_descriptor;
        !          1171:                        /*
        !          1172:                         * Drop trailing CRC bytes from len and ship packet
        !          1173:                         * up 
        !          1174:                         */
        !          1175:                        se_read(sc, (volatile char*)sc->lnrbuf[first], len-4,0);
        !          1176: 
        !          1177:                        /*
        !          1178:                         * Return descriptor to lance, and move on to next
        !          1179:                         * packet 
        !          1180:                         */
        !          1181:                        r.status = LN_RSTATE_OWN;
        !          1182:                        (se_sw->desc_copyout)((vm_offset_t)&r,
        !          1183:                                              (vm_offset_t)sc->lnrring[first],
        !          1184:                                              sizeof(r));
        !          1185:                        continue;
        !          1186:                }
        !          1187:                /*
        !          1188:                 * Not a good packet, see what is wrong 
        !          1189:                 */
        !          1190:                if (status & LN_RSTATE_ERR) {
        !          1191:                        sc->is_if.if_ierrors++;
        !          1192: 
        !          1193:                        if (se_verbose)
        !          1194:                                printf("se%d: rcv error (x%x)\n", unit, status);
        !          1195: 
        !          1196:                        /*
        !          1197:                         * Return descriptor to lance 
        !          1198:                         */
        !          1199:                        se_desc_set_status(sc->lnrring[first], LN_RSTATE_OWN);
        !          1200:                } else {
        !          1201:                        /*
        !          1202:                         * Race condition viz lance, Wait for the next
        !          1203:                         * interrupt. 
        !          1204:                         */
        !          1205:                        return;
        !          1206:                }
        !          1207:        }
        !          1208: }
        !          1209: 
        !          1210: /*
        !          1211:  * Output routine.
        !          1212:  * Call common function for wiring memory,
        !          1213:  * come back later (to se_start) to get
        !          1214:  * things going.
        !          1215:  */
        !          1216: io_return_t
        !          1217: se_output(
        !          1218:        int             dev,
        !          1219:        io_req_t        ior)
        !          1220: {
        !          1221:     return net_write(&se_softc[dev]->is_if, (int(*)())se_start, ior);
        !          1222: }
        !          1223:  
        !          1224: /*
        !          1225:  * Start output on interface.
        !          1226:  *
        !          1227:  */
        !          1228: void
        !          1229: se_start(int   unit)
        !          1230: {
        !          1231:        register se_softc_t sc = se_softc[unit];
        !          1232:        io_req_t        request;
        !          1233:        struct se_desc  r;
        !          1234:        int             tlen;
        !          1235:        spl_t           s;
        !          1236:        register int    index;
        !          1237: 
        !          1238:        s = splimp();
        !          1239: 
        !          1240:        for (index = sc->xmt_last;
        !          1241:             sc->xmt_count < (NXMT - 1);
        !          1242:             sc->xmt_last = index = (index + 1) & (NXMT - 1)) {
        !          1243:                /*
        !          1244:                 * Dequeue the next transmit request, if any. 
        !          1245:                 */
        !          1246:                IF_DEQUEUE(&sc->is_if.if_snd, request);
        !          1247:                if (request == 0) {
        !          1248:                        /*
        !          1249:                         * Tell the lance to send the packet now
        !          1250:                         * instead of waiting until the next 1.6 ms
        !          1251:                         * poll interval expires.
        !          1252:                         */
        !          1253:                        *sc->lnregs = LN_CSR0_TDMD | LN_CSR0_INEA;
        !          1254:                        splx(s);
        !          1255:                        return; /* Nothing on the queue  */
        !          1256:                }
        !          1257: 
        !          1258:                /*
        !          1259:                 * Keep request around until transmission complete
        !          1260:                 */
        !          1261:                sc->tpkt[index] = request;
        !          1262:                tlen = copy_to_lance(request, sc->lntbuf[index]);
        !          1263: 
        !          1264:                /*
        !          1265:                 * Give away buffer.  Must copyin/out, set len,
        !          1266:                 * and set the OWN flag.  We do not do chaining.
        !          1267:                 */
        !          1268:                (se_sw->desc_copyin)((vm_offset_t)sc->lntring[index],
        !          1269:                                     (vm_offset_t)&r, sizeof(r));
        !          1270:                r.buffer_size = -(tlen) | 0xf000;
        !          1271:                r.status = (LN_TSTATE_OWN | LN_TSTATE_STP | LN_TSTATE_ENP);
        !          1272:                (se_sw->desc_copyout)((vm_offset_t)&r,
        !          1273:                                      (vm_offset_t)sc->lntring[index],
        !          1274:                                      sizeof(r));
        !          1275:                wbflush();
        !          1276: 
        !          1277:                sc->xmt_count++;
        !          1278:        }
        !          1279:        /*
        !          1280:         * Since we actually have queued new packets, tell
        !          1281:         * the chip to rescan the descriptors _now_.
        !          1282:         * It is quite unlikely that the ring be filled,
        !          1283:         * but if it is .. the more reason to do it!
        !          1284:         */
        !          1285:        *sc->lnregs = LN_CSR0_TDMD | LN_CSR0_INEA;
        !          1286:        splx(s);
        !          1287: }
        !          1288: 
        !          1289: 
        !          1290: /*
        !          1291:  * Pull a packet off the interface and
        !          1292:  * hand it up to the higher levels.
        !          1293:  *
        !          1294:  * Simulate broadcast packets in software.
        !          1295:  */
        !          1296: void
        !          1297: se_read(
        !          1298:        register se_softc_t      sc,
        !          1299:        volatile char           *lnrbuf,
        !          1300:        int                      len,
        !          1301:        io_req_t                 loop_back)
        !          1302: {
        !          1303:        register struct ifnet *ifp = &sc->is_if;
        !          1304:        register ipc_kmsg_t     new_kmsg;
        !          1305:        char                    *hdr, *pkt;
        !          1306: 
        !          1307:        if (len <= sizeof(struct ether_header))
        !          1308:                return; /* sanity */
        !          1309: 
        !          1310:        /*
        !          1311:         * Get a new kmsg to put data into.
        !          1312:         */
        !          1313:        new_kmsg = net_kmsg_get();
        !          1314:        if (new_kmsg == IKM_NULL) {
        !          1315:            /*
        !          1316:             * No room, drop the packet
        !          1317:             */
        !          1318:            ifp->if_rcvdrops++;
        !          1319:            return;
        !          1320:        }
        !          1321: 
        !          1322:        hdr = net_kmsg(new_kmsg)->header;
        !          1323:        pkt = net_kmsg(new_kmsg)->packet;
        !          1324: 
        !          1325: #define OFF0 (sizeof(struct ether_header) - sizeof(struct packet_header))
        !          1326: #define OFF1 (OFF0 & ~3)
        !          1327:        if (loop_back) {
        !          1328:                bcopy(loop_back->io_data, hdr, sizeof(struct ether_header));
        !          1329:                bcopy(loop_back->io_data + OFF0,
        !          1330:                        pkt, len - OFF0);
        !          1331:        } else
        !          1332:                copy_from_lance(lnrbuf, len, (struct ether_header*)hdr,
        !          1333:                         (struct packet_header*)pkt);
        !          1334: 
        !          1335:        /*
        !          1336:         * Set up the 'fake' header with length.  Type has been left
        !          1337:         * in the correct place.
        !          1338:         */
        !          1339:        len = len - OFF0;
        !          1340:        ((struct packet_header *)pkt)->length = len;
        !          1341: 
        !          1342:        /*
        !          1343:         * Hand the packet to the network module.
        !          1344:         */
        !          1345:        net_packet(ifp, new_kmsg, len, ethernet_priority(new_kmsg));
        !          1346: }
        !          1347: 
        !          1348: 
        !          1349: /*
        !          1350:  * Get a packet out of Lance memory and into main memory.
        !          1351:  */
        !          1352: private void
        !          1353: copy_from_lance(
        !          1354:        register volatile unsigned char *rbuf,
        !          1355:        register unsigned int     nbytes,
        !          1356:        struct ether_header      *hdr,
        !          1357:        struct packet_header     *pkt)
        !          1358: {
        !          1359:        /*
        !          1360:         * Read in ethernet header 
        !          1361:         */
        !          1362:        (se_sw->data_copyin) ((vm_offset_t)rbuf, (vm_offset_t)hdr, sizeof(struct ether_header));
        !          1363: 
        !          1364:        nbytes -= sizeof(struct ether_header);
        !          1365:        rbuf += (se_sw->mapoffs) (sizeof(struct ether_header));
        !          1366: 
        !          1367:        pkt->type = (unsigned short) hdr->ether_type;
        !          1368: 
        !          1369:        (se_sw->data_copyin) ((vm_offset_t)rbuf, (vm_offset_t)(pkt + 1), nbytes);
        !          1370: }
        !          1371: 
        !          1372: 
        !          1373: /*
        !          1374:  * Move a packet into Lance space
        !          1375:  */
        !          1376: private int
        !          1377: copy_to_lance(
        !          1378:        register io_req_t request,
        !          1379:        volatile char    *sbuf)
        !          1380: {
        !          1381:        register unsigned short *dp;
        !          1382:        register int    len;
        !          1383: 
        !          1384:        dp = (unsigned short *) request->io_data;
        !          1385:        len = request->io_count;
        !          1386: 
        !          1387:        if (len > (int)(ETHERMTU + sizeof(struct ether_header))) {
        !          1388:                printf("se: truncating HUGE packet\n");
        !          1389:                len = ETHERMTU + sizeof(struct ether_header);
        !          1390:        }
        !          1391: 
        !          1392:        (se_sw->data_copyout) ((vm_offset_t)dp, (vm_offset_t)sbuf, len);
        !          1393: 
        !          1394:        if (len < LN_MINBUF_NOCH)
        !          1395:                /*
        !          1396:                 * The lance needs at least this much data in a packet. Who
        !          1397:                 * cares if I send some garbage that was left in the lance
        !          1398:                 * buffer ?  If one can spoof packets then one can spoof
        !          1399:                 * packets!
        !          1400:                 */
        !          1401:                len = LN_MINBUF_NOCH;
        !          1402:        return len;
        !          1403: }
        !          1404: 
        !          1405: /*
        !          1406:  * Reset a descriptor's flags.
        !          1407:  * Optionally give the descriptor to the lance
        !          1408:  */
        !          1409: private void
        !          1410: se_desc_set_status (
        !          1411:        register se_desc_t      lndesc,
        !          1412:        int                     val)
        !          1413: {
        !          1414:        struct se_desc          desc;
        !          1415: 
        !          1416:        (se_sw->desc_copyin) ((vm_offset_t)lndesc, (vm_offset_t)&desc, sizeof(desc));
        !          1417:        desc.desc4.bits = 0;
        !          1418:        desc.status     = val;
        !          1419:        (se_sw->desc_copyout) ((vm_offset_t)&desc, (vm_offset_t)lndesc, sizeof(desc));
        !          1420:        wbflush();
        !          1421: }
        !          1422: 
        !          1423: /*
        !          1424:  * Set/Get status functions
        !          1425:  */
        !          1426: int
        !          1427: se_get_status(
        !          1428:        int              dev,
        !          1429:        dev_flavor_t     flavor,
        !          1430:        dev_status_t     status,        /* pointer to OUT array */
        !          1431:        natural_t       *status_count)  /* out */
        !          1432: {
        !          1433:        return (net_getstat(&se_softc[dev]->is_if,
        !          1434:                            flavor, status, status_count));
        !          1435: }
        !          1436: 
        !          1437: int
        !          1438: se_set_status(
        !          1439:        int             unit,
        !          1440:        dev_flavor_t    flavor,
        !          1441:        dev_status_t    status,
        !          1442:        natural_t       status_count)
        !          1443: {
        !          1444:        register se_softc_t     sc;
        !          1445: 
        !          1446:        sc = se_softc[unit];
        !          1447: 
        !          1448: 
        !          1449:        switch (flavor) {
        !          1450: 
        !          1451:          case NET_STATUS:
        !          1452:                break;
        !          1453: 
        !          1454:          case NET_ADDRESS: {
        !          1455: 
        !          1456:                register union ether_cvt {
        !          1457:                    unsigned char addr[6];
        !          1458:                    int  lwd[2];
        !          1459:                } *ec = (union ether_cvt *) status;
        !          1460: 
        !          1461:                if (status_count < sizeof(*ec) / sizeof(int))
        !          1462:                    return (D_INVALID_SIZE);
        !          1463: 
        !          1464:                ec->lwd[0] = ntohl(ec->lwd[0]);
        !          1465:                ec->lwd[1] = ntohl(ec->lwd[1]);
        !          1466: 
        !          1467:                se_setaddr(ec->addr, unit);
        !          1468: 
        !          1469:                break;
        !          1470:          }
        !          1471: 
        !          1472:          default:
        !          1473:                return (D_INVALID_OPERATION);
        !          1474:        }
        !          1475: 
        !          1476:        return (D_SUCCESS);
        !          1477: }
        !          1478: 
        !          1479: 
        !          1480: /*
        !          1481:  * Install new filter.
        !          1482:  * Nothing special needs to be done here.
        !          1483:  */
        !          1484: io_return_t
        !          1485: se_setinput(
        !          1486:        int             dev,
        !          1487:        ipc_port_t      receive_port,
        !          1488:        int             priority,
        !          1489:        filter_t        *filter,
        !          1490:        natural_t       filter_count)
        !          1491: {
        !          1492:        return (net_set_filter(&se_softc[dev]->is_if,
        !          1493:                               receive_port, priority,
        !          1494:                               filter, filter_count));
        !          1495: }
        !          1496: 
        !          1497: /*
        !          1498:  * Allocate and initialize a ring descriptor.
        !          1499:  * Allocates a buffer from the lance memory and writes a descriptor
        !          1500:  * for that buffer to the host virtual address LNDESC.
        !          1501:  */
        !          1502: private volatile long
        !          1503: *se_desc_alloc (
        !          1504:        register se_softc_t     sc,
        !          1505:        register se_desc_t      lndesc)
        !          1506: {
        !          1507:        register vm_offset_t    dp;     /* data pointer */
        !          1508:        struct se_desc          desc;
        !          1509: 
        !          1510:        /*
        !          1511:         * Allocate buffer in lance space 
        !          1512:         */
        !          1513:        dp = se_malloc(sc, LN_BUFFER_SIZE);
        !          1514: 
        !          1515:        /*
        !          1516:         * Build a descriptor pointing to it 
        !          1517:         */
        !          1518:        desc.addr_low = Addr_lo(Lmem(dp));
        !          1519:        desc.addr_hi  = Addr_hi(Lmem(dp));
        !          1520:        desc.status   = 0;
        !          1521:        desc.buffer_size = -LN_BUFFER_SIZE;
        !          1522:        desc.desc4.bits  = 0;
        !          1523: 
        !          1524:        /*
        !          1525:         * Copy the descriptor to lance space 
        !          1526:         */
        !          1527:        (se_sw->desc_copyout) ((vm_offset_t)&desc, (vm_offset_t)lndesc, sizeof(desc));
        !          1528:        wbflush();
        !          1529: 
        !          1530:        return (volatile long *) Hmem(dp);
        !          1531: }
        !          1532: 
        !          1533: /*
        !          1534:  * Allocate a chunk of lance RAM buffer. Since we never
        !          1535:  * give lance RAM buffer memory back, we'll just step up the
        !          1536:  * byte-count on a per-unit basis.
        !          1537:  *
        !          1538:  * The return value is an index into the lance memory, which can be
        !          1539:  * passed with Hmem() and Lmem() to get the host and chip virtual addresses.
        !          1540:  */
        !          1541: private vm_offset_t
        !          1542: se_malloc(
        !          1543:        se_softc_t      sc,
        !          1544:        int             size)
        !          1545: {
        !          1546:        register vm_offset_t    ret;
        !          1547: 
        !          1548:        /*
        !          1549:         * On first call, zero lance memory 
        !          1550:         */
        !          1551:        if (sc->lnsbrk == 0)
        !          1552:                (se_sw->bzero) (Hmem(0), LN_MEMORY_SIZE);
        !          1553: 
        !          1554:        /*
        !          1555:         * Start out on the first double longword boundary
        !          1556:         * (this accomodates some machines, with minimal loss)
        !          1557:         */
        !          1558:        if (sc->lnsbrk & 0xf)
        !          1559:                sc->lnsbrk = (sc->lnsbrk + 0x10) & ~0xf;
        !          1560: 
        !          1561:        ret = sc->lnsbrk;
        !          1562:        sc->lnsbrk += size;
        !          1563: 
        !          1564:        if (sc->lnsbrk > LN_MEMORY_SIZE)
        !          1565:                panic("se_malloc");
        !          1566: 
        !          1567:        return ret;
        !          1568: }
        !          1569: 
        !          1570: #endif     NLN > 0

unix.superglobalmegacorp.com

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