root/dev/isa/if_ef_isapnp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ef_isapnp_match
  2. ef_isapnp_attach
  3. efstart
  4. efioctl
  5. efinit
  6. efreset
  7. efstop
  8. efcompletecmd
  9. efintr
  10. eftxstat
  11. efbusyeeprom
  12. efwatchdog
  13. efsetmulti
  14. efread
  15. efget
  16. ef_mii_writeb
  17. ef_mii_sync
  18. ef_miibus_readreg
  19. ef_miibus_writereg
  20. ef_ifmedia_upd
  21. ef_ifmedia_sts
  22. ef_miibus_statchg
  23. ef_tick

    1 /*      $OpenBSD: if_ef_isapnp.c,v 1.21 2006/03/25 22:41:44 djm Exp $   */
    2 
    3 /*
    4  * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   25  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   26  * POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include "bpfilter.h"
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/mbuf.h>
   34 #include <sys/socket.h>
   35 #include <sys/ioctl.h>
   36 #include <sys/errno.h>
   37 #include <sys/syslog.h>
   38 #include <sys/selinfo.h>
   39 #include <sys/device.h>
   40 #include <sys/queue.h>
   41 #include <sys/kernel.h>
   42 #include <sys/timeout.h>
   43 
   44 #include <net/if.h>
   45 #include <net/if_dl.h>
   46 #include <net/if_types.h>
   47 #include <net/netisr.h>
   48 #include <net/if_media.h>
   49 
   50 #ifdef INET
   51 #include <netinet/in.h>
   52 #include <netinet/in_systm.h>
   53 #include <netinet/in_var.h>
   54 #include <netinet/ip.h>
   55 #include <netinet/if_ether.h>
   56 #endif
   57 
   58 #if NBPFILTER > 0
   59 #include <net/bpf.h>
   60 #endif
   61 
   62 #include <machine/cpu.h>
   63 #include <machine/bus.h>
   64 #include <machine/intr.h>
   65 
   66 #include <dev/mii/mii.h>
   67 #include <dev/mii/miivar.h>
   68 #include <dev/isa/isavar.h>
   69 #include <dev/isa/isadmavar.h>
   70 #include <dev/ic/elink3reg.h>
   71 
   72 #undef EF_DEBUG
   73 
   74 struct ef_softc {
   75         struct device           sc_dv;
   76         bus_space_tag_t         sc_iot;
   77         bus_space_handle_t      sc_ioh;
   78         struct arpcom           sc_arpcom;
   79         struct mii_data         sc_mii;
   80         struct timeout          sc_tick_tmo;
   81         void *                  sc_ih;
   82         int                     sc_tx_start_thresh;
   83         int                     sc_tx_succ_ok;
   84         int                     sc_busmaster;
   85 };
   86 
   87 #define EF_W0_EEPROM_COMMAND    0x200a
   88 #define    EF_EEPROM_BUSY       (1 << 9)
   89 #define    EF_EEPROM_READ       (1 << 7)
   90 #define EF_W0_EEPROM_DATA       0x200c
   91 
   92 #define EF_W1_TX_PIO_WR_1       0x10
   93 #define EF_W1_RX_PIO_RR_1       0x10
   94 #define EF_W1_RX_ERRORS         0x14
   95 #define EF_W1_RX_STATUS         0x18
   96 #define EF_W1_TX_STATUS         0x1b
   97 #define EF_W1_FREE_TX           0x1c
   98 
   99 #define EF_W4_MEDIA             0x0a
  100 #define    EF_MEDIA_SQE         0x0008          /* sqe error for aui */
  101 #define    EF_MEDIA_TP          0x00c0          /* link/jabber, 10baseT */
  102 #define    EF_MEDIA_LNK         0x0080          /* linkbeat, 100baseTX/FX */
  103 #define    EF_MEDIA_LNKBEAT     0x0800
  104 
  105 /* Window 4: EP_W4_CTRLR_STATUS: mii manipulation */
  106 #define EF_MII_CLK              0x01            /* clock bit */
  107 #define EF_MII_DATA             0x02            /* data bit */
  108 #define EF_MII_DIR              0x04            /* direction */
  109 
  110 int ef_isapnp_match(struct device *, void *, void *);
  111 void ef_isapnp_attach(struct device *, struct device *, void *);
  112 
  113 void efstart(struct ifnet *);
  114 int efioctl(struct ifnet *, u_long, caddr_t);
  115 void efwatchdog(struct ifnet *);
  116 void efreset(struct ef_softc *);
  117 void efstop(struct ef_softc *);
  118 void efsetmulti(struct ef_softc *);
  119 int efbusyeeprom(struct ef_softc *);
  120 int efintr(void *);
  121 void efinit(struct ef_softc *);
  122 void efcompletecmd(struct ef_softc *, u_int, u_int);
  123 void eftxstat(struct ef_softc *);
  124 void efread(struct ef_softc *);
  125 struct mbuf *efget(struct ef_softc *, int totlen);
  126 
  127 void ef_miibus_writereg(struct device *, int, int, int);
  128 void ef_miibus_statchg(struct device *);
  129 int ef_miibus_readreg(struct device *, int, int);
  130 void ef_mii_writeb(struct ef_softc *, int);
  131 void ef_mii_sync(struct ef_softc *);
  132 int ef_ifmedia_upd(struct ifnet *);
  133 void ef_ifmedia_sts(struct ifnet *, struct ifmediareq *);
  134 void ef_tick(void *);
  135 
  136 struct cfdriver ef_cd = {
  137         NULL, "ef", DV_IFNET
  138 };
  139 
  140 struct cfattach ef_isapnp_ca = {
  141         sizeof(struct ef_softc), ef_isapnp_match, ef_isapnp_attach
  142 };
  143 
  144 int
  145 ef_isapnp_match(parent, match, aux)
  146         struct device *parent;
  147         void *match, *aux;
  148 {
  149         return (1);
  150 }
  151 
  152 void
  153 ef_isapnp_attach(parent, self, aux)
  154         struct device *parent, *self;
  155         void *aux;
  156 {
  157         struct ef_softc *sc = (void *)self;
  158         struct isa_attach_args *ia = aux;
  159         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  160         bus_space_tag_t iot;
  161         bus_space_handle_t ioh;
  162         int i;
  163         u_int16_t x;
  164         u_int32_t cfg;
  165 
  166         sc->sc_iot = iot = ia->ia_iot;
  167         sc->sc_ioh = ioh = ia->ipa_io[0].h;
  168 
  169         efcompletecmd(sc, EP_COMMAND, GLOBAL_RESET);
  170         DELAY(1500);
  171 
  172         for (i = 0; i < 3; i++) {
  173                 if (efbusyeeprom(sc))
  174                         return;
  175 
  176                 bus_space_write_2(iot, ioh, EF_W0_EEPROM_COMMAND,
  177                     EF_EEPROM_READ | i);
  178 
  179                 if (efbusyeeprom(sc))
  180                         return;
  181 
  182                 x = bus_space_read_2(iot, ioh, EF_W0_EEPROM_DATA);
  183 
  184                 sc->sc_arpcom.ac_enaddr[(i << 1)] = x >> 8;
  185                 sc->sc_arpcom.ac_enaddr[(i << 1) + 1] = x;
  186         }
  187 
  188         printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
  189 
  190         GO_WINDOW(3);
  191         cfg = bus_space_read_4(iot, ioh, EP_W3_INTERNAL_CONFIG);
  192         cfg &= ~(0x00f00000);
  193         cfg |= (0x06 << 20);
  194         bus_space_write_4(iot, ioh, EP_W3_INTERNAL_CONFIG, cfg);
  195 
  196         sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
  197             IPL_NET, efintr, sc, sc->sc_dv.dv_xname);
  198 
  199         if (ia->ia_drq != DRQUNK)
  200                 isadma_cascade(ia->ia_drq);
  201 
  202         timeout_set(&sc->sc_tick_tmo, ef_tick, sc);
  203 
  204         bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ);
  205         ifp->if_softc = sc;
  206         ifp->if_start = efstart;
  207         ifp->if_ioctl = efioctl;
  208         ifp->if_watchdog = efwatchdog;
  209         ifp->if_flags =
  210             IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
  211         IFQ_SET_READY(&ifp->if_snd);
  212 
  213         sc->sc_mii.mii_ifp = ifp;
  214         sc->sc_mii.mii_readreg = ef_miibus_readreg;
  215         sc->sc_mii.mii_writereg = ef_miibus_writereg;
  216         sc->sc_mii.mii_statchg = ef_miibus_statchg;
  217         ifmedia_init(&sc->sc_mii.mii_media, 0, ef_ifmedia_upd, ef_ifmedia_sts);
  218         mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
  219             0);
  220         if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
  221                 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
  222                 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
  223         } else
  224                 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
  225 
  226         if_attach(ifp);
  227         ether_ifattach(ifp);
  228 
  229         sc->sc_tx_start_thresh = 20;
  230 
  231         efcompletecmd(sc, EP_COMMAND, RX_RESET);
  232         efcompletecmd(sc, EP_COMMAND, TX_RESET);
  233 }
  234 
  235 void
  236 efstart(ifp)
  237         struct ifnet *ifp;
  238 {
  239         struct ef_softc *sc = ifp->if_softc;
  240         bus_space_tag_t iot = sc->sc_iot;
  241         bus_space_handle_t ioh = sc->sc_ioh;
  242         struct mbuf *m, *m0;
  243         int s, len, pad, i;
  244         int fillcnt = 0;
  245         u_int32_t filler = 0;
  246 
  247         if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
  248                 return;
  249 
  250 startagain:
  251         IFQ_POLL(&ifp->if_snd, m0);
  252         if (m0 == NULL)
  253                 return;
  254 
  255         if ((m0->m_flags & M_PKTHDR) == 0)
  256                 panic("efstart: no header mbuf");
  257         len = m0->m_pkthdr.len;
  258         pad = (4 - len) & 3;
  259 
  260         if (len + pad > ETHER_MAX_LEN) {
  261                 ifp->if_oerrors++;
  262                 IFQ_DEQUEUE(&ifp->if_snd, m0);
  263                 m_freem(m0);
  264                 goto startagain;
  265         }
  266 
  267         if (bus_space_read_2(iot, ioh, EF_W1_FREE_TX) < len + pad + 4) {
  268                 bus_space_write_2(iot, ioh, EP_COMMAND,
  269                     SET_TX_AVAIL_THRESH | ((len + pad) >> 2));
  270                 ifp->if_flags |= IFF_OACTIVE;
  271                 return;
  272         } else {
  273                 bus_space_write_2(iot, ioh, EP_COMMAND,
  274                     SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE);
  275         }
  276 
  277         bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH |
  278             ((len / 4 + sc->sc_tx_start_thresh)));
  279 
  280 #if NBPFILTER
  281         if (ifp->if_bpf)
  282                 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
  283 #endif
  284 
  285         IFQ_DEQUEUE(&ifp->if_snd, m0);
  286         if (m0 == NULL) /* XXX not needed */
  287                 return;
  288 
  289         s = splhigh();
  290 
  291         bus_space_write_4(iot, ioh, EF_W1_TX_PIO_WR_1, len);
  292         for (m = m0; m; ) {
  293                 if (fillcnt) {
  294                         while (m->m_len && fillcnt < 4) {
  295                                 fillcnt++;
  296                                 filler >>= 8;
  297                                 filler |= m->m_data[0] << 24;
  298                                 m->m_data++;
  299                                 m->m_len--;
  300                         }
  301                         if (fillcnt == 4) {
  302                                 bus_space_write_4(iot, ioh,
  303                                     EF_W1_TX_PIO_WR_1, filler);
  304                                 filler = 0;
  305                                 fillcnt = 0;
  306                         }
  307                 }
  308 
  309                 if (m->m_len & ~3)
  310                         bus_space_write_multi_4(iot, ioh,
  311                             EF_W1_TX_PIO_WR_1, (u_int32_t *)m->m_data,
  312                             m->m_len >> 2);
  313                 for (i = 0; i < (m->m_len & 3); i++) {
  314                         fillcnt++;
  315                         filler >>= 8;
  316                         filler |= m->m_data[(m->m_len & ~3) + i] << 24;
  317                 }
  318                 MFREE(m, m0);
  319                 m = m0;
  320         }
  321 
  322         if (fillcnt) {
  323                 bus_space_write_4(iot, ioh, EF_W1_TX_PIO_WR_1,
  324                     filler >> (32 - (8 * fillcnt)));
  325                 fillcnt = 0;
  326                 filler = 0;
  327         }
  328 
  329         splx(s);
  330 
  331         ifp->if_opackets++;
  332 
  333         goto startagain;
  334 }
  335 
  336 int
  337 efioctl(ifp, cmd, data)
  338         struct ifnet *ifp;
  339         u_long cmd;
  340         caddr_t data;
  341 {
  342         struct ef_softc *sc = ifp->if_softc;
  343         struct ifaddr *ifa = (struct ifaddr *)data;
  344         struct ifreq *ifr = (struct ifreq *)data;
  345         int s, error = 0;
  346 
  347         s = splnet();
  348 
  349         if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
  350                 splx(s);
  351                 return (error);
  352         }
  353 
  354         switch (cmd) {
  355         case SIOCSIFADDR:
  356                 ifp->if_flags |= IFF_UP;
  357                 switch (ifa->ifa_addr->sa_family) {
  358 #ifdef INET
  359                 case AF_INET:
  360                         efinit(sc);
  361                         arp_ifinit(&sc->sc_arpcom, ifa);
  362                         break;
  363 #endif
  364                 default:
  365                         efinit(sc);
  366                         break;
  367                 }
  368                 break;
  369         case SIOCSIFMEDIA:
  370         case SIOCGIFMEDIA:
  371                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  372                 break;
  373         case SIOCSIFFLAGS:
  374                 if ((ifp->if_flags & IFF_UP) == 0 &&
  375                     (ifp->if_flags & IFF_RUNNING) != 0) {
  376                         efstop(sc);
  377                         ifp->if_flags &= ~IFF_RUNNING;
  378                 } else if ((ifp->if_flags & IFF_UP) != 0 &&
  379                            (ifp->if_flags & IFF_RUNNING) == 0) {
  380                         efinit(sc);
  381                 }
  382                 efsetmulti(sc);
  383                 break;
  384 
  385         case SIOCADDMULTI:
  386         case SIOCDELMULTI:
  387                 error = (cmd == SIOCADDMULTI) ?
  388                     ether_addmulti(ifr, &sc->sc_arpcom) :
  389                     ether_delmulti(ifr, &sc->sc_arpcom);
  390 
  391                 if (error == ENETRESET) {
  392                         if (ifp->if_flags & IFF_RUNNING)
  393                                 efreset(sc);
  394                         error = 0;
  395                 }
  396                 efsetmulti(sc);
  397                 break;
  398         default:
  399                 error = EINVAL;
  400                 break;
  401         }
  402 
  403         splx(s);
  404         return (error);
  405 }
  406 
  407 void
  408 efinit(sc)
  409         struct ef_softc *sc;
  410 {
  411         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  412         bus_space_tag_t iot = sc->sc_iot;
  413         bus_space_handle_t ioh = sc->sc_ioh;
  414         int i, s;
  415 
  416         s = splnet();
  417 
  418         efstop(sc);
  419 
  420         while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
  421                 ;
  422 
  423         GO_WINDOW(2);
  424         for (i = 0; i < 6; i++)
  425                 bus_space_write_1(iot, ioh, EP_W2_ADDR_0 + i,
  426                     sc->sc_arpcom.ac_enaddr[i]);
  427         for (i = 0; i < 3; i += 2)
  428                 bus_space_write_2(iot, ioh, EP_W2_RECVMASK_0 + (i * 2), 0);
  429 
  430         efcompletecmd(sc, EP_COMMAND, RX_RESET);
  431         efcompletecmd(sc, EP_COMMAND, TX_RESET);
  432 
  433         bus_space_write_2(iot, ioh, EP_COMMAND,
  434             SET_TX_AVAIL_THRESH | (ETHER_MAX_DIX_LEN >> 2));
  435 
  436         efsetmulti(sc);
  437 
  438         bus_space_write_2(iot, ioh, EP_COMMAND, STATUS_ENABLE | 0);
  439 
  440         GO_WINDOW(6);
  441         for (i = 0; i < 10; i++)
  442                 (void)bus_space_read_1(iot, ioh, i);
  443         (void)bus_space_read_2(iot, ioh, 10);
  444         (void)bus_space_read_2(iot, ioh, 12);
  445         GO_WINDOW(4);
  446         (void)bus_space_read_1(iot, ioh, 12);
  447         bus_space_write_2(iot, ioh, EP_W4_NET_DIAG, 0x0040);
  448 
  449         GO_WINDOW(7);
  450 
  451         efsetmulti(sc);
  452 
  453         bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE);
  454         bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
  455 
  456         bus_space_write_2(iot, ioh, EP_COMMAND, STATUS_ENABLE |
  457             S_CARD_FAILURE | S_INT_RQD | S_UPD_STATS | S_TX_COMPLETE |
  458             S_TX_AVAIL | S_RX_COMPLETE |
  459             (sc->sc_busmaster ? S_DMA_DONE : 0));
  460         bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR |
  461             S_INTR_LATCH | S_TX_AVAIL | S_RX_EARLY | S_INT_RQD);
  462         bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK |
  463             S_INTR_LATCH | S_TX_AVAIL | S_RX_COMPLETE | S_UPD_STATS |
  464             (sc->sc_busmaster ? S_DMA_DONE : 0) | S_UP_COMPLETE |
  465             S_DOWN_COMPLETE | S_CARD_FAILURE | S_TX_COMPLETE);
  466 
  467         mii_mediachg(&sc->sc_mii);
  468 
  469         ifp->if_flags |= IFF_RUNNING;
  470         ifp->if_flags &= ~IFF_OACTIVE;
  471 
  472         splx(s);
  473 
  474         timeout_add(&sc->sc_tick_tmo, hz);
  475 
  476         efstart(ifp);
  477 }
  478 
  479 void
  480 efreset(sc)
  481         struct ef_softc *sc;
  482 {
  483         int s;
  484 
  485         s = splnet();
  486         efstop(sc);
  487         efinit(sc);
  488         splx(s);
  489 }
  490 
  491 void
  492 efstop(sc)
  493         struct ef_softc *sc;
  494 {
  495         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  496         bus_space_tag_t iot = sc->sc_iot;
  497         bus_space_handle_t ioh = sc->sc_ioh;
  498 
  499         ifp->if_timer = 0;
  500         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
  501 
  502         timeout_del(&sc->sc_tick_tmo);
  503 
  504         bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISABLE);
  505         efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
  506 
  507         bus_space_write_2(iot, ioh, EP_COMMAND, TX_DISABLE);
  508         bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
  509 
  510         efcompletecmd(sc, EP_COMMAND, RX_RESET);
  511         efcompletecmd(sc, EP_COMMAND, TX_RESET);
  512 
  513         bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
  514         bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK);
  515         bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK);
  516         bus_space_write_2(iot, ioh, EP_COMMAND, SET_RX_FILTER);
  517 }
  518 
  519 void
  520 efcompletecmd(sc, cmd, arg)
  521         struct ef_softc *sc;
  522         u_int cmd, arg;
  523 {
  524         bus_space_tag_t iot = sc->sc_iot;
  525         bus_space_handle_t ioh = sc->sc_ioh;
  526 
  527         bus_space_write_2(iot, ioh, cmd, arg);
  528         while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
  529                 ;
  530 }
  531 
  532 int
  533 efintr(vsc)
  534         void *vsc;
  535 {
  536         struct ef_softc *sc = vsc;
  537         bus_space_tag_t iot = sc->sc_iot;
  538         bus_space_handle_t ioh = sc->sc_ioh;
  539         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  540         u_int16_t status;
  541         int r = 0;
  542 
  543         status = bus_space_read_2(iot, ioh, EP_STATUS);
  544 
  545         do {
  546                 if (status & S_RX_COMPLETE) {
  547                         r = 1;
  548                         bus_space_write_2(iot, ioh, EP_STATUS, C_RX_COMPLETE);
  549                         efread(sc);
  550                 }
  551                 if (status & S_TX_AVAIL) {
  552                         bus_space_write_2(iot, ioh, EP_STATUS, C_TX_AVAIL);
  553                         r = 1;
  554                         sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
  555                         efstart(&sc->sc_arpcom.ac_if);
  556                 }
  557                 if (status & S_CARD_FAILURE) {
  558                         r = 1;
  559                         efreset(sc);
  560                         printf("%s: adapter failure (%x)\n",
  561                            sc->sc_dv.dv_xname, status);
  562                         bus_space_write_2(iot, ioh, EP_COMMAND,
  563                                           C_CARD_FAILURE);
  564                         return (1);
  565                 }
  566                 if (status & S_TX_COMPLETE) {
  567                         r = 1;
  568                         eftxstat(sc);
  569                         efstart(ifp);
  570                 }
  571                 bus_space_write_2(iot, ioh, EP_COMMAND,
  572                     C_INTR_LATCH | C_INT_RQD);
  573         } while ((status = bus_space_read_2(iot, ioh, EP_STATUS)) &
  574             (S_INT_RQD | S_RX_COMPLETE));
  575 
  576         return (r);
  577 }
  578 
  579 void
  580 eftxstat(sc)
  581         struct ef_softc *sc;
  582 {
  583         bus_space_tag_t iot = sc->sc_iot;
  584         bus_space_handle_t ioh = sc->sc_ioh;
  585         int i;
  586 
  587         while ((i = bus_space_read_1(iot, ioh, EF_W1_TX_STATUS)) &
  588            TXS_COMPLETE) {
  589                 bus_space_write_1(iot, ioh, EF_W1_TX_STATUS, 0);
  590 
  591                 if (i & TXS_JABBER) {
  592                         sc->sc_arpcom.ac_if.if_oerrors++;
  593 #ifdef EF_DEBUG
  594                         if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
  595                                 printf("%s: jabber (%x)\n",
  596                                     sc->sc_dv.dv_xname, i);
  597 #endif
  598                         efreset(sc);
  599                 }
  600                 else if (i & TXS_UNDERRUN) {
  601                         sc->sc_arpcom.ac_if.if_oerrors++;
  602 #ifdef EF_DEBUG
  603                         if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
  604                                 printf("%s: fifo underrun (%x) @%d\n",
  605                                     sc->sc_dv.dv_xname, i,
  606                                     sc->sc_tx_start_thresh);
  607 #endif
  608                         if (sc->sc_tx_succ_ok < 100)
  609                                 sc->sc_tx_start_thresh = min(ETHER_MAX_LEN,
  610                                     sc->sc_tx_start_thresh + 20);
  611                         sc->sc_tx_succ_ok = 0;
  612                         efreset(sc);
  613                 }
  614                 else if (i & TXS_MAX_COLLISION) {
  615                         sc->sc_arpcom.ac_if.if_collisions++;
  616                         bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
  617                         sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
  618                 }
  619                 else
  620                         sc->sc_tx_succ_ok = (sc->sc_tx_succ_ok + 1) & 127;
  621         }
  622 }
  623 
  624 int
  625 efbusyeeprom(sc)
  626         struct ef_softc *sc;
  627 {
  628         int i = 100, j;
  629 
  630         while (i--) {
  631                 j = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
  632                                      EF_W0_EEPROM_COMMAND);
  633                 if (j & EF_EEPROM_BUSY)
  634                         delay(100);
  635                 else
  636                         break;
  637         }
  638         if (i == 0) {
  639                 printf("%s: eeprom failed to come ready\n",
  640                    sc->sc_dv.dv_xname);
  641                 return (1);
  642         }
  643 
  644         return (0);
  645 }
  646 
  647 void
  648 efwatchdog(ifp)
  649         struct ifnet *ifp;
  650 {
  651         struct ef_softc *sc = ifp->if_softc;
  652 
  653         printf("%s: device timeout\n", sc->sc_dv.dv_xname);
  654         sc->sc_arpcom.ac_if.if_oerrors++;
  655         efreset(sc);
  656 }
  657 
  658 void
  659 efsetmulti(sc)
  660         struct ef_softc *sc;
  661 {
  662         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  663         struct arpcom *ac = &sc->sc_arpcom;
  664         bus_space_tag_t iot = sc->sc_iot;
  665         bus_space_handle_t ioh = sc->sc_ioh;
  666         struct ether_multi *enm;
  667         struct ether_multistep step;
  668         u_int16_t cmd = SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST;
  669         int mcnt = 0;
  670 
  671         ETHER_FIRST_MULTI(step, ac, enm);
  672         while (enm != NULL) {
  673                 mcnt++;
  674                 ETHER_NEXT_MULTI(step, enm);
  675         }
  676         if (mcnt || ifp->if_flags & IFF_ALLMULTI)
  677                 cmd |= FIL_MULTICAST;
  678 
  679         if (ifp->if_flags & IFF_PROMISC)
  680                 cmd |= FIL_PROMISC;
  681 
  682         bus_space_write_2(iot, ioh, EP_COMMAND, cmd);
  683 }
  684 
  685 void
  686 efread(sc)
  687         struct ef_softc *sc;
  688 {
  689         bus_space_tag_t iot = sc->sc_iot;
  690         bus_space_handle_t ioh = sc->sc_ioh;
  691         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  692         struct mbuf *m;
  693         int len;
  694 
  695         len = bus_space_read_2(iot, ioh, EF_W1_RX_STATUS);
  696 
  697 #ifdef EF_DEBUG
  698         if (ifp->if_flags & IFF_DEBUG) {
  699                 int err = len & ERR_MASK;
  700                 char *s = NULL;
  701 
  702                 if (len & ERR_INCOMPLETE)
  703                         s = "incomplete packet";
  704                 else if (err == ERR_OVERRUN)
  705                         s = "packet overrun";
  706                 else if (err == ERR_RUNT)
  707                         s = "runt packet";
  708                 else if (err == ERR_ALIGNMENT)
  709                         s = "bad alignment";
  710                 else if (err == ERR_CRC)
  711                         s = "bad crc";
  712                 else if (err == ERR_OVERSIZE)
  713                         s = "oversized packet";
  714                 else if (err == ERR_DRIBBLE)
  715                         s = "dribble bits";
  716 
  717                 if (s)
  718                         printf("%s: %s\n", sc->sc_dv.dv_xname, s);
  719         }
  720 #endif
  721 
  722         if (len & ERR_INCOMPLETE)
  723                 return;
  724 
  725         if (len & ERR_RX) {
  726                 ifp->if_ierrors++;
  727                 efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
  728                 return;
  729         }
  730 
  731         len &= RX_BYTES_MASK;
  732         m = efget(sc, len);
  733         if (m == NULL) {
  734                 ifp->if_ierrors++;
  735                 efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
  736                 return;
  737         }
  738 
  739         ifp->if_ipackets++;
  740 
  741 #if NBPFILTER > 0
  742         if (ifp->if_bpf)
  743                 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
  744 #endif
  745 
  746         ether_input_mbuf(ifp, m);
  747 }
  748 
  749 struct mbuf *
  750 efget(sc, totlen)
  751         struct ef_softc *sc;
  752         int totlen;
  753 {
  754         bus_space_tag_t iot = sc->sc_iot;
  755         bus_space_handle_t ioh = sc->sc_ioh;
  756         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  757         struct mbuf *top, **mp, *m;
  758         int len, pad, s;
  759 
  760         MGETHDR(m, M_DONTWAIT, MT_DATA);
  761         if (m == NULL)
  762                 return (NULL);
  763         m->m_pkthdr.rcvif = ifp;
  764         m->m_pkthdr.len = totlen;
  765         pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
  766         m->m_data += pad;
  767         len = MHLEN -pad;
  768         top = 0;
  769         mp = &top;
  770 
  771         s = splhigh();
  772 
  773         while (totlen > 0) {
  774                 if (top) {
  775                         MGET(m, M_DONTWAIT, MT_DATA);
  776                         if (m == NULL) {
  777                                 m_freem(top);
  778                                 splx(s);
  779                                 return (NULL);
  780                         }
  781                         len = MLEN;
  782                 }
  783                 if (top && totlen >= MINCLSIZE) {
  784                         MCLGET(m, M_DONTWAIT);
  785                         if (m->m_flags & M_EXT)
  786                                 len = MCLBYTES;
  787                 }
  788                 len = min(totlen, len);
  789                 if (len > 1) {
  790                         len &= ~1;
  791                         bus_space_read_raw_multi_2(iot, ioh,
  792                             EF_W1_RX_PIO_RR_1, mtod(m, u_int8_t *),
  793                             len);
  794                 } else
  795                         *(mtod(m, u_int8_t *)) =
  796                             bus_space_read_1(iot, ioh, EF_W1_RX_PIO_RR_1);
  797 
  798                 m->m_len = len;
  799                 totlen -= len;
  800                 *mp = m;
  801                 mp = &m->m_next;
  802         }
  803 
  804         efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
  805 
  806         splx(s);
  807 
  808         return (top);
  809 }
  810 
  811 #define MII_SET(sc, x) \
  812         bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS, \
  813             bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS) \
  814             | (x))
  815 
  816 #define MII_CLR(sc, x) \
  817         bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS, \
  818             bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS) \
  819             & (~(x)))
  820 
  821 void
  822 ef_mii_writeb(sc, b)
  823         struct ef_softc *sc;
  824         int b;
  825 {
  826         MII_CLR(sc, EF_MII_CLK);
  827 
  828         if (b)
  829                 MII_SET(sc, EF_MII_DATA);
  830         else
  831                 MII_CLR(sc, EF_MII_DATA);
  832 
  833         MII_CLR(sc, EF_MII_CLK);
  834         DELAY(1);
  835         MII_SET(sc, EF_MII_CLK);
  836         DELAY(1);
  837 }
  838 
  839 void
  840 ef_mii_sync(sc)
  841         struct ef_softc *sc;
  842 {
  843         int i;
  844 
  845         for (i = 0; i < 32; i++)
  846                 ef_mii_writeb(sc, 1);
  847 }
  848 
  849 int
  850 ef_miibus_readreg(dev, phy, reg)
  851         struct device *dev;
  852         int phy, reg;
  853 {
  854         struct ef_softc *sc = (struct ef_softc *)dev;
  855         int i, ack, s, val = 0;
  856 
  857         s = splnet();
  858 
  859         GO_WINDOW(4);
  860         bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS, 0);
  861 
  862         /* Turn on xmit */
  863         MII_SET(sc, EF_MII_DIR);
  864         MII_CLR(sc, EF_MII_CLK);
  865 
  866         ef_mii_sync(sc);
  867 
  868         /* Transmit start sequence */
  869         ef_mii_writeb(sc, 0);
  870         ef_mii_writeb(sc, 1);
  871 
  872         /* Transmit read sequence */
  873         ef_mii_writeb(sc, 1);
  874         ef_mii_writeb(sc, 0);
  875 
  876         /* Transmit phy addr */
  877         for (i = 0x10; i; i >>= 1)
  878                 ef_mii_writeb(sc, (phy & i) ? 1 : 0);
  879 
  880         /* Transmit reg addr */
  881         for (i = 0x10; i; i >>= 1)
  882                 ef_mii_writeb(sc, (reg & i) ? 1 : 0);
  883 
  884         /* First cycle of turnaround */
  885         MII_CLR(sc, EF_MII_CLK | EF_MII_DATA);
  886         DELAY(1);
  887         MII_SET(sc, EF_MII_CLK);
  888         DELAY(1);
  889 
  890         /* Turn off xmit */
  891         MII_CLR(sc, EF_MII_DIR);
  892 
  893         /* Second cycle of turnaround */
  894         MII_CLR(sc, EF_MII_CLK);
  895         DELAY(1);
  896         MII_SET(sc, EF_MII_CLK);
  897         DELAY(1);
  898         ack = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS) &
  899             EF_MII_DATA;
  900 
  901         /* Read 16bit data */
  902         for (i = 0x8000; i; i >>= 1) {
  903                 MII_CLR(sc, EF_MII_CLK);
  904                 DELAY(1);
  905                 if (bus_space_read_2(sc->sc_iot, sc->sc_ioh,
  906                                      EP_W4_CTRLR_STATUS) & EF_MII_DATA)
  907                         val |= i;
  908                 MII_SET(sc, EF_MII_CLK);
  909                 DELAY(1);
  910         }
  911 
  912         MII_CLR(sc, EF_MII_CLK);
  913         DELAY(1);
  914         MII_SET(sc, EF_MII_CLK);
  915         DELAY(1);
  916 
  917         splx(s);
  918 
  919         return (val);
  920 }
  921 
  922 void
  923 ef_miibus_writereg(dev, phy, reg, val)
  924         struct device *dev;
  925         int phy, reg, val;
  926 {
  927         struct ef_softc *sc = (struct ef_softc *)dev;
  928         int s, i;
  929 
  930         s = splnet();
  931 
  932         GO_WINDOW(4);
  933         bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS, 0);
  934 
  935         /* Turn on xmit */
  936         MII_SET(sc, EF_MII_DIR);
  937 
  938         ef_mii_sync(sc);
  939 
  940         ef_mii_writeb(sc, 0);
  941         ef_mii_writeb(sc, 1);
  942         ef_mii_writeb(sc, 0);
  943         ef_mii_writeb(sc, 1);
  944 
  945         for (i = 0x10; i; i >>= 1)
  946                 ef_mii_writeb(sc, (phy & i) ? 1 : 0);
  947 
  948         for (i = 0x10; i; i >>= 1)
  949                 ef_mii_writeb(sc, (reg & i) ? 1 : 0);
  950 
  951         ef_mii_writeb(sc, 1);
  952         ef_mii_writeb(sc, 0);
  953 
  954         for (i = 0x8000; i; i >>= 1)
  955                 ef_mii_writeb(sc, (val & i) ? 1 : 0);
  956 
  957         splx(s);
  958 }
  959 
  960 int
  961 ef_ifmedia_upd(ifp)
  962         struct ifnet *ifp;
  963 {
  964         struct ef_softc *sc = ifp->if_softc;
  965 
  966         mii_mediachg(&sc->sc_mii);
  967         return (0);
  968 }
  969 
  970 void
  971 ef_ifmedia_sts(ifp, ifmr)
  972         struct ifnet *ifp;
  973         struct ifmediareq *ifmr;
  974 {
  975         struct ef_softc *sc = ifp->if_softc;
  976 
  977         mii_pollstat(&sc->sc_mii);
  978         ifmr->ifm_status = sc->sc_mii.mii_media_status;
  979         ifmr->ifm_active = sc->sc_mii.mii_media_active;
  980 }
  981 
  982 void
  983 ef_miibus_statchg(self)
  984         struct device *self;
  985 {
  986         struct ef_softc *sc = (struct ef_softc *)self;
  987         int s;
  988 
  989         s = splnet();
  990         GO_WINDOW(3);
  991         /* Set duplex bit appropriately */
  992         if ((sc->sc_mii.mii_media_active & IFM_GMASK) == IFM_FDX)
  993                 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
  994                     EP_W3_MAC_CONTROL, 0x20);
  995         else
  996                 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
  997                     EP_W3_MAC_CONTROL, 0x00);
  998         GO_WINDOW(7);
  999         splx(s);
 1000 }
 1001 
 1002 void
 1003 ef_tick(v)
 1004         void *v;
 1005 {
 1006         struct ef_softc *sc = v;
 1007         int s;
 1008 
 1009         s = splnet();
 1010         mii_tick(&sc->sc_mii);
 1011         splx(s);
 1012         timeout_add(&sc->sc_tick_tmo, hz);
 1013 }

/* [<][>][^][v][top][bottom][index][help] */