The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/chips/lance.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: a6d447fb7a59116d4afd126abafb9521


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.