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.23 2008/03/11 05:34:01 matt 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.23 2008/03/11 05:34:01 matt 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 <sys/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         device_t sc_dev;                /* Configuration common part */
  155         struct uba_softc *sc_uh;        /* our parent */
  156         struct evcnt sc_intrcnt;        /* Interrupt counting */
  157         struct ethercom sc_ec;          /* Ethernet common part */
  158 #define sc_if   sc_ec.ec_if             /* network-visible interface */
  159         bus_space_tag_t sc_iot;
  160         bus_addr_t sc_ioh;
  161         bus_dma_tag_t sc_dmat;
  162         int sc_flags;
  163 #define DSF_MAPPED      1
  164         struct ubinfo sc_ui;
  165         struct de_cdata *sc_dedata;     /* Control structure */
  166         struct de_cdata *sc_pdedata;    /* Bus-mapped control structure */
  167         struct ifubinfo sc_ifuba;       /* UNIBUS resources */
  168         struct ifrw sc_ifr[NRCV];       /* UNIBUS receive buffer maps */
  169         struct ifxmt sc_ifw[NXMT];      /* UNIBUS receive buffer maps */
  170 
  171         int sc_xindex;                  /* UNA index into transmit chain */
  172         int sc_rindex;                  /* UNA index into receive chain */
  173         int sc_xfree;                   /* index for next transmit buffer */
  174         int sc_nxmit;                   /* # of transmits in progress */
  175         void *sc_sh;                    /* shutdownhook cookie */
  176 };
  177 
  178 static  int dematch(device_t, cfdata_t, void *);
  179 static  void deattach(device_t, device_t, void *);
  180 static  void dewait(struct de_softc *, const char *);
  181 static  int deinit(struct ifnet *);
  182 static  int deioctl(struct ifnet *, u_long, void *);
  183 static  void dereset(device_t );
  184 static  void destop(struct ifnet *, int);
  185 static  void destart(struct ifnet *);
  186 static  void derecv(struct de_softc *);
  187 static  void deintr(void *);
  188 static  void deshutdown(void *);
  189 
  190 CFATTACH_DECL_NEW(de, sizeof(struct de_softc),
  191     dematch, deattach, NULL, NULL);
  192 
  193 #define DE_WCSR(csr, val) \
  194         bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val)
  195 #define DE_WLOW(val) \
  196         bus_space_write_1(sc->sc_iot, sc->sc_ioh, DE_PCSR0, val)
  197 #define DE_WHIGH(val) \
  198         bus_space_write_1(sc->sc_iot, sc->sc_ioh, DE_PCSR0 + 1, val)
  199 #define DE_RCSR(csr) \
  200         bus_space_read_2(sc->sc_iot, sc->sc_ioh, csr)
  201 
  202 #define LOWORD(x)       ((int)(x) & 0xffff)
  203 #define HIWORD(x)       (((int)(x) >> 16) & 0x3)
  204 /*
  205  * Interface exists: make available by filling in network interface
  206  * record.  System will initialize the interface when it is ready
  207  * to accept packets.  We get the ethernet address here.
  208  */
  209 void
  210 deattach(device_t parent, device_t self, void *aux)
  211 {
  212         struct uba_attach_args *ua = aux;
  213         struct de_softc *sc = device_private(self);
  214         struct ifnet *ifp = &sc->sc_if;
  215         u_int8_t myaddr[ETHER_ADDR_LEN];
  216         int csr1, error;
  217         const char *c;
  218 
  219         sc->sc_dev = self;
  220         sc->sc_uh = device_private(parent);
  221         sc->sc_iot = ua->ua_iot;
  222         sc->sc_ioh = ua->ua_ioh;
  223         sc->sc_dmat = ua->ua_dmat;
  224 
  225         /*
  226          * What kind of a board is this?
  227          * The error bits 4-6 in pcsr1 are a device id as long as
  228          * the high byte is zero.
  229          */
  230         csr1 = DE_RCSR(DE_PCSR1);
  231         if (csr1 & 0xff60)
  232                 c = "broken";
  233         else if (csr1 & 0x10)
  234                 c = "delua";
  235         else
  236                 c = "deuna";
  237 
  238         /*
  239          * Reset the board and temporarily map
  240          * the pcbb buffer onto the Unibus.
  241          */
  242         DE_WCSR(DE_PCSR0, 0);           /* reset INTE */
  243         DELAY(100);
  244         DE_WCSR(DE_PCSR0, PCSR0_RSET);
  245         dewait(sc, "reset");
  246 
  247         sc->sc_ui.ui_size = sizeof(struct de_cdata);
  248         if ((error = ubmemalloc(sc->sc_uh, &sc->sc_ui, 0)))
  249                 return printf(": failed ubmemalloc(), error = %d\n", error);
  250         sc->sc_dedata = (struct de_cdata *)sc->sc_ui.ui_vaddr;
  251 
  252         /*
  253          * Tell the DEUNA about our PCB
  254          */
  255         DE_WCSR(DE_PCSR2, LOWORD(sc->sc_ui.ui_baddr));
  256         DE_WCSR(DE_PCSR3, HIWORD(sc->sc_ui.ui_baddr));
  257         DE_WLOW(CMD_GETPCBB);
  258         dewait(sc, "pcbb");
  259 
  260         sc->sc_dedata->dc_pcbb.pcbb0 = FC_RDPHYAD;
  261         DE_WLOW(CMD_GETCMD);
  262         dewait(sc, "read addr ");
  263 
  264         bcopy((void *)&sc->sc_dedata->dc_pcbb.pcbb2, myaddr, sizeof (myaddr));
  265         printf(": %s, hardware address %s\n", c, ether_sprintf(myaddr));
  266 
  267         uba_intr_establish(ua->ua_icookie, ua->ua_cvec, deintr, sc,
  268             &sc->sc_intrcnt);
  269         uba_reset_establish(dereset, sc->sc_dev);
  270         evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  271             device_xname(sc->sc_dev), "intr");
  272 
  273         strcpy(ifp->if_xname, device_xname(sc->sc_dev));
  274         ifp->if_softc = sc;
  275         ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI;
  276         ifp->if_ioctl = deioctl;
  277         ifp->if_start = destart;
  278         ifp->if_init = deinit;
  279         ifp->if_stop = destop;
  280         IFQ_SET_READY(&ifp->if_snd);
  281 
  282         if_attach(ifp);
  283         ether_ifattach(ifp, myaddr);
  284         ubmemfree(sc->sc_uh, &sc->sc_ui);
  285 
  286         sc->sc_sh = shutdownhook_establish(deshutdown, sc);
  287 }
  288 
  289 void
  290 destop(struct ifnet *ifp, int a)
  291 {
  292         struct de_softc *sc = ifp->if_softc;
  293 
  294         DE_WLOW(0);
  295         DELAY(5000);
  296         DE_WLOW(PCSR0_RSET);
  297 }
  298 
  299 
  300 /*
  301  * Reset of interface after UNIBUS reset.
  302  */
  303 void
  304 dereset(device_t dev)
  305 {
  306         struct de_softc *sc = (void *)dev;
  307 
  308         sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
  309         sc->sc_flags &= ~DSF_MAPPED;
  310         sc->sc_pdedata = NULL;  /* All mappings lost */
  311         DE_WCSR(DE_PCSR0, PCSR0_RSET);
  312         dewait(sc, "reset");
  313         deinit(&sc->sc_if);
  314 }
  315 
  316 /*
  317  * Initialization of interface; clear recorded pending
  318  * operations, and reinitialize UNIBUS usage.
  319  */
  320 int
  321 deinit(struct ifnet *ifp)
  322 {
  323         struct de_softc *sc = ifp->if_softc;
  324         struct de_cdata *dc, *pdc;
  325         struct ifrw *ifrw;
  326         struct ifxmt *ifxp;
  327         struct de_ring *rp;
  328         int s, error;
  329 
  330         if (ifp->if_flags & IFF_RUNNING)
  331                 return 0;
  332         if ((sc->sc_flags & DSF_MAPPED) == 0) {
  333                 if (if_ubaminit(&sc->sc_ifuba, sc->sc_uh, MCLBYTES,
  334                                 sc->sc_ifr, NRCV, sc->sc_ifw, NXMT)) {
  335                         aprint_error_dev(sc->sc_dev, " can't initialize\n");
  336                         ifp->if_flags &= ~IFF_UP;
  337                         return 0;
  338                 }
  339                 sc->sc_ui.ui_size = sizeof(struct de_cdata);
  340                 if ((error = ubmemalloc(sc->sc_uh, &sc->sc_ui, 0))) {
  341                         aprint_error(": unable to ubmemalloc(), error = %d\n",
  342                             error);
  343                         return 0;
  344                 }
  345                 sc->sc_pdedata = (struct de_cdata *)sc->sc_ui.ui_baddr;
  346                 sc->sc_dedata = (struct de_cdata *)sc->sc_ui.ui_vaddr;
  347                 sc->sc_flags |= DSF_MAPPED;
  348         }
  349 
  350         /*
  351          * Tell the DEUNA about our PCB
  352          */
  353         DE_WCSR(DE_PCSR2, LOWORD(sc->sc_pdedata));
  354         DE_WCSR(DE_PCSR3, HIWORD(sc->sc_pdedata));
  355         DE_WLOW(0);             /* reset INTE */
  356         DELAY(500);
  357         DE_WLOW(CMD_GETPCBB);
  358         dewait(sc, "pcbb");
  359 
  360         dc = sc->sc_dedata;
  361         pdc = sc->sc_pdedata;
  362         /* set the transmit and receive ring header addresses */
  363         dc->dc_pcbb.pcbb0 = FC_WTRING;
  364         dc->dc_pcbb.pcbb2 = LOWORD(&pdc->dc_udbbuf);
  365         dc->dc_pcbb.pcbb4 = HIWORD(&pdc->dc_udbbuf);
  366 
  367         dc->dc_udbbuf.b_tdrbl = LOWORD(&pdc->dc_xrent[0]);
  368         dc->dc_udbbuf.b_tdrbh = HIWORD(&pdc->dc_xrent[0]);
  369         dc->dc_udbbuf.b_telen = sizeof (struct de_ring) / sizeof(u_int16_t);
  370         dc->dc_udbbuf.b_trlen = NXMT;
  371         dc->dc_udbbuf.b_rdrbl = LOWORD(&pdc->dc_rrent[0]);
  372         dc->dc_udbbuf.b_rdrbh = HIWORD(&pdc->dc_rrent[0]);
  373         dc->dc_udbbuf.b_relen = sizeof (struct de_ring) / sizeof(u_int16_t);
  374         dc->dc_udbbuf.b_rrlen = NRCV;
  375 
  376         DE_WLOW(CMD_GETCMD);
  377         dewait(sc, "wtring");
  378 
  379         sc->sc_dedata->dc_pcbb.pcbb0 = FC_WTMODE;
  380         sc->sc_dedata->dc_pcbb.pcbb2 = MOD_TPAD|MOD_HDX|MOD_DRDC|MOD_ENAL;
  381         DE_WLOW(CMD_GETCMD);
  382         dewait(sc, "wtmode");
  383 
  384         /* set up the receive and transmit ring entries */
  385         ifxp = &sc->sc_ifw[0];
  386         for (rp = &dc->dc_xrent[0]; rp < &dc->dc_xrent[NXMT]; rp++) {
  387                 rp->r_segbl = LOWORD(ifxp->ifw_info);
  388                 rp->r_segbh = HIWORD(ifxp->ifw_info);
  389                 rp->r_flags = 0;
  390                 ifxp++;
  391         }
  392         ifrw = &sc->sc_ifr[0];
  393         for (rp = &dc->dc_rrent[0]; rp < &dc->dc_rrent[NRCV]; rp++) {
  394                 rp->r_slen = MCLBYTES - 2;
  395                 rp->r_segbl = LOWORD(ifrw->ifrw_info);
  396                 rp->r_segbh = HIWORD(ifrw->ifrw_info);
  397                 rp->r_flags = RFLG_OWN;
  398                 ifrw++;
  399         }
  400 
  401         /* start up the board (rah rah) */
  402         s = splnet();
  403         sc->sc_rindex = sc->sc_xindex = sc->sc_xfree = sc->sc_nxmit = 0;
  404         sc->sc_if.if_flags |= IFF_RUNNING;
  405         DE_WLOW(PCSR0_INTE);                    /* avoid interlock */
  406         destart(&sc->sc_if);            /* queue output packets */
  407         DE_WLOW(CMD_START|PCSR0_INTE);
  408         splx(s);
  409         return 0;
  410 }
  411 
  412 /*
  413  * Setup output on interface.
  414  * Get another datagram to send off of the interface queue,
  415  * and map it to the interface before starting the output.
  416  * Must be called from ipl >= our interrupt level.
  417  */
  418 void
  419 destart(struct ifnet *ifp)
  420 {
  421         struct de_softc *sc = ifp->if_softc;
  422         struct de_cdata *dc;
  423         struct de_ring *rp;
  424         struct mbuf *m;
  425         int nxmit, len;
  426 
  427         /*
  428          * the following test is necessary, since
  429          * the code is not reentrant and we have
  430          * multiple transmission buffers.
  431          */
  432         if (sc->sc_if.if_flags & IFF_OACTIVE)
  433                 return;
  434         dc = sc->sc_dedata;
  435         for (nxmit = sc->sc_nxmit; nxmit < NXMT; nxmit++) {
  436                 IFQ_DEQUEUE(&ifp->if_snd, m);
  437                 if (m == 0)
  438                         break;
  439 
  440                 rp = &dc->dc_xrent[sc->sc_xfree];
  441                 if (rp->r_flags & XFLG_OWN)
  442                         panic("deuna xmit in progress");
  443 #if NBPFILTER > 0
  444                 if (ifp->if_bpf)
  445                         bpf_mtap(ifp->if_bpf, m);
  446 #endif
  447 
  448                 len = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[sc->sc_xfree], m);
  449                 rp->r_slen = len;
  450                 rp->r_tdrerr = 0;
  451                 rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
  452 
  453                 sc->sc_xfree++;
  454                 if (sc->sc_xfree == NXMT)
  455                         sc->sc_xfree = 0;
  456         }
  457         if (sc->sc_nxmit != nxmit) {
  458                 sc->sc_nxmit = nxmit;
  459                 if (ifp->if_flags & IFF_RUNNING)
  460                         DE_WLOW(PCSR0_INTE|CMD_PDMD);
  461         }
  462 }
  463 
  464 /*
  465  * Command done interrupt.
  466  */
  467 void
  468 deintr(void *arg)
  469 {
  470         struct ifxmt *ifxp;
  471         struct de_cdata *dc;
  472         struct de_softc *sc = arg;
  473         struct de_ring *rp;
  474         short csr0;
  475 
  476         /* save flags right away - clear out interrupt bits */
  477         csr0 = DE_RCSR(DE_PCSR0);
  478         DE_WHIGH(csr0 >> 8);
  479 
  480 
  481         sc->sc_if.if_flags |= IFF_OACTIVE;      /* prevent entering destart */
  482         /*
  483          * if receive, put receive buffer on mbuf
  484          * and hang the request again
  485          */
  486         derecv(sc);
  487 
  488         /*
  489          * Poll transmit ring and check status.
  490          * Be careful about loopback requests.
  491          * Then free buffer space and check for
  492          * more transmit requests.
  493          */
  494         dc = sc->sc_dedata;
  495         for ( ; sc->sc_nxmit > 0; sc->sc_nxmit--) {
  496                 rp = &dc->dc_xrent[sc->sc_xindex];
  497                 if (rp->r_flags & XFLG_OWN)
  498                         break;
  499 
  500                 sc->sc_if.if_opackets++;
  501                 ifxp = &sc->sc_ifw[sc->sc_xindex];
  502                 /* check for unusual conditions */
  503                 if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
  504                         if (rp->r_flags & XFLG_ERRS) {
  505                                 /* output error */
  506                                 sc->sc_if.if_oerrors++;
  507                         } else if (rp->r_flags & XFLG_ONE) {
  508                                 /* one collision */
  509                                 sc->sc_if.if_collisions++;
  510                         } else if (rp->r_flags & XFLG_MORE) {
  511                                 /* more than one collision */
  512                                 sc->sc_if.if_collisions += 2;   /* guess */
  513                         }
  514                 }
  515                 if_ubaend(&sc->sc_ifuba, ifxp);
  516                 /* check if next transmit buffer also finished */
  517                 sc->sc_xindex++;
  518                 if (sc->sc_xindex == NXMT)
  519                         sc->sc_xindex = 0;
  520         }
  521         sc->sc_if.if_flags &= ~IFF_OACTIVE;
  522         destart(&sc->sc_if);
  523 
  524         if (csr0 & PCSR0_RCBI) {
  525                 DE_WLOW(PCSR0_INTE|CMD_PDMD);
  526         }
  527 }
  528 
  529 /*
  530  * Ethernet interface receiver interface.
  531  * If input error just drop packet.
  532  * Otherwise purge input buffered data path and examine
  533  * packet to determine type.  If can't determine length
  534  * from type, then have to drop packet.  Othewise decapsulate
  535  * packet based on type and pass to type specific higher-level
  536  * input routine.
  537  */
  538 void
  539 derecv(struct de_softc *sc)
  540 {
  541         struct ifnet *ifp = &sc->sc_if;
  542         struct de_ring *rp;
  543         struct de_cdata *dc;
  544         struct mbuf *m;
  545         int len;
  546 
  547         dc = sc->sc_dedata;
  548         rp = &dc->dc_rrent[sc->sc_rindex];
  549         while ((rp->r_flags & RFLG_OWN) == 0) {
  550                 sc->sc_if.if_ipackets++;
  551                 len = (rp->r_lenerr&RERR_MLEN) - ETHER_CRC_LEN;
  552                 /* check for errors */
  553                 if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) ||
  554                     (rp->r_lenerr & (RERR_BUFL|RERR_UBTO))) {
  555                         sc->sc_if.if_ierrors++;
  556                         goto next;
  557                 }
  558                 m = if_ubaget(&sc->sc_ifuba, &sc->sc_ifr[sc->sc_rindex],
  559                     ifp, len);
  560                 if (m == 0) {
  561                         sc->sc_if.if_ierrors++;
  562                         goto next;
  563                 }
  564 #if NBPFILTER > 0
  565                 if (ifp->if_bpf)
  566                         bpf_mtap(ifp->if_bpf, m);
  567 #endif
  568 
  569                 (*ifp->if_input)(ifp, m);
  570 
  571                 /* hang the receive buffer again */
  572 next:           rp->r_lenerr = 0;
  573                 rp->r_flags = RFLG_OWN;
  574 
  575                 /* check next receive buffer */
  576                 sc->sc_rindex++;
  577                 if (sc->sc_rindex == NRCV)
  578                         sc->sc_rindex = 0;
  579                 rp = &dc->dc_rrent[sc->sc_rindex];
  580         }
  581 }
  582 
  583 /*
  584  * Process an ioctl request.
  585  */
  586 int
  587 deioctl(struct ifnet *ifp, u_long cmd, void *data)
  588 {
  589         int s, error = 0;
  590 
  591         s = splnet();
  592 
  593         error = ether_ioctl(ifp, cmd, data);
  594         if (error == ENETRESET)
  595                 error = 0;
  596 
  597         splx(s);
  598         return (error);
  599 }
  600 
  601 /*
  602  * Await completion of the named function
  603  * and check for errors.
  604  */
  605 void
  606 dewait(struct de_softc *sc, const char *fn)
  607 {
  608         int csr0, csr1;
  609 
  610         while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0)
  611                 ;
  612         csr0 = DE_RCSR(DE_PCSR0);
  613         DE_WHIGH(csr0 >> 8);
  614         if (csr0 & PCSR0_PCEI) {
  615                 char bits0[64];
  616                 char bits1[64];
  617                 csr1 = DE_RCSR(DE_PCSR1);
  618                 aprint_error_dev(sc->sc_dev, "%s failed, csr0=%s csr1=%s\n",
  619                     fn,
  620                     bitmask_snprintf(csr0, PCSR0_BITS, bits0, sizeof(bits0)),
  621                     bitmask_snprintf(csr1, PCSR1_BITS, bits1, sizeof(bits1)));
  622         }
  623 }
  624 
  625 int
  626 dematch(device_t parent, cfdata_t cf, void *aux)
  627 {
  628         struct uba_attach_args *ua = aux;
  629         struct de_softc ssc;
  630         struct de_softc *sc = &ssc;
  631         int i;
  632 
  633         sc->sc_iot = ua->ua_iot;
  634         sc->sc_ioh = ua->ua_ioh;
  635         /*
  636          * Make sure self-test is finished before we screw with the board.
  637          * Self-test on a DELUA can take 15 seconds (argh).
  638          */
  639         for (i = 0;
  640             (i < 160) &&
  641             (DE_RCSR(DE_PCSR0) & PCSR0_FATI) == 0 &&
  642             (DE_RCSR(DE_PCSR1) & PCSR1_STMASK) == STAT_RESET;
  643             ++i)
  644                 DELAY(50000);
  645         if (((DE_RCSR(DE_PCSR0) & PCSR0_FATI) != 0) ||
  646             (((DE_RCSR(DE_PCSR1) & PCSR1_STMASK) != STAT_READY) &&
  647             ((DE_RCSR(DE_PCSR1) & PCSR1_STMASK) != STAT_RUN)))
  648                 return(0);
  649 
  650         DE_WCSR(DE_PCSR0, 0);
  651         DELAY(5000);
  652         DE_WCSR(DE_PCSR0, PCSR0_RSET);
  653         while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0)
  654                 ;
  655         /* make board interrupt by executing a GETPCBB command */
  656         DE_WCSR(DE_PCSR0, PCSR0_INTE);
  657         DE_WCSR(DE_PCSR2, 0);
  658         DE_WCSR(DE_PCSR3, 0);
  659         DE_WCSR(DE_PCSR0, PCSR0_INTE|CMD_GETPCBB);
  660         DELAY(50000);
  661 
  662         return 1;
  663 }
  664 
  665 void
  666 deshutdown(void *arg)
  667 {
  668         struct de_softc *sc = arg;
  669 
  670         DE_WCSR(DE_PCSR0, 0);
  671         DELAY(1000);
  672         DE_WCSR(DE_PCSR0, PCSR0_RSET);
  673         dewait(sc, "shutdown");
  674 }

Cache object: f5fc77b7cf62f13192a5cadc80a8e3bd


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