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.20 2006/03/29 18:17:36 thorpej 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.20 2006/03/29 18:17:36 thorpej 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 *, const 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 = device_private(self);
  213         struct ifnet *ifp = &sc->sc_if;
  214         u_int8_t myaddr[ETHER_ADDR_LEN];
  215         int csr1, error;
  216         const 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,
  332                     (void *)device_parent(&sc->sc_dev),
  333                     MCLBYTES, sc->sc_ifr, NRCV, sc->sc_ifw, NXMT)) {
  334                         printf("%s: can't initialize\n", sc->sc_dev.dv_xname);
  335                         ifp->if_flags &= ~IFF_UP;
  336                         return 0;
  337                 }
  338                 sc->sc_ui.ui_size = sizeof(struct de_cdata);
  339                 if ((error = ubmemalloc((void *)device_parent(&sc->sc_dev),
  340                     &sc->sc_ui, 0))) {
  341                         printf(": unable to ubmemalloc(), error = %d\n", error);
  342                         return 0;
  343                 }
  344                 sc->sc_pdedata = (struct de_cdata *)sc->sc_ui.ui_baddr;
  345                 sc->sc_dedata = (struct de_cdata *)sc->sc_ui.ui_vaddr;
  346                 sc->sc_flags |= DSF_MAPPED;
  347         }
  348 
  349         /*
  350          * Tell the DEUNA about our PCB
  351          */
  352         DE_WCSR(DE_PCSR2, LOWORD(sc->sc_pdedata));
  353         DE_WCSR(DE_PCSR3, HIWORD(sc->sc_pdedata));
  354         DE_WLOW(0);             /* reset INTE */
  355         DELAY(500);
  356         DE_WLOW(CMD_GETPCBB);
  357         dewait(sc, "pcbb");
  358 
  359         dc = sc->sc_dedata;
  360         pdc = sc->sc_pdedata;
  361         /* set the transmit and receive ring header addresses */
  362         dc->dc_pcbb.pcbb0 = FC_WTRING;
  363         dc->dc_pcbb.pcbb2 = LOWORD(&pdc->dc_udbbuf);
  364         dc->dc_pcbb.pcbb4 = HIWORD(&pdc->dc_udbbuf);
  365 
  366         dc->dc_udbbuf.b_tdrbl = LOWORD(&pdc->dc_xrent[0]);
  367         dc->dc_udbbuf.b_tdrbh = HIWORD(&pdc->dc_xrent[0]);
  368         dc->dc_udbbuf.b_telen = sizeof (struct de_ring) / sizeof(u_int16_t);
  369         dc->dc_udbbuf.b_trlen = NXMT;
  370         dc->dc_udbbuf.b_rdrbl = LOWORD(&pdc->dc_rrent[0]);
  371         dc->dc_udbbuf.b_rdrbh = HIWORD(&pdc->dc_rrent[0]);
  372         dc->dc_udbbuf.b_relen = sizeof (struct de_ring) / sizeof(u_int16_t);
  373         dc->dc_udbbuf.b_rrlen = NRCV;
  374 
  375         DE_WLOW(CMD_GETCMD);
  376         dewait(sc, "wtring");
  377 
  378         sc->sc_dedata->dc_pcbb.pcbb0 = FC_WTMODE;
  379         sc->sc_dedata->dc_pcbb.pcbb2 = MOD_TPAD|MOD_HDX|MOD_DRDC|MOD_ENAL;
  380         DE_WLOW(CMD_GETCMD);
  381         dewait(sc, "wtmode");
  382 
  383         /* set up the receive and transmit ring entries */
  384         ifxp = &sc->sc_ifw[0];
  385         for (rp = &dc->dc_xrent[0]; rp < &dc->dc_xrent[NXMT]; rp++) {
  386                 rp->r_segbl = LOWORD(ifxp->ifw_info);
  387                 rp->r_segbh = HIWORD(ifxp->ifw_info);
  388                 rp->r_flags = 0;
  389                 ifxp++;
  390         }
  391         ifrw = &sc->sc_ifr[0];
  392         for (rp = &dc->dc_rrent[0]; rp < &dc->dc_rrent[NRCV]; rp++) {
  393                 rp->r_slen = MCLBYTES - 2;
  394                 rp->r_segbl = LOWORD(ifrw->ifrw_info);
  395                 rp->r_segbh = HIWORD(ifrw->ifrw_info);
  396                 rp->r_flags = RFLG_OWN;
  397                 ifrw++;
  398         }
  399 
  400         /* start up the board (rah rah) */
  401         s = splnet();
  402         sc->sc_rindex = sc->sc_xindex = sc->sc_xfree = sc->sc_nxmit = 0;
  403         sc->sc_if.if_flags |= IFF_RUNNING;
  404         DE_WLOW(PCSR0_INTE);                    /* avoid interlock */
  405         destart(&sc->sc_if);            /* queue output packets */
  406         DE_WLOW(CMD_START|PCSR0_INTE);
  407         splx(s);
  408         return 0;
  409 }
  410 
  411 /*
  412  * Setup output on interface.
  413  * Get another datagram to send off of the interface queue,
  414  * and map it to the interface before starting the output.
  415  * Must be called from ipl >= our interrupt level.
  416  */
  417 void
  418 destart(struct ifnet *ifp)
  419 {
  420         struct de_softc *sc = ifp->if_softc;
  421         struct de_cdata *dc;
  422         struct de_ring *rp;
  423         struct mbuf *m;
  424         int nxmit, len;
  425 
  426         /*
  427          * the following test is necessary, since
  428          * the code is not reentrant and we have
  429          * multiple transmission buffers.
  430          */
  431         if (sc->sc_if.if_flags & IFF_OACTIVE)
  432                 return;
  433         dc = sc->sc_dedata;
  434         for (nxmit = sc->sc_nxmit; nxmit < NXMT; nxmit++) {
  435                 IFQ_DEQUEUE(&ifp->if_snd, m);
  436                 if (m == 0)
  437                         break;
  438 
  439                 rp = &dc->dc_xrent[sc->sc_xfree];
  440                 if (rp->r_flags & XFLG_OWN)
  441                         panic("deuna xmit in progress");
  442 #if NBPFILTER > 0
  443                 if (ifp->if_bpf)
  444                         bpf_mtap(ifp->if_bpf, m);
  445 #endif
  446 
  447                 len = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[sc->sc_xfree], m);
  448                 rp->r_slen = len;
  449                 rp->r_tdrerr = 0;
  450                 rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
  451 
  452                 sc->sc_xfree++;
  453                 if (sc->sc_xfree == NXMT)
  454                         sc->sc_xfree = 0;
  455         }
  456         if (sc->sc_nxmit != nxmit) {
  457                 sc->sc_nxmit = nxmit;
  458                 if (ifp->if_flags & IFF_RUNNING)
  459                         DE_WLOW(PCSR0_INTE|CMD_PDMD);
  460         }
  461 }
  462 
  463 /*
  464  * Command done interrupt.
  465  */
  466 void
  467 deintr(void *arg)
  468 {
  469         struct ifxmt *ifxp;
  470         struct de_cdata *dc;
  471         struct de_softc *sc = arg;
  472         struct de_ring *rp;
  473         short csr0;
  474 
  475         /* save flags right away - clear out interrupt bits */
  476         csr0 = DE_RCSR(DE_PCSR0);
  477         DE_WHIGH(csr0 >> 8);
  478 
  479 
  480         sc->sc_if.if_flags |= IFF_OACTIVE;      /* prevent entering destart */
  481         /*
  482          * if receive, put receive buffer on mbuf
  483          * and hang the request again
  484          */
  485         derecv(sc);
  486 
  487         /*
  488          * Poll transmit ring and check status.
  489          * Be careful about loopback requests.
  490          * Then free buffer space and check for
  491          * more transmit requests.
  492          */
  493         dc = sc->sc_dedata;
  494         for ( ; sc->sc_nxmit > 0; sc->sc_nxmit--) {
  495                 rp = &dc->dc_xrent[sc->sc_xindex];
  496                 if (rp->r_flags & XFLG_OWN)
  497                         break;
  498 
  499                 sc->sc_if.if_opackets++;
  500                 ifxp = &sc->sc_ifw[sc->sc_xindex];
  501                 /* check for unusual conditions */
  502                 if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
  503                         if (rp->r_flags & XFLG_ERRS) {
  504                                 /* output error */
  505                                 sc->sc_if.if_oerrors++;
  506                         } else if (rp->r_flags & XFLG_ONE) {
  507                                 /* one collision */
  508                                 sc->sc_if.if_collisions++;
  509                         } else if (rp->r_flags & XFLG_MORE) {
  510                                 /* more than one collision */
  511                                 sc->sc_if.if_collisions += 2;   /* guess */
  512                         }
  513                 }
  514                 if_ubaend(&sc->sc_ifuba, ifxp);
  515                 /* check if next transmit buffer also finished */
  516                 sc->sc_xindex++;
  517                 if (sc->sc_xindex == NXMT)
  518                         sc->sc_xindex = 0;
  519         }
  520         sc->sc_if.if_flags &= ~IFF_OACTIVE;
  521         destart(&sc->sc_if);
  522 
  523         if (csr0 & PCSR0_RCBI) {
  524                 DE_WLOW(PCSR0_INTE|CMD_PDMD);
  525         }
  526 }
  527 
  528 /*
  529  * Ethernet interface receiver interface.
  530  * If input error just drop packet.
  531  * Otherwise purge input buffered data path and examine
  532  * packet to determine type.  If can't determine length
  533  * from type, then have to drop packet.  Othewise decapsulate
  534  * packet based on type and pass to type specific higher-level
  535  * input routine.
  536  */
  537 void
  538 derecv(struct de_softc *sc)
  539 {
  540         struct ifnet *ifp = &sc->sc_if;
  541         struct de_ring *rp;
  542         struct de_cdata *dc;
  543         struct mbuf *m;
  544         int len;
  545 
  546         dc = sc->sc_dedata;
  547         rp = &dc->dc_rrent[sc->sc_rindex];
  548         while ((rp->r_flags & RFLG_OWN) == 0) {
  549                 sc->sc_if.if_ipackets++;
  550                 len = (rp->r_lenerr&RERR_MLEN) - ETHER_CRC_LEN;
  551                 /* check for errors */
  552                 if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) ||
  553                     (rp->r_lenerr & (RERR_BUFL|RERR_UBTO))) {
  554                         sc->sc_if.if_ierrors++;
  555                         goto next;
  556                 }
  557                 m = if_ubaget(&sc->sc_ifuba, &sc->sc_ifr[sc->sc_rindex],
  558                     ifp, len);
  559                 if (m == 0) {
  560                         sc->sc_if.if_ierrors++;
  561                         goto next;
  562                 }
  563 #if NBPFILTER > 0
  564                 if (ifp->if_bpf)
  565                         bpf_mtap(ifp->if_bpf, m);
  566 #endif
  567 
  568                 (*ifp->if_input)(ifp, m);
  569 
  570                 /* hang the receive buffer again */
  571 next:           rp->r_lenerr = 0;
  572                 rp->r_flags = RFLG_OWN;
  573 
  574                 /* check next receive buffer */
  575                 sc->sc_rindex++;
  576                 if (sc->sc_rindex == NRCV)
  577                         sc->sc_rindex = 0;
  578                 rp = &dc->dc_rrent[sc->sc_rindex];
  579         }
  580 }
  581 
  582 /*
  583  * Process an ioctl request.
  584  */
  585 int
  586 deioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  587 {
  588         int s, error = 0;
  589 
  590         s = splnet();
  591 
  592         error = ether_ioctl(ifp, cmd, data);
  593         if (error == ENETRESET)
  594                 error = 0;
  595 
  596         splx(s);
  597         return (error);
  598 }
  599 
  600 /*
  601  * Await completion of the named function
  602  * and check for errors.
  603  */
  604 void
  605 dewait(struct de_softc *sc, const char *fn)
  606 {
  607         int csr0;
  608 
  609         while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0)
  610                 ;
  611         csr0 = DE_RCSR(DE_PCSR0);
  612         DE_WHIGH(csr0 >> 8);
  613         if (csr0 & PCSR0_PCEI) {
  614                 char bits[64];
  615                 printf("%s: %s failed, csr0=%s ", sc->sc_dev.dv_xname, fn,
  616                     bitmask_snprintf(csr0, PCSR0_BITS, bits, sizeof(bits)));
  617                 printf("csr1=%s\n", bitmask_snprintf(DE_RCSR(DE_PCSR1),
  618                     PCSR1_BITS, bits, sizeof(bits)));
  619         }
  620 }
  621 
  622 int
  623 dematch(struct device *parent, struct cfdata *cf, void *aux)
  624 {
  625         struct uba_attach_args *ua = aux;
  626         struct de_softc ssc;
  627         struct de_softc *sc = &ssc;
  628         int i;
  629 
  630         sc->sc_iot = ua->ua_iot;
  631         sc->sc_ioh = ua->ua_ioh;
  632         /*
  633          * Make sure self-test is finished before we screw with the board.
  634          * Self-test on a DELUA can take 15 seconds (argh).
  635          */
  636         for (i = 0;
  637             (i < 160) &&
  638             (DE_RCSR(DE_PCSR0) & PCSR0_FATI) == 0 &&
  639             (DE_RCSR(DE_PCSR1) & PCSR1_STMASK) == STAT_RESET;
  640             ++i)
  641                 DELAY(50000);
  642         if (((DE_RCSR(DE_PCSR0) & PCSR0_FATI) != 0) ||
  643             (((DE_RCSR(DE_PCSR1) & PCSR1_STMASK) != STAT_READY) &&
  644             ((DE_RCSR(DE_PCSR1) & PCSR1_STMASK) != STAT_RUN)))
  645                 return(0);
  646 
  647         DE_WCSR(DE_PCSR0, 0);
  648         DELAY(5000);
  649         DE_WCSR(DE_PCSR0, PCSR0_RSET);
  650         while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0)
  651                 ;
  652         /* make board interrupt by executing a GETPCBB command */
  653         DE_WCSR(DE_PCSR0, PCSR0_INTE);
  654         DE_WCSR(DE_PCSR2, 0);
  655         DE_WCSR(DE_PCSR3, 0);
  656         DE_WCSR(DE_PCSR0, PCSR0_INTE|CMD_GETPCBB);
  657         DELAY(50000);
  658 
  659         return 1;
  660 }
  661 
  662 void
  663 deshutdown(void *arg)
  664 {
  665         struct de_softc *sc = arg;
  666 
  667         DE_WCSR(DE_PCSR0, 0);
  668         DELAY(1000);
  669         DE_WCSR(DE_PCSR0, PCSR0_RSET);
  670         dewait(sc, "shutdown");
  671 }

Cache object: 82ff83920ebec24c5fc5c56094cd6a3c


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