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/dev/qbus/if_de.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 /*      $NetBSD: if_de.c,v 1.16 2005/02/26 12:45:06 simonb Exp $        */
    2 
    3 /*
    4  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
    5  * All rights reserved.
    6  *
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  *      @(#)if_de.c     7.12 (Berkeley) 12/16/90
   33  */
   34 
   35 /*
   36  * Copyright (c) 2000 Ludd, University of Lule}, Sweden.
   37  * All rights reserved.
   38  *
   39  *
   40  * Redistribution and use in source and binary forms, with or without
   41  * modification, are permitted provided that the following conditions
   42  * are met:
   43  * 1. Redistributions of source code must retain the above copyright
   44  *    notice, this list of conditions and the following disclaimer.
   45  * 2. Redistributions in binary form must reproduce the above copyright
   46  *    notice, this list of conditions and the following disclaimer in the
   47  *    documentation and/or other materials provided with the distribution.
   48  * 3. All advertising materials mentioning features or use of this software
   49  *    must display the following acknowledgement:
   50  *      This product includes software developed by the University of
   51  *      California, Berkeley and its contributors.
   52  * 4. Neither the name of the University nor the names of its contributors
   53  *    may be used to endorse or promote products derived from this software
   54  *    without specific prior written permission.
   55  *
   56  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   57  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   58  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   59  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   60  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   61  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   62  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   64  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   65  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   66  * SUCH DAMAGE.
   67  *
   68  *      @(#)if_de.c     7.12 (Berkeley) 12/16/90
   69  */
   70 
   71 /*
   72  * DEC DEUNA interface
   73  *
   74  *      Lou Salkind
   75  *      New York University
   76  *
   77  *      Rewritten by Ragge 30 April 2000 to match new world.
   78  *
   79  * TODO:
   80  *      timeout routine (get statistics)
   81  */
   82 
   83 #include <sys/cdefs.h>
   84 __KERNEL_RCSID(0, "$NetBSD: if_de.c,v 1.16 2005/02/26 12:45:06 simonb Exp $");
   85 
   86 #include "opt_inet.h"
   87 #include "bpfilter.h"
   88 
   89 #include <sys/param.h>
   90 #include <sys/systm.h>
   91 #include <sys/mbuf.h>
   92 #include <sys/buf.h>
   93 #include <sys/protosw.h>
   94 #include <sys/socket.h>
   95 #include <sys/ioctl.h>
   96 #include <sys/errno.h>
   97 #include <sys/syslog.h>
   98 #include <sys/device.h>
   99 
  100 #include <net/if.h>
  101 #include <net/if_ether.h>
  102 #include <net/if_dl.h>
  103 
  104 #ifdef INET
  105 #include <netinet/in.h>
  106 #include <netinet/if_inarp.h>
  107 #endif
  108 
  109 #if NBPFILTER > 0
  110 #include <net/bpf.h>
  111 #include <net/bpfdesc.h>
  112 #endif
  113 
  114 #include <machine/bus.h>
  115 
  116 #include <dev/qbus/ubavar.h>
  117 #include <dev/qbus/if_dereg.h>
  118 #include <dev/qbus/if_uba.h>
  119 
  120 #include "ioconf.h"
  121 
  122 /*
  123  * Be careful with transmit/receive buffers, each entry steals 4 map
  124  * registers, and there is only 496 on one unibus...
  125  */
  126 #define NRCV    7       /* number of receive buffers (must be > 1) */
  127 #define NXMT    3       /* number of transmit buffers */
  128 
  129 /*
  130  * Structure containing the elements that must be in DMA-safe memory.
  131  */
  132 struct  de_cdata {
  133         /* the following structures are always mapped in */
  134         struct  de_pcbb dc_pcbb;        /* port control block */
  135         struct  de_ring dc_xrent[NXMT]; /* transmit ring entrys */
  136         struct  de_ring dc_rrent[NRCV]; /* receive ring entrys */
  137         struct  de_udbbuf dc_udbbuf;    /* UNIBUS data buffer */
  138         /* end mapped area */
  139 };
  140 
  141 /*
  142  * Ethernet software status per interface.
  143  *
  144  * Each interface is referenced by a network interface structure,
  145  * ds_if, which the routing code uses to locate the interface.
  146  * This structure contains the output queue for the interface, its address, ...
  147  * We also have, for each interface, a UBA interface structure, which
  148  * contains information about the UNIBUS resources held by the interface:
  149  * map registers, buffered data paths, etc.  Information is cached in this
  150  * structure for use by the if_uba.c routines in running the interface
  151  * efficiently.
  152  */
  153 struct  de_softc {
  154         struct  device sc_dev;          /* Configuration common part */
  155         struct  evcnt sc_intrcnt;       /* Interrupt counting */
  156         struct  ethercom sc_ec;         /* Ethernet common part */
  157 #define sc_if   sc_ec.ec_if             /* network-visible interface */
  158         bus_space_tag_t sc_iot;
  159         bus_addr_t sc_ioh;
  160         bus_dma_tag_t sc_dmat;
  161         int     sc_flags;
  162 #define DSF_MAPPED      1
  163         struct ubinfo sc_ui;
  164         struct de_cdata *sc_dedata;     /* Control structure */
  165         struct de_cdata *sc_pdedata;    /* Bus-mapped control structure */
  166         struct  ifubinfo sc_ifuba;      /* UNIBUS resources */
  167         struct  ifrw sc_ifr[NRCV];      /* UNIBUS receive buffer maps */
  168         struct  ifxmt sc_ifw[NXMT];     /* UNIBUS receive buffer maps */
  169 
  170         int     sc_xindex;              /* UNA index into transmit chain */
  171         int     sc_rindex;              /* UNA index into receive chain */
  172         int     sc_xfree;               /* index for next transmit buffer */
  173         int     sc_nxmit;               /* # of transmits in progress */
  174         void *sc_sh;                    /* shutdownhook cookie */
  175 };
  176 
  177 static  int dematch(struct device *, struct cfdata *, void *);
  178 static  void deattach(struct device *, struct device *, void *);
  179 static  void dewait(struct de_softc *, char *);
  180 static  int deinit(struct ifnet *);
  181 static  int deioctl(struct ifnet *, u_long, caddr_t);
  182 static  void dereset(struct device *);
  183 static  void destop(struct ifnet *, int);
  184 static  void destart(struct ifnet *);
  185 static  void derecv(struct de_softc *);
  186 static  void deintr(void *);
  187 static  void deshutdown(void *);
  188 
  189 CFATTACH_DECL(de, sizeof(struct de_softc),
  190     dematch, deattach, NULL, NULL);
  191 
  192 #define DE_WCSR(csr, val) \
  193         bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val)
  194 #define DE_WLOW(val) \
  195         bus_space_write_1(sc->sc_iot, sc->sc_ioh, DE_PCSR0, val)
  196 #define DE_WHIGH(val) \
  197         bus_space_write_1(sc->sc_iot, sc->sc_ioh, DE_PCSR0 + 1, val)
  198 #define DE_RCSR(csr) \
  199         bus_space_read_2(sc->sc_iot, sc->sc_ioh, csr)
  200 
  201 #define LOWORD(x)       ((int)(x) & 0xffff)
  202 #define HIWORD(x)       (((int)(x) >> 16) & 0x3)
  203 /*
  204  * Interface exists: make available by filling in network interface
  205  * record.  System will initialize the interface when it is ready
  206  * to accept packets.  We get the ethernet address here.
  207  */
  208 void
  209 deattach(struct device *parent, struct device *self, void *aux)
  210 {
  211         struct uba_attach_args *ua = aux;
  212         struct de_softc *sc = (struct de_softc *)self;
  213         struct ifnet *ifp = &sc->sc_if;
  214         u_int8_t myaddr[ETHER_ADDR_LEN];
  215         int csr1, error;
  216         char *c;
  217 
  218         sc->sc_iot = ua->ua_iot;
  219         sc->sc_ioh = ua->ua_ioh;
  220         sc->sc_dmat = ua->ua_dmat;
  221 
  222         /*
  223          * What kind of a board is this?
  224          * The error bits 4-6 in pcsr1 are a device id as long as
  225          * the high byte is zero.
  226          */
  227         csr1 = DE_RCSR(DE_PCSR1);
  228         if (csr1 & 0xff60)
  229                 c = "broken";
  230         else if (csr1 & 0x10)
  231                 c = "delua";
  232         else
  233                 c = "deuna";
  234 
  235         /*
  236          * Reset the board and temporarily map
  237          * the pcbb buffer onto the Unibus.
  238          */
  239         DE_WCSR(DE_PCSR0, 0);           /* reset INTE */
  240         DELAY(100);
  241         DE_WCSR(DE_PCSR0, PCSR0_RSET);
  242         dewait(sc, "reset");
  243 
  244         sc->sc_ui.ui_size = sizeof(struct de_cdata);
  245         if ((error = ubmemalloc((struct uba_softc *)parent, &sc->sc_ui, 0)))
  246                 return printf(": failed ubmemalloc(), error = %d\n", error);
  247         sc->sc_dedata = (struct de_cdata *)sc->sc_ui.ui_vaddr;
  248 
  249         /*
  250          * Tell the DEUNA about our PCB
  251          */
  252         DE_WCSR(DE_PCSR2, LOWORD(sc->sc_ui.ui_baddr));
  253         DE_WCSR(DE_PCSR3, HIWORD(sc->sc_ui.ui_baddr));
  254         DE_WLOW(CMD_GETPCBB);
  255         dewait(sc, "pcbb");
  256 
  257         sc->sc_dedata->dc_pcbb.pcbb0 = FC_RDPHYAD;
  258         DE_WLOW(CMD_GETCMD);
  259         dewait(sc, "read addr ");
  260 
  261         bcopy((caddr_t)&sc->sc_dedata->dc_pcbb.pcbb2, myaddr, sizeof (myaddr));
  262         printf("\n%s: %s, hardware address %s\n", sc->sc_dev.dv_xname, c,
  263                 ether_sprintf(myaddr));
  264 
  265         uba_intr_establish(ua->ua_icookie, ua->ua_cvec, deintr, sc,
  266             &sc->sc_intrcnt);
  267         uba_reset_establish(dereset, &sc->sc_dev);
  268         evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  269             sc->sc_dev.dv_xname, "intr");
  270 
  271         strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
  272         ifp->if_softc = sc;
  273         ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI;
  274         ifp->if_ioctl = deioctl;
  275         ifp->if_start = destart;
  276         ifp->if_init = deinit;
  277         ifp->if_stop = destop;
  278         IFQ_SET_READY(&ifp->if_snd);
  279 
  280         if_attach(ifp);
  281         ether_ifattach(ifp, myaddr);
  282         ubmemfree((struct uba_softc *)parent, &sc->sc_ui);
  283 
  284         sc->sc_sh = shutdownhook_establish(deshutdown, sc);
  285 }
  286 
  287 void
  288 destop(struct ifnet *ifp, int a)
  289 {
  290         struct de_softc *sc = ifp->if_softc;
  291 
  292         DE_WLOW(0);
  293         DELAY(5000);
  294         DE_WLOW(PCSR0_RSET);
  295 }
  296 
  297 
  298 /*
  299  * Reset of interface after UNIBUS reset.
  300  */
  301 void
  302 dereset(struct device *dev)
  303 {
  304         struct de_softc *sc = (void *)dev;
  305 
  306         sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
  307         sc->sc_flags &= ~DSF_MAPPED;
  308         sc->sc_pdedata = NULL;  /* All mappings lost */
  309         DE_WCSR(DE_PCSR0, PCSR0_RSET);
  310         dewait(sc, "reset");
  311         deinit(&sc->sc_if);
  312 }
  313 
  314 /*
  315  * Initialization of interface; clear recorded pending
  316  * operations, and reinitialize UNIBUS usage.
  317  */
  318 int
  319 deinit(struct ifnet *ifp)
  320 {
  321         struct de_softc *sc = ifp->if_softc;
  322         struct de_cdata *dc, *pdc;
  323         struct ifrw *ifrw;
  324         struct ifxmt *ifxp;
  325         struct de_ring *rp;
  326         int s, error;
  327 
  328         if (ifp->if_flags & IFF_RUNNING)
  329                 return 0;
  330         if ((sc->sc_flags & DSF_MAPPED) == 0) {
  331                 if (if_ubaminit(&sc->sc_ifuba, (void *)sc->sc_dev.dv_parent,
  332                     MCLBYTES, sc->sc_ifr, NRCV, sc->sc_ifw, NXMT)) {
  333                         printf("%s: can't initialize\n", sc->sc_dev.dv_xname);
  334                         ifp->if_flags &= ~IFF_UP;
  335                         return 0;
  336                 }
  337                 sc->sc_ui.ui_size = sizeof(struct de_cdata);
  338                 if ((error = ubmemalloc((void *)sc->sc_dev.dv_parent,
  339                     &sc->sc_ui, 0))) {
  340                         printf(": unable to ubmemalloc(), error = %d\n", error);
  341                         return 0;
  342                 }
  343                 sc->sc_pdedata = (struct de_cdata *)sc->sc_ui.ui_baddr;
  344                 sc->sc_dedata = (struct de_cdata *)sc->sc_ui.ui_vaddr;
  345                 sc->sc_flags |= DSF_MAPPED;
  346         }
  347 
  348         /*
  349          * Tell the DEUNA about our PCB
  350          */
  351         DE_WCSR(DE_PCSR2, LOWORD(sc->sc_pdedata));
  352         DE_WCSR(DE_PCSR3, HIWORD(sc->sc_pdedata));
  353         DE_WLOW(0);             /* reset INTE */
  354         DELAY(500);
  355         DE_WLOW(CMD_GETPCBB);
  356         dewait(sc, "pcbb");
  357 
  358         dc = sc->sc_dedata;
  359         pdc = sc->sc_pdedata;
  360         /* set the transmit and receive ring header addresses */
  361         dc->dc_pcbb.pcbb0 = FC_WTRING;
  362         dc->dc_pcbb.pcbb2 = LOWORD(&pdc->dc_udbbuf);
  363         dc->dc_pcbb.pcbb4 = HIWORD(&pdc->dc_udbbuf);
  364 
  365         dc->dc_udbbuf.b_tdrbl = LOWORD(&pdc->dc_xrent[0]);
  366         dc->dc_udbbuf.b_tdrbh = HIWORD(&pdc->dc_xrent[0]);
  367         dc->dc_udbbuf.b_telen = sizeof (struct de_ring) / sizeof(u_int16_t);
  368         dc->dc_udbbuf.b_trlen = NXMT;
  369         dc->dc_udbbuf.b_rdrbl = LOWORD(&pdc->dc_rrent[0]);
  370         dc->dc_udbbuf.b_rdrbh = HIWORD(&pdc->dc_rrent[0]);
  371         dc->dc_udbbuf.b_relen = sizeof (struct de_ring) / sizeof(u_int16_t);
  372         dc->dc_udbbuf.b_rrlen = NRCV;
  373 
  374         DE_WLOW(CMD_GETCMD);
  375         dewait(sc, "wtring");
  376 
  377         sc->sc_dedata->dc_pcbb.pcbb0 = FC_WTMODE;
  378         sc->sc_dedata->dc_pcbb.pcbb2 = MOD_TPAD|MOD_HDX|MOD_DRDC|MOD_ENAL;
  379         DE_WLOW(CMD_GETCMD);
  380         dewait(sc, "wtmode");
  381 
  382         /* set up the receive and transmit ring entries */
  383         ifxp = &sc->sc_ifw[0];
  384         for (rp = &dc->dc_xrent[0]; rp < &dc->dc_xrent[NXMT]; rp++) {
  385                 rp->r_segbl = LOWORD(ifxp->ifw_info);
  386                 rp->r_segbh = HIWORD(ifxp->ifw_info);
  387                 rp->r_flags = 0;
  388                 ifxp++;
  389         }
  390         ifrw = &sc->sc_ifr[0];
  391         for (rp = &dc->dc_rrent[0]; rp < &dc->dc_rrent[NRCV]; rp++) {
  392                 rp->r_slen = MCLBYTES - 2;
  393                 rp->r_segbl = LOWORD(ifrw->ifrw_info);
  394                 rp->r_segbh = HIWORD(ifrw->ifrw_info);
  395                 rp->r_flags = RFLG_OWN;
  396                 ifrw++;
  397         }
  398 
  399         /* start up the board (rah rah) */
  400         s = splnet();
  401         sc->sc_rindex = sc->sc_xindex = sc->sc_xfree = sc->sc_nxmit = 0;
  402         sc->sc_if.if_flags |= IFF_RUNNING;
  403         DE_WLOW(PCSR0_INTE);                    /* avoid interlock */
  404         destart(&sc->sc_if);            /* queue output packets */
  405         DE_WLOW(CMD_START|PCSR0_INTE);
  406         splx(s);
  407         return 0;
  408 }
  409 
  410 /*
  411  * Setup output on interface.
  412  * Get another datagram to send off of the interface queue,
  413  * and map it to the interface before starting the output.
  414  * Must be called from ipl >= our interrupt level.
  415  */
  416 void
  417 destart(struct ifnet *ifp)
  418 {
  419         struct de_softc *sc = ifp->if_softc;
  420         struct de_cdata *dc;
  421         struct de_ring *rp;
  422         struct mbuf *m;
  423         int nxmit, len;
  424 
  425         /*
  426          * the following test is necessary, since
  427          * the code is not reentrant and we have
  428          * multiple transmission buffers.
  429          */
  430         if (sc->sc_if.if_flags & IFF_OACTIVE)
  431                 return;
  432         dc = sc->sc_dedata;
  433         for (nxmit = sc->sc_nxmit; nxmit < NXMT; nxmit++) {
  434                 IFQ_DEQUEUE(&ifp->if_snd, m);
  435                 if (m == 0)
  436                         break;
  437 
  438                 rp = &dc->dc_xrent[sc->sc_xfree];
  439                 if (rp->r_flags & XFLG_OWN)
  440                         panic("deuna xmit in progress");
  441 #if NBPFILTER > 0
  442                 if (ifp->if_bpf)
  443                         bpf_mtap(ifp->if_bpf, m);
  444 #endif
  445 
  446                 len = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[sc->sc_xfree], m);
  447                 rp->r_slen = len;
  448                 rp->r_tdrerr = 0;
  449                 rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
  450 
  451                 sc->sc_xfree++;
  452                 if (sc->sc_xfree == NXMT)
  453                         sc->sc_xfree = 0;
  454         }
  455         if (sc->sc_nxmit != nxmit) {
  456                 sc->sc_nxmit = nxmit;
  457                 if (ifp->if_flags & IFF_RUNNING)
  458                         DE_WLOW(PCSR0_INTE|CMD_PDMD);
  459         }
  460 }
  461 
  462 /*
  463  * Command done interrupt.
  464  */
  465 void
  466 deintr(void *arg)
  467 {
  468         struct ifxmt *ifxp;
  469         struct de_cdata *dc;
  470         struct de_softc *sc = arg;
  471         struct de_ring *rp;
  472         short csr0;
  473 
  474         /* save flags right away - clear out interrupt bits */
  475         csr0 = DE_RCSR(DE_PCSR0);
  476         DE_WHIGH(csr0 >> 8);
  477 
  478 
  479         sc->sc_if.if_flags |= IFF_OACTIVE;      /* prevent entering destart */
  480         /*
  481          * if receive, put receive buffer on mbuf
  482          * and hang the request again
  483          */
  484         derecv(sc);
  485 
  486         /*
  487          * Poll transmit ring and check status.
  488          * Be careful about loopback requests.
  489          * Then free buffer space and check for
  490          * more transmit requests.
  491          */
  492         dc = sc->sc_dedata;
  493         for ( ; sc->sc_nxmit > 0; sc->sc_nxmit--) {
  494                 rp = &dc->dc_xrent[sc->sc_xindex];
  495                 if (rp->r_flags & XFLG_OWN)
  496                         break;
  497 
  498                 sc->sc_if.if_opackets++;
  499                 ifxp = &sc->sc_ifw[sc->sc_xindex];
  500                 /* check for unusual conditions */
  501                 if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
  502                         if (rp->r_flags & XFLG_ERRS) {
  503                                 /* output error */
  504                                 sc->sc_if.if_oerrors++;
  505                         } else if (rp->r_flags & XFLG_ONE) {
  506                                 /* one collision */
  507                                 sc->sc_if.if_collisions++;
  508                         } else if (rp->r_flags & XFLG_MORE) {
  509                                 /* more than one collision */
  510                                 sc->sc_if.if_collisions += 2;   /* guess */
  511                         }
  512                 }
  513                 if_ubaend(&sc->sc_ifuba, ifxp);
  514                 /* check if next transmit buffer also finished */
  515                 sc->sc_xindex++;
  516                 if (sc->sc_xindex == NXMT)
  517                         sc->sc_xindex = 0;
  518         }
  519         sc->sc_if.if_flags &= ~IFF_OACTIVE;
  520         destart(&sc->sc_if);
  521 
  522         if (csr0 & PCSR0_RCBI) {
  523                 DE_WLOW(PCSR0_INTE|CMD_PDMD);
  524         }
  525 }
  526 
  527 /*
  528  * Ethernet interface receiver interface.
  529  * If input error just drop packet.
  530  * Otherwise purge input buffered data path and examine
  531  * packet to determine type.  If can't determine length
  532  * from type, then have to drop packet.  Othewise decapsulate
  533  * packet based on type and pass to type specific higher-level
  534  * input routine.
  535  */
  536 void
  537 derecv(struct de_softc *sc)
  538 {
  539         struct ifnet *ifp = &sc->sc_if;
  540         struct de_ring *rp;
  541         struct de_cdata *dc;
  542         struct mbuf *m;
  543         int len;
  544 
  545         dc = sc->sc_dedata;
  546         rp = &dc->dc_rrent[sc->sc_rindex];
  547         while ((rp->r_flags & RFLG_OWN) == 0) {
  548                 sc->sc_if.if_ipackets++;
  549                 len = (rp->r_lenerr&RERR_MLEN) - ETHER_CRC_LEN;
  550                 /* check for errors */
  551                 if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) ||
  552                     (rp->r_lenerr & (RERR_BUFL|RERR_UBTO))) {
  553                         sc->sc_if.if_ierrors++;
  554                         goto next;
  555                 }
  556                 m = if_ubaget(&sc->sc_ifuba, &sc->sc_ifr[sc->sc_rindex],
  557                     ifp, len);
  558                 if (m == 0) {
  559                         sc->sc_if.if_ierrors++;
  560                         goto next;
  561                 }
  562 #if NBPFILTER > 0
  563                 if (ifp->if_bpf)
  564                         bpf_mtap(ifp->if_bpf, m);
  565 #endif
  566 
  567                 (*ifp->if_input)(ifp, m);
  568 
  569                 /* hang the receive buffer again */
  570 next:           rp->r_lenerr = 0;
  571                 rp->r_flags = RFLG_OWN;
  572 
  573                 /* check next receive buffer */
  574                 sc->sc_rindex++;
  575                 if (sc->sc_rindex == NRCV)
  576                         sc->sc_rindex = 0;
  577                 rp = &dc->dc_rrent[sc->sc_rindex];
  578         }
  579 }
  580 
  581 /*
  582  * Process an ioctl request.
  583  */
  584 int
  585 deioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  586 {
  587         int s, error = 0;
  588 
  589         s = splnet();
  590 
  591         error = ether_ioctl(ifp, cmd, data);
  592         if (error == ENETRESET)
  593                 error = 0;
  594 
  595         splx(s);
  596         return (error);
  597 }
  598 
  599 /*
  600  * Await completion of the named function
  601  * and check for errors.
  602  */
  603 void
  604 dewait(struct de_softc *sc, char *fn)
  605 {
  606         int csr0;
  607 
  608         while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0)
  609                 ;
  610         csr0 = DE_RCSR(DE_PCSR0);
  611         DE_WHIGH(csr0 >> 8);
  612         if (csr0 & PCSR0_PCEI) {
  613                 char bits[64];
  614                 printf("%s: %s failed, csr0=%s ", sc->sc_dev.dv_xname, fn,
  615                     bitmask_snprintf(csr0, PCSR0_BITS, bits, sizeof(bits)));
  616                 printf("csr1=%s\n", bitmask_snprintf(DE_RCSR(DE_PCSR1),
  617                     PCSR1_BITS, bits, sizeof(bits)));
  618         }
  619 }
  620 
  621 int
  622 dematch(struct device *parent, struct cfdata *cf, void *aux)
  623 {
  624         struct uba_attach_args *ua = aux;
  625         struct de_softc ssc;
  626         struct de_softc *sc = &ssc;
  627         int i;
  628 
  629         sc->sc_iot = ua->ua_iot;
  630         sc->sc_ioh = ua->ua_ioh;
  631         /*
  632          * Make sure self-test is finished before we screw with the board.
  633          * Self-test on a DELUA can take 15 seconds (argh).
  634          */
  635         for (i = 0;
  636             (i < 160) &&
  637             (DE_RCSR(DE_PCSR0) & PCSR0_FATI) == 0 &&
  638             (DE_RCSR(DE_PCSR1) & PCSR1_STMASK) == STAT_RESET;
  639             ++i)
  640                 DELAY(50000);
  641         if (((DE_RCSR(DE_PCSR0) & PCSR0_FATI) != 0) ||
  642             (((DE_RCSR(DE_PCSR1) & PCSR1_STMASK) != STAT_READY) &&
  643             ((DE_RCSR(DE_PCSR1) & PCSR1_STMASK) != STAT_RUN)))
  644                 return(0);
  645 
  646         DE_WCSR(DE_PCSR0, 0);
  647         DELAY(5000);
  648         DE_WCSR(DE_PCSR0, PCSR0_RSET);
  649         while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0)
  650                 ;
  651         /* make board interrupt by executing a GETPCBB command */
  652         DE_WCSR(DE_PCSR0, PCSR0_INTE);
  653         DE_WCSR(DE_PCSR2, 0);
  654         DE_WCSR(DE_PCSR3, 0);
  655         DE_WCSR(DE_PCSR0, PCSR0_INTE|CMD_GETPCBB);
  656         DELAY(50000);
  657 
  658         return 1;
  659 }
  660 
  661 void
  662 deshutdown(void *arg)
  663 {
  664         struct de_softc *sc = arg;
  665 
  666         DE_WCSR(DE_PCSR0, 0);
  667         DELAY(1000);
  668         DE_WCSR(DE_PCSR0, PCSR0_RSET);
  669         dewait(sc, "shutdown");
  670 }

Cache object: 8234eb21514d695dfc3e1582f2094c81


[ 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.