This source file includes following definitions.
- wb_eeprom_putbyte
- wb_eeprom_getword
- wb_read_eeprom
- wb_mii_sync
- wb_mii_send
- wb_mii_readreg
- wb_mii_writereg
- wb_miibus_readreg
- wb_miibus_writereg
- wb_miibus_statchg
- wb_setmulti
- wb_setcfg
- wb_reset
- wb_fixmedia
- wb_probe
- wb_attach
- wb_list_tx_init
- wb_list_rx_init
- wb_bfree
- wb_newbuf
- wb_rxeof
- wb_rxeoc
- wb_txeof
- wb_txeoc
- wb_intr
- wb_tick
- wb_encap
- wb_start
- wb_init
- wb_ifmedia_upd
- wb_ifmedia_sts
- wb_ioctl
- wb_watchdog
- wb_stop
- wb_shutdown
    1 
    2 
    3 
    4 
    5 
    6 
    7 
    8 
    9 
   10 
   11 
   12 
   13 
   14 
   15 
   16 
   17 
   18 
   19 
   20 
   21 
   22 
   23 
   24 
   25 
   26 
   27 
   28 
   29 
   30 
   31 
   32 
   33 
   34 
   35 
   36 
   37 
   38 
   39 
   40 
   41 
   42 
   43 
   44 
   45 
   46 
   47 
   48 
   49 
   50 
   51 
   52 
   53 
   54 
   55 
   56 
   57 
   58 
   59 
   60 
   61 
   62 
   63 
   64 
   65 
   66 
   67 
   68 
   69 
   70 
   71 
   72 
   73 
   74 
   75 
   76 
   77 
   78 
   79 
   80 
   81 
   82 
   83 
   84 
   85 
   86 
   87 
   88 #include "bpfilter.h"
   89 
   90 #include <sys/param.h>
   91 #include <sys/systm.h>
   92 #include <sys/sockio.h>
   93 #include <sys/mbuf.h>
   94 #include <sys/malloc.h>
   95 #include <sys/kernel.h>
   96 #include <sys/socket.h>
   97 #include <sys/device.h>
   98 #include <sys/queue.h>
   99 #include <sys/timeout.h>
  100 
  101 #include <net/if.h>
  102 #include <net/if_dl.h>
  103 #include <net/if_types.h>
  104 
  105 #ifdef INET
  106 #include <netinet/in.h>
  107 #include <netinet/in_systm.h>
  108 #include <netinet/in_var.h>
  109 #include <netinet/ip.h>
  110 #include <netinet/if_ether.h>
  111 #endif
  112 
  113 #include <net/if_media.h>
  114 
  115 #if NBPFILTER > 0
  116 #include <net/bpf.h>
  117 #endif
  118 
  119 #include <uvm/uvm_extern.h>             
  120 #define VTOPHYS(v)      vtophys((vaddr_t)(v))
  121 
  122 #include <dev/mii/mii.h>
  123 #include <dev/mii/miivar.h>
  124 #include <dev/pci/pcireg.h>
  125 #include <dev/pci/pcivar.h>
  126 #include <dev/pci/pcidevs.h>
  127 
  128 #define WB_USEIOSPACE
  129 
  130 
  131 
  132 #include <dev/pci/if_wbreg.h>
  133 
  134 int wb_probe(struct device *, void *, void *);
  135 void wb_attach(struct device *, struct device *, void *);
  136 
  137 void wb_bfree(caddr_t, u_int, void *);
  138 int wb_newbuf(struct wb_softc *, struct wb_chain_onefrag *,
  139     struct mbuf *);
  140 int wb_encap(struct wb_softc *, struct wb_chain *,
  141     struct mbuf *);
  142 
  143 void wb_rxeof(struct wb_softc *);
  144 void wb_rxeoc(struct wb_softc *);
  145 void wb_txeof(struct wb_softc *);
  146 void wb_txeoc(struct wb_softc *);
  147 int wb_intr(void *);
  148 void wb_tick(void *);
  149 void wb_start(struct ifnet *);
  150 int wb_ioctl(struct ifnet *, u_long, caddr_t);
  151 void wb_init(void *);
  152 void wb_stop(struct wb_softc *);
  153 void wb_watchdog(struct ifnet *);
  154 void wb_shutdown(void *);
  155 int wb_ifmedia_upd(struct ifnet *);
  156 void wb_ifmedia_sts(struct ifnet *, struct ifmediareq *);
  157 
  158 void wb_eeprom_putbyte(struct wb_softc *, int);
  159 void wb_eeprom_getword(struct wb_softc *, int, u_int16_t *);
  160 void wb_read_eeprom(struct wb_softc *, caddr_t, int, int, int);
  161 void wb_mii_sync(struct wb_softc *);
  162 void wb_mii_send(struct wb_softc *, u_int32_t, int);
  163 int wb_mii_readreg(struct wb_softc *, struct wb_mii_frame *);
  164 int wb_mii_writereg(struct wb_softc *, struct wb_mii_frame *);
  165 
  166 void wb_setcfg(struct wb_softc *, u_int32_t);
  167 u_int8_t wb_calchash(caddr_t);
  168 void wb_setmulti(struct wb_softc *);
  169 void wb_reset(struct wb_softc *);
  170 void wb_fixmedia(struct wb_softc *);
  171 int wb_list_rx_init(struct wb_softc *);
  172 int wb_list_tx_init(struct wb_softc *);
  173 
  174 int wb_miibus_readreg(struct device *, int, int);
  175 void wb_miibus_writereg(struct device *, int, int, int);
  176 void wb_miibus_statchg(struct device *);
  177 
  178 #define WB_SETBIT(sc, reg, x)                           \
  179         CSR_WRITE_4(sc, reg,                            \
  180                 CSR_READ_4(sc, reg) | x)
  181 
  182 #define WB_CLRBIT(sc, reg, x)                           \
  183         CSR_WRITE_4(sc, reg,                            \
  184                 CSR_READ_4(sc, reg) & ~x)
  185 
  186 #define SIO_SET(x)                                      \
  187         CSR_WRITE_4(sc, WB_SIO,                         \
  188                 CSR_READ_4(sc, WB_SIO) | x)
  189 
  190 #define SIO_CLR(x)                                      \
  191         CSR_WRITE_4(sc, WB_SIO,                         \
  192                 CSR_READ_4(sc, WB_SIO) & ~x)
  193 
  194 
  195 
  196 
  197 void wb_eeprom_putbyte(sc, addr)
  198         struct wb_softc         *sc;
  199         int                     addr;
  200 {
  201         int                     d, i;
  202 
  203         d = addr | WB_EECMD_READ;
  204 
  205         
  206 
  207 
  208         for (i = 0x400; i; i >>= 1) {
  209                 if (d & i) {
  210                         SIO_SET(WB_SIO_EE_DATAIN);
  211                 } else {
  212                         SIO_CLR(WB_SIO_EE_DATAIN);
  213                 }
  214                 DELAY(100);
  215                 SIO_SET(WB_SIO_EE_CLK);
  216                 DELAY(150);
  217                 SIO_CLR(WB_SIO_EE_CLK);
  218                 DELAY(100);
  219         }
  220 
  221         return;
  222 }
  223 
  224 
  225 
  226 
  227 void wb_eeprom_getword(sc, addr, dest)
  228         struct wb_softc         *sc;
  229         int                     addr;
  230         u_int16_t               *dest;
  231 {
  232         int                     i;
  233         u_int16_t               word = 0;
  234 
  235         
  236         CSR_WRITE_4(sc, WB_SIO, WB_SIO_EESEL|WB_SIO_EE_CS);
  237 
  238         
  239 
  240 
  241         wb_eeprom_putbyte(sc, addr);
  242 
  243         CSR_WRITE_4(sc, WB_SIO, WB_SIO_EESEL|WB_SIO_EE_CS);
  244 
  245         
  246 
  247 
  248         for (i = 0x8000; i; i >>= 1) {
  249                 SIO_SET(WB_SIO_EE_CLK);
  250                 DELAY(100);
  251                 if (CSR_READ_4(sc, WB_SIO) & WB_SIO_EE_DATAOUT)
  252                         word |= i;
  253                 SIO_CLR(WB_SIO_EE_CLK);
  254                 DELAY(100);
  255         }
  256 
  257         
  258         CSR_WRITE_4(sc, WB_SIO, 0);
  259 
  260         *dest = word;
  261 
  262         return;
  263 }
  264 
  265 
  266 
  267 
  268 void wb_read_eeprom(sc, dest, off, cnt, swap)
  269         struct wb_softc         *sc;
  270         caddr_t                 dest;
  271         int                     off;
  272         int                     cnt;
  273         int                     swap;
  274 {
  275         int                     i;
  276         u_int16_t               word = 0, *ptr;
  277 
  278         for (i = 0; i < cnt; i++) {
  279                 wb_eeprom_getword(sc, off + i, &word);
  280                 ptr = (u_int16_t *)(dest + (i * 2));
  281                 if (swap)
  282                         *ptr = ntohs(word);
  283                 else
  284                         *ptr = word;
  285         }
  286 
  287         return;
  288 }
  289 
  290 
  291 
  292 
  293 void wb_mii_sync(sc)
  294         struct wb_softc         *sc;
  295 {
  296         int                     i;
  297 
  298         SIO_SET(WB_SIO_MII_DIR|WB_SIO_MII_DATAIN);
  299 
  300         for (i = 0; i < 32; i++) {
  301                 SIO_SET(WB_SIO_MII_CLK);
  302                 DELAY(1);
  303                 SIO_CLR(WB_SIO_MII_CLK);
  304                 DELAY(1);
  305         }
  306 
  307         return;
  308 }
  309 
  310 
  311 
  312 
  313 void wb_mii_send(sc, bits, cnt)
  314         struct wb_softc         *sc;
  315         u_int32_t               bits;
  316         int                     cnt;
  317 {
  318         int                     i;
  319 
  320         SIO_CLR(WB_SIO_MII_CLK);
  321 
  322         for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
  323                 if (bits & i) {
  324                         SIO_SET(WB_SIO_MII_DATAIN);
  325                 } else {
  326                         SIO_CLR(WB_SIO_MII_DATAIN);
  327                 }
  328                 DELAY(1);
  329                 SIO_CLR(WB_SIO_MII_CLK);
  330                 DELAY(1);
  331                 SIO_SET(WB_SIO_MII_CLK);
  332         }
  333 }
  334 
  335 
  336 
  337 
  338 int wb_mii_readreg(sc, frame)
  339         struct wb_softc         *sc;
  340         struct wb_mii_frame     *frame;
  341         
  342 {
  343         int                     i, ack, s;
  344 
  345         s = splnet();
  346 
  347         
  348 
  349 
  350         frame->mii_stdelim = WB_MII_STARTDELIM;
  351         frame->mii_opcode = WB_MII_READOP;
  352         frame->mii_turnaround = 0;
  353         frame->mii_data = 0;
  354         
  355         CSR_WRITE_4(sc, WB_SIO, 0);
  356 
  357         
  358 
  359 
  360         SIO_SET(WB_SIO_MII_DIR);
  361 
  362         wb_mii_sync(sc);
  363 
  364         
  365 
  366 
  367         wb_mii_send(sc, frame->mii_stdelim, 2);
  368         wb_mii_send(sc, frame->mii_opcode, 2);
  369         wb_mii_send(sc, frame->mii_phyaddr, 5);
  370         wb_mii_send(sc, frame->mii_regaddr, 5);
  371 
  372         
  373         SIO_CLR((WB_SIO_MII_CLK|WB_SIO_MII_DATAIN));
  374         DELAY(1);
  375         SIO_SET(WB_SIO_MII_CLK);
  376         DELAY(1);
  377 
  378         
  379         SIO_CLR(WB_SIO_MII_DIR);
  380         
  381         SIO_CLR(WB_SIO_MII_CLK);
  382         DELAY(1);
  383         ack = CSR_READ_4(sc, WB_SIO) & WB_SIO_MII_DATAOUT;
  384         SIO_SET(WB_SIO_MII_CLK);
  385         DELAY(1);
  386         SIO_CLR(WB_SIO_MII_CLK);
  387         DELAY(1);
  388         SIO_SET(WB_SIO_MII_CLK);
  389         DELAY(1);
  390 
  391         
  392 
  393 
  394 
  395         if (ack) {
  396                 for(i = 0; i < 16; i++) {
  397                         SIO_CLR(WB_SIO_MII_CLK);
  398                         DELAY(1);
  399                         SIO_SET(WB_SIO_MII_CLK);
  400                         DELAY(1);
  401                 }
  402                 goto fail;
  403         }
  404 
  405         for (i = 0x8000; i; i >>= 1) {
  406                 SIO_CLR(WB_SIO_MII_CLK);
  407                 DELAY(1);
  408                 if (!ack) {
  409                         if (CSR_READ_4(sc, WB_SIO) & WB_SIO_MII_DATAOUT)
  410                                 frame->mii_data |= i;
  411                         DELAY(1);
  412                 }
  413                 SIO_SET(WB_SIO_MII_CLK);
  414                 DELAY(1);
  415         }
  416 
  417 fail:
  418 
  419         SIO_CLR(WB_SIO_MII_CLK);
  420         DELAY(1);
  421         SIO_SET(WB_SIO_MII_CLK);
  422         DELAY(1);
  423 
  424         splx(s);
  425 
  426         if (ack)
  427                 return(1);
  428         return(0);
  429 }
  430 
  431 
  432 
  433 
  434 int wb_mii_writereg(sc, frame)
  435         struct wb_softc         *sc;
  436         struct wb_mii_frame     *frame;
  437         
  438 {
  439         int                     s;
  440 
  441         s = splnet();
  442         
  443 
  444 
  445 
  446         frame->mii_stdelim = WB_MII_STARTDELIM;
  447         frame->mii_opcode = WB_MII_WRITEOP;
  448         frame->mii_turnaround = WB_MII_TURNAROUND;
  449         
  450         
  451 
  452 
  453         SIO_SET(WB_SIO_MII_DIR);
  454 
  455         wb_mii_sync(sc);
  456 
  457         wb_mii_send(sc, frame->mii_stdelim, 2);
  458         wb_mii_send(sc, frame->mii_opcode, 2);
  459         wb_mii_send(sc, frame->mii_phyaddr, 5);
  460         wb_mii_send(sc, frame->mii_regaddr, 5);
  461         wb_mii_send(sc, frame->mii_turnaround, 2);
  462         wb_mii_send(sc, frame->mii_data, 16);
  463 
  464         
  465         SIO_SET(WB_SIO_MII_CLK);
  466         DELAY(1);
  467         SIO_CLR(WB_SIO_MII_CLK);
  468         DELAY(1);
  469 
  470         
  471 
  472 
  473         SIO_CLR(WB_SIO_MII_DIR);
  474 
  475         splx(s);
  476 
  477         return(0);
  478 }
  479 
  480 int
  481 wb_miibus_readreg(dev, phy, reg)
  482         struct device *dev;
  483         int phy, reg;
  484 {
  485         struct wb_softc *sc = (struct wb_softc *)dev;
  486         struct wb_mii_frame frame;
  487 
  488         bzero((char *)&frame, sizeof(frame));
  489 
  490         frame.mii_phyaddr = phy;
  491         frame.mii_regaddr = reg;
  492         wb_mii_readreg(sc, &frame);
  493 
  494         return(frame.mii_data);
  495 }
  496 
  497 void
  498 wb_miibus_writereg(dev, phy, reg, data)
  499         struct device *dev;
  500         int phy, reg, data;
  501 {
  502         struct wb_softc *sc = (struct wb_softc *)dev;
  503         struct wb_mii_frame frame;
  504 
  505         bzero((char *)&frame, sizeof(frame));
  506 
  507         frame.mii_phyaddr = phy;
  508         frame.mii_regaddr = reg;
  509         frame.mii_data = data;
  510 
  511         wb_mii_writereg(sc, &frame);
  512 
  513         return;
  514 }
  515 
  516 void
  517 wb_miibus_statchg(dev)
  518         struct device *dev;
  519 {
  520         struct wb_softc *sc = (struct wb_softc *)dev;
  521 
  522         wb_setcfg(sc, sc->sc_mii.mii_media_active);
  523 }
  524 
  525 
  526 
  527 
  528 void wb_setmulti(sc)
  529         struct wb_softc         *sc;
  530 {
  531         struct ifnet            *ifp;
  532         int                     h = 0;
  533         u_int32_t               hashes[2] = { 0, 0 };
  534         struct arpcom           *ac = &sc->arpcom;
  535         struct ether_multi      *enm;
  536         struct ether_multistep  step;
  537         u_int32_t               rxfilt;
  538         int                     mcnt = 0;
  539 
  540         ifp = &sc->arpcom.ac_if;
  541 
  542         rxfilt = CSR_READ_4(sc, WB_NETCFG);
  543 
  544 allmulti:
  545         if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
  546                 rxfilt |= WB_NETCFG_RX_MULTI;
  547                 CSR_WRITE_4(sc, WB_NETCFG, rxfilt);
  548                 CSR_WRITE_4(sc, WB_MAR0, 0xFFFFFFFF);
  549                 CSR_WRITE_4(sc, WB_MAR1, 0xFFFFFFFF);
  550                 return;
  551         }
  552 
  553         
  554         CSR_WRITE_4(sc, WB_MAR0, 0);
  555         CSR_WRITE_4(sc, WB_MAR1, 0);
  556 
  557         
  558         ETHER_FIRST_MULTI(step, ac, enm);
  559         while (enm != NULL) {
  560                 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
  561                         ifp->if_flags |= IFF_ALLMULTI;
  562                         goto allmulti;
  563                 }
  564                 h = ~(ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26);
  565                 if (h < 32)
  566                         hashes[0] |= (1 << h);
  567                 else
  568                         hashes[1] |= (1 << (h - 32));
  569                 mcnt++;
  570                 ETHER_NEXT_MULTI(step, enm);
  571         }
  572 
  573         if (mcnt)
  574                 rxfilt |= WB_NETCFG_RX_MULTI;
  575         else
  576                 rxfilt &= ~WB_NETCFG_RX_MULTI;
  577 
  578         CSR_WRITE_4(sc, WB_MAR0, hashes[0]);
  579         CSR_WRITE_4(sc, WB_MAR1, hashes[1]);
  580         CSR_WRITE_4(sc, WB_NETCFG, rxfilt);
  581 
  582         return;
  583 }
  584 
  585 
  586 
  587 
  588 
  589 
  590 void
  591 wb_setcfg(sc, media)
  592         struct wb_softc *sc;
  593         u_int32_t media;
  594 {
  595         int                     i, restart = 0;
  596 
  597         if (CSR_READ_4(sc, WB_NETCFG) & (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON)) {
  598                 restart = 1;
  599                 WB_CLRBIT(sc, WB_NETCFG, (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON));
  600 
  601                 for (i = 0; i < WB_TIMEOUT; i++) {
  602                         DELAY(10);
  603                         if ((CSR_READ_4(sc, WB_ISR) & WB_ISR_TX_IDLE) &&
  604                                 (CSR_READ_4(sc, WB_ISR) & WB_ISR_RX_IDLE))
  605                                 break;
  606                 }
  607 
  608                 if (i == WB_TIMEOUT)
  609                         printf("%s: failed to force tx and "
  610                                 "rx to idle state\n", sc->sc_dev.dv_xname);
  611         }
  612 
  613         if (IFM_SUBTYPE(media) == IFM_10_T)
  614                 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_100MBPS);
  615         else
  616                 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_100MBPS);
  617 
  618         if ((media & IFM_GMASK) == IFM_FDX)
  619                 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_FULLDUPLEX);
  620         else
  621                 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_FULLDUPLEX);
  622 
  623         if (restart)
  624                 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON|WB_NETCFG_RX_ON);
  625 
  626         return;
  627 }
  628 
  629 void
  630 wb_reset(sc)
  631         struct wb_softc *sc;
  632 {
  633         int i;
  634         struct mii_data *mii = &sc->sc_mii;
  635 
  636         CSR_WRITE_4(sc, WB_NETCFG, 0);
  637         CSR_WRITE_4(sc, WB_BUSCTL, 0);
  638         CSR_WRITE_4(sc, WB_TXADDR, 0);
  639         CSR_WRITE_4(sc, WB_RXADDR, 0);
  640 
  641         WB_SETBIT(sc, WB_BUSCTL, WB_BUSCTL_RESET);
  642         WB_SETBIT(sc, WB_BUSCTL, WB_BUSCTL_RESET);
  643 
  644         for (i = 0; i < WB_TIMEOUT; i++) {
  645                 DELAY(10);
  646                 if (!(CSR_READ_4(sc, WB_BUSCTL) & WB_BUSCTL_RESET))
  647                         break;
  648         }
  649         if (i == WB_TIMEOUT)
  650                 printf("%s: reset never completed!\n", sc->sc_dev.dv_xname);
  651 
  652         
  653         DELAY(1000);
  654 
  655         if (mii->mii_instance) {
  656                 struct mii_softc *miisc;
  657                 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
  658                         mii_phy_reset(miisc);
  659         }
  660 }
  661 
  662 void
  663 wb_fixmedia(sc)
  664         struct wb_softc *sc;
  665 {
  666         struct mii_data *mii = &sc->sc_mii;
  667         u_int32_t media;
  668 
  669         if (LIST_FIRST(&mii->mii_phys) == NULL)
  670                 return;
  671 
  672         mii_pollstat(mii);
  673         if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) {
  674                 media = mii->mii_media_active & ~IFM_10_T;
  675                 media |= IFM_100_TX;
  676         } if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) {
  677                 media = mii->mii_media_active & ~IFM_100_TX;
  678                 media |= IFM_10_T;
  679         } else
  680                 return;
  681 
  682         ifmedia_set(&mii->mii_media, media);
  683 }
  684 
  685 const struct pci_matchid wb_devices[] = {
  686         { PCI_VENDOR_WINBOND, PCI_PRODUCT_WINBOND_W89C840F },
  687         { PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_RL100ATX },
  688 };
  689 
  690 
  691 
  692 
  693 
  694 int
  695 wb_probe(parent, match, aux)
  696         struct device *parent;
  697         void *match, *aux;
  698 {
  699         return (pci_matchbyid((struct pci_attach_args *)aux, wb_devices,
  700             sizeof(wb_devices)/sizeof(wb_devices[0])));
  701 }
  702 
  703 
  704 
  705 
  706 
  707 void
  708 wb_attach(parent, self, aux)
  709         struct device *parent, *self;
  710         void *aux;
  711 {
  712         struct wb_softc *sc = (struct wb_softc *)self;
  713         struct pci_attach_args *pa = aux;
  714         pci_chipset_tag_t pc = pa->pa_pc;
  715         pci_intr_handle_t ih;
  716         const char *intrstr = NULL;
  717         struct ifnet *ifp = &sc->arpcom.ac_if;
  718         bus_size_t size;
  719         int rseg;
  720         pcireg_t command;
  721         bus_dma_segment_t seg;
  722         bus_dmamap_t dmamap;
  723         caddr_t kva;
  724 
  725         
  726 
  727 
  728 
  729         command = pci_conf_read(pc, pa->pa_tag, WB_PCI_CAPID) & 0x000000FF;
  730         if (command == 0x01) {
  731 
  732                 command = pci_conf_read(pc, pa->pa_tag, WB_PCI_PWRMGMTCTRL);
  733                 if (command & WB_PSTATE_MASK) {
  734                         u_int32_t               io, mem, irq;
  735 
  736                         
  737                         io = pci_conf_read(pc, pa->pa_tag, WB_PCI_LOIO);
  738                         mem = pci_conf_read(pc, pa->pa_tag, WB_PCI_LOMEM);
  739                         irq = pci_conf_read(pc, pa->pa_tag, WB_PCI_INTLINE);
  740 
  741                         
  742                         printf("%s: chip is in D%d power mode "
  743                             "-- setting to D0\n", sc->sc_dev.dv_xname,
  744                             command & WB_PSTATE_MASK);
  745                         command &= 0xFFFFFFFC;
  746                         pci_conf_write(pc, pa->pa_tag, WB_PCI_PWRMGMTCTRL,
  747                             command);
  748 
  749                         
  750                         pci_conf_write(pc, pa->pa_tag, WB_PCI_LOIO, io);
  751                         pci_conf_write(pc, pa->pa_tag, WB_PCI_LOMEM, mem);
  752                         pci_conf_write(pc, pa->pa_tag, WB_PCI_INTLINE, irq);
  753                 }
  754         }
  755 
  756         
  757 
  758 
  759 
  760 #ifdef WB_USEIOSPACE
  761         if (pci_mapreg_map(pa, WB_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
  762             &sc->wb_btag, &sc->wb_bhandle, NULL, &size, 0)) {
  763                 printf(": can't map i/o space\n");
  764                 return;
  765         }
  766 #else
  767         if (pci_mapreg_map(pa, WB_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
  768             &sc->wb_btag, &sc->wb_bhandle, NULL, &size, 0)){
  769                 printf(": can't map mem space\n");
  770                 return;
  771         }
  772 #endif
  773 
  774         
  775         if (pci_intr_map(pa, &ih)) {
  776                 printf(": couldn't map interrupt\n");
  777                 goto fail_1;
  778         }
  779         intrstr = pci_intr_string(pc, ih);
  780         sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, wb_intr, sc,
  781             self->dv_xname);
  782         if (sc->sc_ih == NULL) {
  783                 printf(": couldn't establish interrupt");
  784                 if (intrstr != NULL)
  785                         printf(" at %s", intrstr);
  786                 printf("\n");
  787                 goto fail_1;
  788         }
  789         printf(": %s", intrstr);
  790 
  791         sc->wb_cachesize = pci_conf_read(pc, pa->pa_tag, WB_PCI_CACHELEN)&0xff;
  792 
  793         
  794         wb_reset(sc);
  795 
  796         
  797 
  798 
  799         wb_read_eeprom(sc, (caddr_t)&sc->arpcom.ac_enaddr, 0, 3, 0);
  800         printf(", address %s\n", ether_sprintf(sc->arpcom.ac_enaddr));
  801 
  802         if (bus_dmamem_alloc(pa->pa_dmat, sizeof(struct wb_list_data),
  803             PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
  804                 printf(": can't alloc list data\n");
  805                 goto fail_2;
  806         }
  807         if (bus_dmamem_map(pa->pa_dmat, &seg, rseg,
  808             sizeof(struct wb_list_data), &kva, BUS_DMA_NOWAIT)) {
  809                 printf(": can't map list data, size %d\n",
  810                     sizeof(struct wb_list_data));
  811                 goto fail_3;
  812         }
  813         if (bus_dmamap_create(pa->pa_dmat, sizeof(struct wb_list_data), 1,
  814             sizeof(struct wb_list_data), 0, BUS_DMA_NOWAIT, &dmamap)) {
  815                 printf(": can't create dma map\n");
  816                 goto fail_4;
  817         }
  818         if (bus_dmamap_load(pa->pa_dmat, dmamap, kva,
  819             sizeof(struct wb_list_data), NULL, BUS_DMA_NOWAIT)) {
  820                 printf(": can't load dma map\n");
  821                 goto fail_5;
  822         }
  823         sc->wb_ldata = (struct wb_list_data *)kva;
  824         bzero(sc->wb_ldata, sizeof(struct wb_list_data));
  825 
  826         ifp->if_softc = sc;
  827         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  828         ifp->if_ioctl = wb_ioctl;
  829         ifp->if_start = wb_start;
  830         ifp->if_watchdog = wb_watchdog;
  831         ifp->if_baudrate = 10000000;
  832         IFQ_SET_MAXLEN(&ifp->if_snd, WB_TX_LIST_CNT - 1);
  833         IFQ_SET_READY(&ifp->if_snd);
  834 
  835         bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
  836 
  837         
  838 
  839 
  840         wb_stop(sc);
  841 
  842         ifmedia_init(&sc->sc_mii.mii_media, 0, wb_ifmedia_upd, wb_ifmedia_sts);
  843         sc->sc_mii.mii_ifp = ifp;
  844         sc->sc_mii.mii_readreg = wb_miibus_readreg;
  845         sc->sc_mii.mii_writereg = wb_miibus_writereg;
  846         sc->sc_mii.mii_statchg = wb_miibus_statchg;
  847         mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
  848             0);
  849         if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
  850                 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE,0,NULL);
  851                 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
  852         } else
  853                 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
  854 
  855         
  856 
  857 
  858         if_attach(ifp);
  859         ether_ifattach(ifp);
  860 
  861         shutdownhook_establish(wb_shutdown, sc);
  862         return;
  863 
  864 fail_5:
  865         bus_dmamap_destroy(pa->pa_dmat, dmamap);
  866 
  867 fail_4:
  868         bus_dmamem_unmap(pa->pa_dmat, kva,
  869             sizeof(struct wb_list_data));
  870 
  871 fail_3:
  872         bus_dmamem_free(pa->pa_dmat, &seg, rseg);
  873 
  874 fail_2:
  875         pci_intr_disestablish(pc, sc->sc_ih);
  876 
  877 fail_1:
  878         bus_space_unmap(sc->wb_btag, sc->wb_bhandle, size);
  879 }
  880 
  881 
  882 
  883 
  884 int wb_list_tx_init(sc)
  885         struct wb_softc         *sc;
  886 {
  887         struct wb_chain_data    *cd;
  888         struct wb_list_data     *ld;
  889         int                     i;
  890 
  891         cd = &sc->wb_cdata;
  892         ld = sc->wb_ldata;
  893 
  894         for (i = 0; i < WB_TX_LIST_CNT; i++) {
  895                 cd->wb_tx_chain[i].wb_ptr = &ld->wb_tx_list[i];
  896                 if (i == (WB_TX_LIST_CNT - 1)) {
  897                         cd->wb_tx_chain[i].wb_nextdesc =
  898                                 &cd->wb_tx_chain[0];
  899                 } else {
  900                         cd->wb_tx_chain[i].wb_nextdesc =
  901                                 &cd->wb_tx_chain[i + 1];
  902                 }
  903         }
  904 
  905         cd->wb_tx_free = &cd->wb_tx_chain[0];
  906         cd->wb_tx_tail = cd->wb_tx_head = NULL;
  907 
  908         return(0);
  909 }
  910 
  911 
  912 
  913 
  914 
  915 
  916 
  917 int wb_list_rx_init(sc)
  918         struct wb_softc         *sc;
  919 {
  920         struct wb_chain_data    *cd;
  921         struct wb_list_data     *ld;
  922         int                     i;
  923 
  924         cd = &sc->wb_cdata;
  925         ld = sc->wb_ldata;
  926 
  927         for (i = 0; i < WB_RX_LIST_CNT; i++) {
  928                 cd->wb_rx_chain[i].wb_ptr =
  929                         (struct wb_desc *)&ld->wb_rx_list[i];
  930                 cd->wb_rx_chain[i].wb_buf = (void *)&ld->wb_rxbufs[i];
  931                 if (wb_newbuf(sc, &cd->wb_rx_chain[i], NULL) == ENOBUFS)
  932                         return(ENOBUFS);
  933                 if (i == (WB_RX_LIST_CNT - 1)) {
  934                         cd->wb_rx_chain[i].wb_nextdesc = &cd->wb_rx_chain[0];
  935                         ld->wb_rx_list[i].wb_next = 
  936                                         VTOPHYS(&ld->wb_rx_list[0]);
  937                 } else {
  938                         cd->wb_rx_chain[i].wb_nextdesc =
  939                                         &cd->wb_rx_chain[i + 1];
  940                         ld->wb_rx_list[i].wb_next =
  941                                         VTOPHYS(&ld->wb_rx_list[i + 1]);
  942                 }
  943         }
  944 
  945         cd->wb_rx_head = &cd->wb_rx_chain[0];
  946 
  947         return(0);
  948 }
  949 
  950 void
  951 wb_bfree(buf, size, arg)
  952         caddr_t                 buf;
  953         u_int                   size;
  954         void *arg;
  955 {
  956 }
  957 
  958 
  959 
  960 
  961 int
  962 wb_newbuf(sc, c, m)
  963         struct wb_softc *sc;
  964         struct wb_chain_onefrag *c;
  965         struct mbuf *m;
  966 {
  967         struct mbuf             *m_new = NULL;
  968 
  969         if (m == NULL) {
  970                 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
  971                 if (m_new == NULL)
  972                         return(ENOBUFS);
  973                 m_new->m_data = m_new->m_ext.ext_buf = c->wb_buf;
  974                 m_new->m_flags |= M_EXT;
  975                 m_new->m_ext.ext_size = m_new->m_pkthdr.len =
  976                     m_new->m_len = WB_BUFBYTES;
  977                 m_new->m_ext.ext_free = wb_bfree;
  978                 m_new->m_ext.ext_arg = NULL;
  979                 MCLINITREFERENCE(m_new);
  980         } else {
  981                 m_new = m;
  982                 m_new->m_len = m_new->m_pkthdr.len = WB_BUFBYTES;
  983                 m_new->m_data = m_new->m_ext.ext_buf;
  984         }
  985 
  986         m_adj(m_new, sizeof(u_int64_t));
  987 
  988         c->wb_mbuf = m_new;
  989         c->wb_ptr->wb_data = VTOPHYS(mtod(m_new, caddr_t));
  990         c->wb_ptr->wb_ctl = WB_RXCTL_RLINK | ETHER_MAX_DIX_LEN;
  991         c->wb_ptr->wb_status = WB_RXSTAT;
  992 
  993         return(0);
  994 }
  995 
  996 
  997 
  998 
  999 
 1000 void wb_rxeof(sc)
 1001         struct wb_softc         *sc;
 1002 {
 1003         struct mbuf             *m = NULL;
 1004         struct ifnet            *ifp;
 1005         struct wb_chain_onefrag *cur_rx;
 1006         int                     total_len = 0;
 1007         u_int32_t               rxstat;
 1008 
 1009         ifp = &sc->arpcom.ac_if;
 1010 
 1011         while(!((rxstat = sc->wb_cdata.wb_rx_head->wb_ptr->wb_status) &
 1012                                                         WB_RXSTAT_OWN)) {
 1013                 struct mbuf *m0 = NULL;
 1014 
 1015                 cur_rx = sc->wb_cdata.wb_rx_head;
 1016                 sc->wb_cdata.wb_rx_head = cur_rx->wb_nextdesc;
 1017 
 1018                 m = cur_rx->wb_mbuf;
 1019 
 1020                 if ((rxstat & WB_RXSTAT_MIIERR) ||
 1021                     (WB_RXBYTES(cur_rx->wb_ptr->wb_status) < WB_MIN_FRAMELEN) ||
 1022                     (WB_RXBYTES(cur_rx->wb_ptr->wb_status) > ETHER_MAX_DIX_LEN) ||
 1023                     !(rxstat & WB_RXSTAT_LASTFRAG) ||
 1024                     !(rxstat & WB_RXSTAT_RXCMP)) {
 1025                         ifp->if_ierrors++;
 1026                         wb_newbuf(sc, cur_rx, m);
 1027                         printf("%s: receiver babbling: possible chip "
 1028                                 "bug, forcing reset\n", sc->sc_dev.dv_xname);
 1029                         wb_fixmedia(sc);
 1030                         wb_reset(sc);
 1031                         wb_init(sc);
 1032                         return;
 1033                 }
 1034 
 1035                 if (rxstat & WB_RXSTAT_RXERR) {
 1036                         ifp->if_ierrors++;
 1037                         wb_newbuf(sc, cur_rx, m);
 1038                         break;
 1039                 }
 1040 
 1041                     
 1042                 total_len = WB_RXBYTES(cur_rx->wb_ptr->wb_status);
 1043 
 1044                 
 1045 
 1046 
 1047 
 1048 
 1049 
 1050 
 1051                 total_len -= ETHER_CRC_LEN;
 1052 
 1053                 m0 = m_devget(mtod(m, char *) - ETHER_ALIGN,
 1054                     total_len + ETHER_ALIGN, 0, ifp, NULL);
 1055                 wb_newbuf(sc, cur_rx, m);
 1056                 if (m0 == NULL) {
 1057                         ifp->if_ierrors++;
 1058                         break;
 1059                 }
 1060                 m_adj(m0, ETHER_ALIGN);
 1061                 m = m0;
 1062 
 1063                 ifp->if_ipackets++;
 1064 
 1065 #if NBPFILTER > 0
 1066                 
 1067 
 1068 
 1069                 if (ifp->if_bpf)
 1070                         bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
 1071 #endif
 1072                 
 1073                 ether_input_mbuf(ifp, m);
 1074         }
 1075 
 1076         return;
 1077 }
 1078 
 1079 void wb_rxeoc(sc)
 1080         struct wb_softc         *sc;
 1081 {
 1082         wb_rxeof(sc);
 1083 
 1084         WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
 1085         CSR_WRITE_4(sc, WB_RXADDR, VTOPHYS(&sc->wb_ldata->wb_rx_list[0]));
 1086         WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
 1087         if (CSR_READ_4(sc, WB_ISR) & WB_RXSTATE_SUSPEND)
 1088                 CSR_WRITE_4(sc, WB_RXSTART, 0xFFFFFFFF);
 1089 
 1090         return;
 1091 }
 1092 
 1093 
 1094 
 1095 
 1096 
 1097 void wb_txeof(sc)
 1098         struct wb_softc         *sc;
 1099 {
 1100         struct wb_chain         *cur_tx;
 1101         struct ifnet            *ifp;
 1102 
 1103         ifp = &sc->arpcom.ac_if;
 1104 
 1105         
 1106         ifp->if_timer = 0;
 1107 
 1108         if (sc->wb_cdata.wb_tx_head == NULL)
 1109                 return;
 1110 
 1111         
 1112 
 1113 
 1114 
 1115         while(sc->wb_cdata.wb_tx_head->wb_mbuf != NULL) {
 1116                 u_int32_t               txstat;
 1117 
 1118                 cur_tx = sc->wb_cdata.wb_tx_head;
 1119                 txstat = WB_TXSTATUS(cur_tx);
 1120 
 1121                 if ((txstat & WB_TXSTAT_OWN) || txstat == WB_UNSENT)
 1122                         break;
 1123 
 1124                 if (txstat & WB_TXSTAT_TXERR) {
 1125                         ifp->if_oerrors++;
 1126                         if (txstat & WB_TXSTAT_ABORT)
 1127                                 ifp->if_collisions++;
 1128                         if (txstat & WB_TXSTAT_LATECOLL)
 1129                                 ifp->if_collisions++;
 1130                 }
 1131 
 1132                 ifp->if_collisions += (txstat & WB_TXSTAT_COLLCNT) >> 3;
 1133 
 1134                 ifp->if_opackets++;
 1135                 m_freem(cur_tx->wb_mbuf);
 1136                 cur_tx->wb_mbuf = NULL;
 1137 
 1138                 if (sc->wb_cdata.wb_tx_head == sc->wb_cdata.wb_tx_tail) {
 1139                         sc->wb_cdata.wb_tx_head = NULL;
 1140                         sc->wb_cdata.wb_tx_tail = NULL;
 1141                         break;
 1142                 }
 1143 
 1144                 sc->wb_cdata.wb_tx_head = cur_tx->wb_nextdesc;
 1145         }
 1146 
 1147         return;
 1148 }
 1149 
 1150 
 1151 
 1152 
 1153 void wb_txeoc(sc)
 1154         struct wb_softc         *sc;
 1155 {
 1156         struct ifnet            *ifp;
 1157 
 1158         ifp = &sc->arpcom.ac_if;
 1159 
 1160         ifp->if_timer = 0;
 1161 
 1162         if (sc->wb_cdata.wb_tx_head == NULL) {
 1163                 ifp->if_flags &= ~IFF_OACTIVE;
 1164                 sc->wb_cdata.wb_tx_tail = NULL;
 1165         } else {
 1166                 if (WB_TXOWN(sc->wb_cdata.wb_tx_head) == WB_UNSENT) {
 1167                         WB_TXOWN(sc->wb_cdata.wb_tx_head) = WB_TXSTAT_OWN;
 1168                         ifp->if_timer = 5;
 1169                         CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
 1170                 }
 1171         }
 1172 
 1173         return;
 1174 }
 1175 
 1176 int wb_intr(arg)
 1177         void                    *arg;
 1178 {
 1179         struct wb_softc         *sc;
 1180         struct ifnet            *ifp;
 1181         u_int32_t               status;
 1182         int                     r = 0;
 1183 
 1184         sc = arg;
 1185         ifp = &sc->arpcom.ac_if;
 1186 
 1187         if (!(ifp->if_flags & IFF_UP))
 1188                 return (r);
 1189 
 1190         
 1191         CSR_WRITE_4(sc, WB_IMR, 0x00000000);
 1192 
 1193         for (;;) {
 1194 
 1195                 status = CSR_READ_4(sc, WB_ISR);
 1196                 if (status)
 1197                         CSR_WRITE_4(sc, WB_ISR, status);
 1198 
 1199                 if ((status & WB_INTRS) == 0)
 1200                         break;
 1201 
 1202                 r = 1;
 1203 
 1204                 if ((status & WB_ISR_RX_NOBUF) || (status & WB_ISR_RX_ERR)) {
 1205                         ifp->if_ierrors++;
 1206                         wb_reset(sc);
 1207                         if (status & WB_ISR_RX_ERR)
 1208                                 wb_fixmedia(sc);
 1209                         wb_init(sc);
 1210                         continue;
 1211                 }
 1212 
 1213                 if (status & WB_ISR_RX_OK)
 1214                         wb_rxeof(sc);
 1215 
 1216                 if (status & WB_ISR_RX_IDLE)
 1217                         wb_rxeoc(sc);
 1218 
 1219                 if (status & WB_ISR_TX_OK)
 1220                         wb_txeof(sc);
 1221 
 1222                 if (status & WB_ISR_TX_NOBUF)
 1223                         wb_txeoc(sc);
 1224 
 1225                 if (status & WB_ISR_TX_IDLE) {
 1226                         wb_txeof(sc);
 1227                         if (sc->wb_cdata.wb_tx_head != NULL) {
 1228                                 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
 1229                                 CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
 1230                         }
 1231                 }
 1232 
 1233                 if (status & WB_ISR_TX_UNDERRUN) {
 1234                         ifp->if_oerrors++;
 1235                         wb_txeof(sc);
 1236                         WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
 1237                         
 1238                         sc->wb_txthresh += WB_TXTHRESH_CHUNK;
 1239                         WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_THRESH);
 1240                         WB_SETBIT(sc, WB_NETCFG, WB_TXTHRESH(sc->wb_txthresh));
 1241                         WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
 1242                 }
 1243 
 1244                 if (status & WB_ISR_BUS_ERR) {
 1245                         wb_reset(sc);
 1246                         wb_init(sc);
 1247                 }
 1248 
 1249         }
 1250 
 1251         
 1252         CSR_WRITE_4(sc, WB_IMR, WB_INTRS);
 1253 
 1254         if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 1255                 wb_start(ifp);
 1256         }
 1257 
 1258         return (r);
 1259 }
 1260 
 1261 void
 1262 wb_tick(xsc)
 1263         void *xsc;
 1264 {
 1265         struct wb_softc *sc = xsc;
 1266         int s;
 1267 
 1268         s = splnet();
 1269         mii_tick(&sc->sc_mii);
 1270         splx(s);
 1271         timeout_add(&sc->wb_tick_tmo, hz);
 1272 }
 1273 
 1274 
 1275 
 1276 
 1277 
 1278 int wb_encap(sc, c, m_head)
 1279         struct wb_softc         *sc;
 1280         struct wb_chain         *c;
 1281         struct mbuf             *m_head;
 1282 {
 1283         int                     frag = 0;
 1284         struct wb_desc          *f = NULL;
 1285         int                     total_len;
 1286         struct mbuf             *m;
 1287 
 1288         
 1289 
 1290 
 1291 
 1292 
 1293         m = m_head;
 1294         total_len = 0;
 1295 
 1296         for (m = m_head, frag = 0; m != NULL; m = m->m_next) {
 1297                 if (m->m_len != 0) {
 1298                         if (frag == WB_MAXFRAGS)
 1299                                 break;
 1300                         total_len += m->m_len;
 1301                         f = &c->wb_ptr->wb_frag[frag];
 1302                         f->wb_ctl = WB_TXCTL_TLINK | m->m_len;
 1303                         if (frag == 0) {
 1304                                 f->wb_ctl |= WB_TXCTL_FIRSTFRAG;
 1305                                 f->wb_status = 0;
 1306                         } else
 1307                                 f->wb_status = WB_TXSTAT_OWN;
 1308                         f->wb_next = VTOPHYS(&c->wb_ptr->wb_frag[frag + 1]);
 1309                         f->wb_data = VTOPHYS(mtod(m, vaddr_t));
 1310                         frag++;
 1311                 }
 1312         }
 1313 
 1314         
 1315 
 1316 
 1317 
 1318 
 1319 
 1320 
 1321 
 1322         if (m != NULL) {
 1323                 struct mbuf             *m_new = NULL;
 1324 
 1325                 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
 1326                 if (m_new == NULL)
 1327                         return(1);
 1328                 if (m_head->m_pkthdr.len > MHLEN) {
 1329                         MCLGET(m_new, M_DONTWAIT);
 1330                         if (!(m_new->m_flags & M_EXT)) {
 1331                                 m_freem(m_new);
 1332                                 return(1);
 1333                         }
 1334                 }
 1335                 m_copydata(m_head, 0, m_head->m_pkthdr.len,     
 1336                                         mtod(m_new, caddr_t));
 1337                 m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
 1338                 m_freem(m_head);
 1339                 m_head = m_new;
 1340                 f = &c->wb_ptr->wb_frag[0];
 1341                 f->wb_status = 0;
 1342                 f->wb_data = VTOPHYS(mtod(m_new, caddr_t));
 1343                 f->wb_ctl = total_len = m_new->m_len;
 1344                 f->wb_ctl |= WB_TXCTL_TLINK|WB_TXCTL_FIRSTFRAG;
 1345                 frag = 1;
 1346         }
 1347 
 1348         if (total_len < WB_MIN_FRAMELEN) {
 1349                 f = &c->wb_ptr->wb_frag[frag];
 1350                 f->wb_ctl = WB_MIN_FRAMELEN - total_len;
 1351                 f->wb_data = VTOPHYS(&sc->wb_cdata.wb_pad);
 1352                 f->wb_ctl |= WB_TXCTL_TLINK;
 1353                 f->wb_status = WB_TXSTAT_OWN;
 1354                 frag++;
 1355         }
 1356 
 1357         c->wb_mbuf = m_head;
 1358         c->wb_lastdesc = frag - 1;
 1359         WB_TXCTL(c) |= WB_TXCTL_LASTFRAG;
 1360         WB_TXNEXT(c) = VTOPHYS(&c->wb_nextdesc->wb_ptr->wb_frag[0]);
 1361 
 1362         return(0);
 1363 }
 1364 
 1365 
 1366 
 1367 
 1368 
 1369 
 1370 
 1371 
 1372 void wb_start(ifp)
 1373         struct ifnet            *ifp;
 1374 {
 1375         struct wb_softc         *sc;
 1376         struct mbuf             *m_head = NULL;
 1377         struct wb_chain         *cur_tx = NULL, *start_tx;
 1378 
 1379         sc = ifp->if_softc;
 1380 
 1381         
 1382 
 1383 
 1384 
 1385         if (sc->wb_cdata.wb_tx_free->wb_mbuf != NULL) {
 1386                 ifp->if_flags |= IFF_OACTIVE;
 1387                 return;
 1388         }
 1389 
 1390         start_tx = sc->wb_cdata.wb_tx_free;
 1391 
 1392         while(sc->wb_cdata.wb_tx_free->wb_mbuf == NULL) {
 1393                 IFQ_DEQUEUE(&ifp->if_snd, m_head);
 1394                 if (m_head == NULL)
 1395                         break;
 1396 
 1397                 
 1398                 cur_tx = sc->wb_cdata.wb_tx_free;
 1399                 sc->wb_cdata.wb_tx_free = cur_tx->wb_nextdesc;
 1400 
 1401                 
 1402                 wb_encap(sc, cur_tx, m_head);
 1403 
 1404                 if (cur_tx != start_tx)
 1405                         WB_TXOWN(cur_tx) = WB_TXSTAT_OWN;
 1406 
 1407 #if NBPFILTER > 0
 1408                 
 1409 
 1410 
 1411 
 1412                 if (ifp->if_bpf)
 1413                         bpf_mtap(ifp->if_bpf, cur_tx->wb_mbuf,
 1414                             BPF_DIRECTION_OUT);
 1415 #endif
 1416         }
 1417 
 1418         
 1419 
 1420 
 1421         if (cur_tx == NULL)
 1422                 return;
 1423 
 1424         
 1425 
 1426 
 1427 
 1428 
 1429 
 1430 
 1431         WB_TXCTL(cur_tx) |= WB_TXCTL_FINT;
 1432         cur_tx->wb_ptr->wb_frag[0].wb_ctl |= WB_TXCTL_FINT;
 1433         sc->wb_cdata.wb_tx_tail = cur_tx;
 1434 
 1435         if (sc->wb_cdata.wb_tx_head == NULL) {
 1436                 sc->wb_cdata.wb_tx_head = start_tx;
 1437                 WB_TXOWN(start_tx) = WB_TXSTAT_OWN;
 1438                 CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
 1439         } else {
 1440                 
 1441 
 1442 
 1443 
 1444 
 1445 
 1446 
 1447 
 1448 
 1449 
 1450 
 1451 
 1452                 WB_TXOWN(start_tx) = WB_UNSENT;
 1453         }
 1454 
 1455         
 1456 
 1457 
 1458         ifp->if_timer = 5;
 1459 
 1460         return;
 1461 }
 1462 
 1463 void wb_init(xsc)
 1464         void                    *xsc;
 1465 {
 1466         struct wb_softc *sc = xsc;
 1467         struct ifnet *ifp = &sc->arpcom.ac_if;
 1468         int s, i;
 1469 
 1470         s = splnet();
 1471 
 1472         
 1473 
 1474 
 1475         wb_stop(sc);
 1476         wb_reset(sc);
 1477 
 1478         sc->wb_txthresh = WB_TXTHRESH_INIT;
 1479 
 1480         
 1481 
 1482 
 1483 #ifdef foo
 1484         CSR_WRITE_4(sc, WB_BUSCTL, WB_BUSCTL_CONFIG);
 1485         WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_THRESH);
 1486         WB_SETBIT(sc, WB_NETCFG, WB_TXTHRESH(sc->wb_txthresh));
 1487 #endif
 1488 
 1489         CSR_WRITE_4(sc, WB_BUSCTL, WB_BUSCTL_MUSTBEONE|WB_BUSCTL_ARBITRATION);
 1490         WB_SETBIT(sc, WB_BUSCTL, WB_BURSTLEN_16LONG);
 1491         switch(sc->wb_cachesize) {
 1492         case 32:
 1493                 WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_32LONG);
 1494                 break;
 1495         case 16:
 1496                 WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_16LONG);
 1497                 break;
 1498         case 8:
 1499                 WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_8LONG);
 1500                 break;
 1501         case 0:
 1502         default:
 1503                 WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_NONE);
 1504                 break;
 1505         }
 1506 
 1507         
 1508         WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_EARLY_ON);
 1509 
 1510         
 1511         for (i = 0; i < ETHER_ADDR_LEN; i++) {
 1512                 CSR_WRITE_1(sc, WB_NODE0 + i, sc->arpcom.ac_enaddr[i]);
 1513         }
 1514 
 1515         
 1516         if (wb_list_rx_init(sc) == ENOBUFS) {
 1517                 printf("%s: initialization failed: no "
 1518                         "memory for rx buffers\n", sc->sc_dev.dv_xname);
 1519                 wb_stop(sc);
 1520                 splx(s);
 1521                 return;
 1522         }
 1523 
 1524         
 1525         wb_list_tx_init(sc);
 1526 
 1527         
 1528         if (ifp->if_flags & IFF_PROMISC) {
 1529                 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_ALLPHYS);
 1530         } else {
 1531                 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_ALLPHYS);
 1532         }
 1533 
 1534         
 1535 
 1536 
 1537         if (ifp->if_flags & IFF_BROADCAST) {
 1538                 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_BROAD);
 1539         } else {
 1540                 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_BROAD);
 1541         }
 1542 
 1543         
 1544 
 1545 
 1546         wb_setmulti(sc);
 1547 
 1548         
 1549 
 1550 
 1551         WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
 1552         CSR_WRITE_4(sc, WB_RXADDR, VTOPHYS(&sc->wb_ldata->wb_rx_list[0]));
 1553 
 1554         
 1555 
 1556 
 1557         CSR_WRITE_4(sc, WB_IMR, WB_INTRS);
 1558         CSR_WRITE_4(sc, WB_ISR, 0xFFFFFFFF);
 1559 
 1560         
 1561         WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
 1562         CSR_WRITE_4(sc, WB_RXSTART, 0xFFFFFFFF);
 1563 
 1564         WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
 1565         CSR_WRITE_4(sc, WB_TXADDR, VTOPHYS(&sc->wb_ldata->wb_tx_list[0]));
 1566         WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
 1567 
 1568         ifp->if_flags |= IFF_RUNNING;
 1569         ifp->if_flags &= ~IFF_OACTIVE;
 1570 
 1571         splx(s);
 1572 
 1573         timeout_set(&sc->wb_tick_tmo, wb_tick, sc);
 1574         timeout_add(&sc->wb_tick_tmo, hz);
 1575 
 1576         return;
 1577 }
 1578 
 1579 
 1580 
 1581 
 1582 int
 1583 wb_ifmedia_upd(ifp)
 1584         struct ifnet *ifp;
 1585 {
 1586         struct wb_softc *sc = ifp->if_softc;
 1587 
 1588         if (ifp->if_flags & IFF_UP)
 1589                 wb_init(sc);
 1590 
 1591         return(0);
 1592 }
 1593 
 1594 
 1595 
 1596 
 1597 void
 1598 wb_ifmedia_sts(ifp, ifmr)
 1599         struct ifnet            *ifp;
 1600         struct ifmediareq       *ifmr;
 1601 {
 1602         struct wb_softc *sc = ifp->if_softc;
 1603         struct mii_data *mii = &sc->sc_mii;
 1604 
 1605         mii_pollstat(mii);
 1606         ifmr->ifm_active = mii->mii_media_active;
 1607         ifmr->ifm_status = mii->mii_media_status;
 1608 }
 1609 
 1610 int wb_ioctl(ifp, command, data)
 1611         struct ifnet            *ifp;
 1612         u_long                  command;
 1613         caddr_t                 data;
 1614 {
 1615         struct wb_softc         *sc = ifp->if_softc;
 1616         struct ifreq            *ifr = (struct ifreq *) data;
 1617         struct ifaddr           *ifa = (struct ifaddr *)data;
 1618         int                     s, error = 0;
 1619 
 1620         s = splnet();
 1621 
 1622         if ((error = ether_ioctl(ifp, &sc->arpcom, command, data)) > 0) {
 1623                 splx(s);
 1624                 return (error);
 1625         }
 1626 
 1627         switch(command) {
 1628         case SIOCSIFADDR:
 1629                 ifp->if_flags |= IFF_UP;
 1630                 switch (ifa->ifa_addr->sa_family) {
 1631 #ifdef INET
 1632                 case AF_INET:
 1633                         wb_init(sc);
 1634                         arp_ifinit(&sc->arpcom, ifa);
 1635                         break;
 1636 #endif 
 1637                 default:
 1638                         wb_init(sc);
 1639                 }
 1640                 break;
 1641         case SIOCSIFFLAGS:
 1642                 if (ifp->if_flags & IFF_UP) {
 1643                         wb_init(sc);
 1644                 } else {
 1645                         if (ifp->if_flags & IFF_RUNNING)
 1646                                 wb_stop(sc);
 1647                 }
 1648                 error = 0;
 1649                 break;
 1650         case SIOCADDMULTI:
 1651         case SIOCDELMULTI:
 1652                 error = (command == SIOCADDMULTI) ?
 1653                     ether_addmulti(ifr, &sc->arpcom) :
 1654                     ether_delmulti(ifr, &sc->arpcom);
 1655 
 1656                 if (error == ENETRESET) {
 1657                         
 1658 
 1659 
 1660 
 1661                         if (ifp->if_flags & IFF_RUNNING)
 1662                                 wb_setmulti(sc);
 1663                         error = 0;
 1664                 }
 1665                 break;
 1666         case SIOCGIFMEDIA:
 1667         case SIOCSIFMEDIA:
 1668                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
 1669                 break;
 1670         default:
 1671                 error = ENOTTY;
 1672                 break;
 1673         }
 1674 
 1675         splx(s);
 1676 
 1677         return(error);
 1678 }
 1679 
 1680 void wb_watchdog(ifp)
 1681         struct ifnet            *ifp;
 1682 {
 1683         struct wb_softc         *sc;
 1684 
 1685         sc = ifp->if_softc;
 1686 
 1687         ifp->if_oerrors++;
 1688         printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
 1689 
 1690 #ifdef foo
 1691         if (!(wb_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT))
 1692                 printf("%s: no carrier - transceiver cable problem?\n",
 1693                     sc->sc_dev.dv_xname);
 1694 #endif
 1695         wb_stop(sc);
 1696         wb_reset(sc);
 1697         wb_init(sc);
 1698 
 1699         if (!IFQ_IS_EMPTY(&ifp->if_snd))
 1700                 wb_start(ifp);
 1701 
 1702         return;
 1703 }
 1704 
 1705 
 1706 
 1707 
 1708 
 1709 void wb_stop(sc)
 1710         struct wb_softc         *sc;
 1711 {
 1712         int                     i;
 1713         struct ifnet            *ifp;
 1714 
 1715         ifp = &sc->arpcom.ac_if;
 1716         ifp->if_timer = 0;
 1717 
 1718         timeout_del(&sc->wb_tick_tmo);
 1719 
 1720         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
 1721 
 1722         WB_CLRBIT(sc, WB_NETCFG, (WB_NETCFG_RX_ON|WB_NETCFG_TX_ON));
 1723         CSR_WRITE_4(sc, WB_IMR, 0x00000000);
 1724         CSR_WRITE_4(sc, WB_TXADDR, 0x00000000);
 1725         CSR_WRITE_4(sc, WB_RXADDR, 0x00000000);
 1726 
 1727         
 1728 
 1729 
 1730         for (i = 0; i < WB_RX_LIST_CNT; i++) {
 1731                 if (sc->wb_cdata.wb_rx_chain[i].wb_mbuf != NULL) {
 1732                         m_freem(sc->wb_cdata.wb_rx_chain[i].wb_mbuf);
 1733                         sc->wb_cdata.wb_rx_chain[i].wb_mbuf = NULL;
 1734                 }
 1735         }
 1736         bzero((char *)&sc->wb_ldata->wb_rx_list,
 1737                 sizeof(sc->wb_ldata->wb_rx_list));
 1738 
 1739         
 1740 
 1741 
 1742         for (i = 0; i < WB_TX_LIST_CNT; i++) {
 1743                 if (sc->wb_cdata.wb_tx_chain[i].wb_mbuf != NULL) {
 1744                         m_freem(sc->wb_cdata.wb_tx_chain[i].wb_mbuf);
 1745                         sc->wb_cdata.wb_tx_chain[i].wb_mbuf = NULL;
 1746                 }
 1747         }
 1748 
 1749         bzero((char *)&sc->wb_ldata->wb_tx_list,
 1750                 sizeof(sc->wb_ldata->wb_tx_list));
 1751 }
 1752 
 1753 
 1754 
 1755 
 1756 
 1757 void wb_shutdown(arg)
 1758         void                    *arg;
 1759 {
 1760         struct wb_softc         *sc = (struct wb_softc *)arg;
 1761 
 1762         wb_stop(sc);
 1763 
 1764         return;
 1765 }
 1766 
 1767 struct cfattach wb_ca = {
 1768         sizeof(struct wb_softc), wb_probe, wb_attach
 1769 };
 1770 
 1771 struct cfdriver wb_cd = {
 1772         0, "wb", DV_IFNET
 1773 };