LCOV - code coverage report
Current view: top level - dev/pci - if_lii.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 459 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 27 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if_lii.c,v 1.44 2017/01/22 10:17:38 dlg Exp $ */
       2             : 
       3             : /*
       4             :  *  Copyright (c) 2007 The NetBSD Foundation.
       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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      17             :  *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      18             :  *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      19             :  *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      20             :  *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      21             :  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      22             :  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      23             :  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      24             :  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      25             :  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      26             :  *  POSSIBILITY OF SUCH DAMAGE.
      27             :  */
      28             : 
      29             : /*
      30             :  * Driver for Attansic/Atheros's L2 Fast Ethernet controller
      31             :  */
      32             : 
      33             : #include "bpfilter.h"
      34             : 
      35             : #include <sys/param.h>
      36             : #include <sys/systm.h>
      37             : #include <sys/sockio.h>
      38             : #include <sys/mbuf.h>
      39             : #include <sys/kernel.h>
      40             : #include <sys/socket.h>
      41             : #include <sys/malloc.h>
      42             : #include <sys/device.h>
      43             : #include <sys/timeout.h>
      44             : 
      45             : #include <machine/bus.h>
      46             : 
      47             : #include <net/if.h>
      48             : #include <net/if_media.h>
      49             : 
      50             : #if NBPFILTER > 0
      51             : #include <net/bpf.h>
      52             : #endif
      53             : 
      54             : #include <netinet/in.h>
      55             : #include <netinet/if_ether.h>
      56             : 
      57             : #include <dev/mii/miivar.h>
      58             : 
      59             : #include <dev/pci/pcireg.h>
      60             : #include <dev/pci/pcivar.h>
      61             : #include <dev/pci/pcidevs.h>
      62             : 
      63             : #include <dev/pci/if_liireg.h>
      64             : 
      65             : /*#define LII_DEBUG*/
      66             : #ifdef LII_DEBUG
      67             : #define DPRINTF(x)      printf x
      68             : #else
      69             : #define DPRINTF(x)
      70             : #endif
      71             : 
      72             : struct lii_softc {
      73             :         struct device           sc_dev;
      74             :         pci_chipset_tag_t       sc_pc;
      75             :         pcitag_t                sc_tag;
      76             : 
      77             :         bus_space_tag_t         sc_mmiot;
      78             :         bus_space_handle_t      sc_mmioh;
      79             :         bus_size_t              sc_mmios;
      80             : 
      81             :         /*
      82             :          * We allocate a big chunk of DMA-safe memory for all data exchanges.
      83             :          * It is unfortunate that this chip doesn't seem to do scatter-gather.
      84             :          */
      85             :         bus_dma_tag_t           sc_dmat;
      86             :         bus_dmamap_t            sc_ringmap;
      87             :         bus_dma_segment_t       sc_ringseg;
      88             : 
      89             :         uint8_t                 *sc_ring; /* the whole area */
      90             :         size_t                  sc_ringsize;
      91             : 
      92             :         struct rx_pkt           *sc_rxp; /* the part used for RX */
      93             :         struct tx_pkt_status    *sc_txs; /* the parts used for TX */
      94             :         bus_addr_t              sc_txsp;
      95             :         char                    *sc_txdbase;
      96             :         bus_addr_t              sc_txdp;
      97             : 
      98             :         unsigned int            sc_rxcur;
      99             :         /* the active area is [ack; cur[ */
     100             :         int                     sc_txs_cur;
     101             :         int                     sc_txs_ack;
     102             :         int                     sc_txd_cur;
     103             :         int                     sc_txd_ack;
     104             :         int                     sc_free_tx_slots;
     105             : 
     106             :         void                    *sc_ih;
     107             : 
     108             :         struct arpcom           sc_ac;
     109             :         struct mii_data         sc_mii;
     110             :         struct timeout          sc_tick;
     111             : 
     112             :         int                     (*sc_memread)(struct lii_softc *, uint32_t,
     113             :                                      uint32_t *);
     114             : };
     115             : 
     116             : #define DEVNAME(_s)     ((_s)->sc_dev.dv_xname)
     117             : 
     118             : int     lii_match(struct device *, void *, void *);
     119             : void    lii_attach(struct device *, struct device *, void *);
     120             : int     lii_activate(struct device *, int);
     121             : 
     122             : struct cfdriver lii_cd = {
     123             :         0,
     124             :         "lii",
     125             :         DV_IFNET
     126             : };
     127             : 
     128             : struct cfattach lii_ca = {
     129             :         sizeof(struct lii_softc),
     130             :         lii_match,
     131             :         lii_attach,
     132             :         NULL,
     133             :         lii_activate
     134             : };
     135             : 
     136             : int     lii_reset(struct lii_softc *);
     137             : int     lii_eeprom_present(struct lii_softc *);
     138             : void    lii_read_macaddr(struct lii_softc *, uint8_t *);
     139             : int     lii_eeprom_read(struct lii_softc *, uint32_t, uint32_t *);
     140             : void    lii_spi_configure(struct lii_softc *);
     141             : int     lii_spi_read(struct lii_softc *, uint32_t, uint32_t *);
     142             : void    lii_iff(struct lii_softc *);
     143             : void    lii_tick(void *);
     144             : 
     145             : int     lii_alloc_rings(struct lii_softc *);
     146             : int     lii_free_tx_space(struct lii_softc *);
     147             : void    lii_tx_put(struct lii_softc *, struct mbuf *);
     148             : 
     149             : int     lii_mii_readreg(struct device *, int, int);
     150             : void    lii_mii_writereg(struct device *, int, int, int);
     151             : void    lii_mii_statchg(struct device *);
     152             : 
     153             : int     lii_media_change(struct ifnet *);
     154             : void    lii_media_status(struct ifnet *, struct ifmediareq *);
     155             : 
     156             : int     lii_init(struct ifnet *);
     157             : void    lii_start(struct ifnet *);
     158             : void    lii_stop(struct ifnet *);
     159             : void    lii_watchdog(struct ifnet *);
     160             : int     lii_ioctl(struct ifnet *, u_long, caddr_t);
     161             : 
     162             : int     lii_intr(void *);
     163             : void    lii_rxintr(struct lii_softc *);
     164             : void    lii_txintr(struct lii_softc *);
     165             : 
     166             : const struct pci_matchid lii_devices[] = {
     167             :         { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2 }
     168             : };
     169             : 
     170             : #define LII_READ_4(sc,reg) \
     171             :     bus_space_read_4((sc)->sc_mmiot, (sc)->sc_mmioh, (reg))
     172             : #define LII_READ_2(sc,reg) \
     173             :     bus_space_read_2((sc)->sc_mmiot, (sc)->sc_mmioh, (reg))
     174             : #define LII_READ_1(sc,reg) \
     175             :     bus_space_read_1((sc)->sc_mmiot, (sc)->sc_mmioh, (reg))
     176             : #define LII_WRITE_4(sc,reg,val) \
     177             :     bus_space_write_4((sc)->sc_mmiot, (sc)->sc_mmioh, (reg), (val))
     178             : #define LII_WRITE_2(sc,reg,val) \
     179             :     bus_space_write_2((sc)->sc_mmiot, (sc)->sc_mmioh, (reg), (val))
     180             : #define LII_WRITE_1(sc,reg,val) \
     181             :     bus_space_write_1((sc)->sc_mmiot, (sc)->sc_mmioh, (reg), (val))
     182             : 
     183             : /*
     184             :  * Those are the default Linux parameters.
     185             :  */
     186             : 
     187             : #define AT_TXD_NUM              64
     188             : #define AT_TXD_BUFFER_SIZE      8192
     189             : #define AT_RXD_NUM              64
     190             : 
     191             : /* Pad the RXD buffer so that the packets are on a 128-byte boundary. */
     192             : #define AT_RXD_PADDING          120
     193             : 
     194             : int
     195           0 : lii_match(struct device *parent, void *match, void *aux)
     196             : {
     197           0 :         return (pci_matchbyid((struct pci_attach_args *)aux, lii_devices,   
     198             :             nitems(lii_devices)));
     199             : }
     200             : 
     201             : void
     202           0 : lii_attach(struct device *parent, struct device *self, void *aux)
     203             : {
     204           0 :         struct lii_softc *sc = (struct lii_softc *)self;
     205           0 :         struct pci_attach_args *pa = aux;
     206           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
     207           0 :         pci_intr_handle_t ih;
     208             :         pcireg_t memtype;
     209             : 
     210           0 :         sc->sc_pc = pa->pa_pc;
     211           0 :         sc->sc_tag = pa->pa_tag;
     212           0 :         sc->sc_dmat = pa->pa_dmat;
     213             : 
     214           0 :         memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, PCI_MAPREG_START);
     215           0 :         if (pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0,  &sc->sc_mmiot, 
     216           0 :             &sc->sc_mmioh, NULL, &sc->sc_mmios, 0)) {
     217           0 :                 printf(": can't map mem space\n");
     218           0 :                 return;
     219             :         }
     220             : 
     221           0 :         if (lii_reset(sc))
     222             :                 goto unmap;
     223             : 
     224           0 :         lii_spi_configure(sc);
     225             : 
     226           0 :         if (lii_eeprom_present(sc))
     227           0 :                 sc->sc_memread = lii_eeprom_read;
     228             :         else
     229           0 :                 sc->sc_memread = lii_spi_read;
     230             : 
     231           0 :         lii_read_macaddr(sc, sc->sc_ac.ac_enaddr);
     232             : 
     233           0 :         if (pci_intr_map(pa, &ih) != 0) {
     234           0 :                 printf(": can't map interrupt\n");
     235           0 :                 goto unmap;
     236             :         }
     237           0 :         sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_NET,
     238           0 :             lii_intr, sc, DEVNAME(sc));
     239           0 :         if (sc->sc_ih == NULL) {
     240           0 :                 printf(": can't establish interrupt\n");
     241           0 :                 goto unmap;
     242             :         }
     243             : 
     244           0 :         if (lii_alloc_rings(sc))
     245             :                 goto deintr;
     246             : 
     247           0 :         printf(": %s, address %s\n", pci_intr_string(sc->sc_pc, ih),
     248           0 :             ether_sprintf(sc->sc_ac.ac_enaddr));
     249             : 
     250           0 :         timeout_set(&sc->sc_tick, lii_tick, sc);
     251             : 
     252           0 :         sc->sc_mii.mii_ifp = ifp;
     253           0 :         sc->sc_mii.mii_readreg = lii_mii_readreg;
     254           0 :         sc->sc_mii.mii_writereg = lii_mii_writereg;
     255           0 :         sc->sc_mii.mii_statchg = lii_mii_statchg;
     256           0 :         ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, lii_media_change,
     257             :             lii_media_status);
     258           0 :         mii_attach(self, &sc->sc_mii, 0xffffffff, 1,
     259             :             MII_OFFSET_ANY, 0);
     260           0 :         ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
     261             : 
     262           0 :         strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
     263           0 :         ifp->if_softc = sc;
     264           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     265           0 :         ifp->if_capabilities = IFCAP_VLAN_MTU;
     266           0 :         ifp->if_ioctl = lii_ioctl;
     267           0 :         ifp->if_start = lii_start;
     268           0 :         ifp->if_watchdog = lii_watchdog;
     269             : 
     270           0 :         if_attach(ifp);
     271           0 :         ether_ifattach(ifp);
     272             : 
     273           0 :         return;
     274             : 
     275             : deintr:
     276           0 :         pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
     277             : unmap:
     278           0 :         bus_space_unmap(sc->sc_mmiot, sc->sc_mmioh, sc->sc_mmios);
     279           0 :         return;
     280           0 : }
     281             : 
     282             : int
     283           0 : lii_activate(struct device *self, int act)
     284             : {
     285           0 :         struct lii_softc *sc = (struct lii_softc *)self;
     286           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
     287             :         int rv = 0;
     288             : 
     289           0 :         switch (act) {
     290             :         case DVACT_SUSPEND:
     291           0 :                 if (ifp->if_flags & IFF_RUNNING)
     292           0 :                         lii_stop(ifp);
     293           0 :                 rv = config_activate_children(self, act);
     294           0 :                 break;
     295             :         case DVACT_RESUME:
     296           0 :                 if (ifp->if_flags & IFF_UP)
     297           0 :                         lii_init(ifp);
     298             :                 break;
     299             :         default:
     300           0 :                 rv = config_activate_children(self, act);
     301           0 :                 break;
     302             :         }
     303           0 :         return (rv);
     304             : }
     305             : 
     306             : int
     307           0 : lii_reset(struct lii_softc *sc)
     308             : {
     309             :         int i;
     310             : 
     311             :         DPRINTF(("lii_reset\n"));
     312             : 
     313           0 :         LII_WRITE_4(sc, LII_SMC, SMC_SOFT_RST);
     314           0 :         DELAY(1000);
     315             : 
     316           0 :         for (i = 0; i < 10; ++i) {
     317           0 :                 if (LII_READ_4(sc, LII_BIS) == 0)
     318             :                         break;
     319           0 :                 DELAY(1000);
     320             :         }
     321             : 
     322           0 :         if (i == 10) {
     323           0 :                 printf("%s: reset failed\n", DEVNAME(sc));
     324           0 :                 return 1;
     325             :         }
     326             : 
     327           0 :         LII_WRITE_4(sc, LII_PHYC, PHYC_ENABLE);
     328           0 :         DELAY(10);
     329             : 
     330             :         /* Init PCI-Express module */
     331             :         /* Magic Numbers Warning */
     332           0 :         LII_WRITE_4(sc, 0x12fc, 0x00006500);
     333           0 :         LII_WRITE_4(sc, 0x1008, 0x00008000 |
     334             :             LII_READ_4(sc, 0x1008));
     335             : 
     336           0 :         return 0;
     337           0 : }
     338             : 
     339             : int
     340           0 : lii_eeprom_present(struct lii_softc *sc)
     341             : {
     342             :         uint32_t val;
     343             : 
     344           0 :         val = LII_READ_4(sc, LII_SFC);
     345           0 :         if (val & SFC_EN_VPD)
     346           0 :                 LII_WRITE_4(sc, LII_SFC, val & ~(SFC_EN_VPD));
     347             : 
     348           0 :         return pci_get_capability(sc->sc_pc, sc->sc_tag, PCI_CAP_VPD,
     349           0 :             NULL, NULL) == 1;
     350             : }
     351             : 
     352             : int
     353           0 : lii_eeprom_read(struct lii_softc *sc, uint32_t reg, uint32_t *val)
     354             : {
     355           0 :         return pci_vpd_read(sc->sc_pc, sc->sc_tag, reg, 1, (pcireg_t *)val);
     356             : }
     357             : 
     358             : void
     359           0 : lii_spi_configure(struct lii_softc *sc)
     360             : {
     361             :         /*
     362             :          * We don't offer a way to configure the SPI Flash vendor parameter, so
     363             :          * the table is given for reference
     364             :          */
     365             :         static const struct lii_spi_flash_vendor {
     366             :             const char *sfv_name;
     367             :             const uint8_t sfv_opcodes[9];
     368             :         } lii_sfv[] = {
     369             :             { "Atmel", { 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52, 0x62 } },
     370             :             { "SST",   { 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20, 0x60 } },
     371             :             { "ST",    { 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xab, 0xd8, 0xc7 } },
     372             :         };
     373             : #define SF_OPCODE_WRSR  0
     374             : #define SF_OPCODE_READ  1
     375             : #define SF_OPCODE_PRGM  2
     376             : #define SF_OPCODE_WREN  3
     377             : #define SF_OPCODE_WRDI  4
     378             : #define SF_OPCODE_RDSR  5
     379             : #define SF_OPCODE_RDID  6
     380             : #define SF_OPCODE_SECT_ER       7
     381             : #define SF_OPCODE_CHIP_ER       8
     382             : 
     383             : #define SF_DEFAULT_VENDOR       0
     384             :         static const uint8_t vendor = SF_DEFAULT_VENDOR;
     385             : 
     386             :         /*
     387             :          * Why isn't WRDI used?  Heck if I know.
     388             :          */
     389             : 
     390           0 :         LII_WRITE_1(sc, LII_SFOP_WRSR,
     391             :             lii_sfv[vendor].sfv_opcodes[SF_OPCODE_WRSR]);
     392           0 :         LII_WRITE_1(sc, LII_SFOP_READ,
     393             :             lii_sfv[vendor].sfv_opcodes[SF_OPCODE_READ]);
     394           0 :         LII_WRITE_1(sc, LII_SFOP_PROGRAM,
     395             :             lii_sfv[vendor].sfv_opcodes[SF_OPCODE_PRGM]);
     396           0 :         LII_WRITE_1(sc, LII_SFOP_WREN,
     397             :             lii_sfv[vendor].sfv_opcodes[SF_OPCODE_WREN]);
     398           0 :         LII_WRITE_1(sc, LII_SFOP_RDSR,
     399             :             lii_sfv[vendor].sfv_opcodes[SF_OPCODE_RDSR]);
     400           0 :         LII_WRITE_1(sc, LII_SFOP_RDID,
     401             :             lii_sfv[vendor].sfv_opcodes[SF_OPCODE_RDID]);
     402           0 :         LII_WRITE_1(sc, LII_SFOP_SC_ERASE,
     403             :             lii_sfv[vendor].sfv_opcodes[SF_OPCODE_SECT_ER]);
     404           0 :         LII_WRITE_1(sc, LII_SFOP_CHIP_ERASE,
     405             :             lii_sfv[vendor].sfv_opcodes[SF_OPCODE_CHIP_ER]);
     406           0 : }
     407             : 
     408             : #define MAKE_SFC(cssetup, clkhi, clklo, cshold, cshi, ins) \
     409             :     ( (((cssetup) & SFC_CS_SETUP_MASK)      \
     410             :         << SFC_CS_SETUP_SHIFT)            \
     411             :     | (((clkhi) & SFC_CLK_HI_MASK)  \
     412             :         << SFC_CLK_HI_SHIFT)              \
     413             :     | (((clklo) & SFC_CLK_LO_MASK)  \
     414             :         << SFC_CLK_LO_SHIFT)              \
     415             :     | (((cshold) & SFC_CS_HOLD_MASK)        \
     416             :         << SFC_CS_HOLD_SHIFT)             \
     417             :     | (((cshi) & SFC_CS_HI_MASK)    \
     418             :         << SFC_CS_HI_SHIFT)               \
     419             :     | (((ins) & SFC_INS_MASK)               \
     420             :         << SFC_INS_SHIFT))
     421             : 
     422             : #define CUSTOM_SPI_CS_SETUP     2
     423             : #define CUSTOM_SPI_CLK_HI       2
     424             : #define CUSTOM_SPI_CLK_LO       2
     425             : #define CUSTOM_SPI_CS_HOLD      2
     426             : #define CUSTOM_SPI_CS_HI        3
     427             : 
     428             : int
     429           0 : lii_spi_read(struct lii_softc *sc, uint32_t reg, uint32_t *val)
     430             : {
     431             :         uint32_t v;
     432             :         int i;
     433             : 
     434           0 :         LII_WRITE_4(sc, LII_SF_DATA, 0);
     435           0 :         LII_WRITE_4(sc, LII_SF_ADDR, reg);
     436             : 
     437             :         v = SFC_WAIT_READY |
     438             :             MAKE_SFC(CUSTOM_SPI_CS_SETUP, CUSTOM_SPI_CLK_HI,
     439             :                  CUSTOM_SPI_CLK_LO, CUSTOM_SPI_CS_HOLD, CUSTOM_SPI_CS_HI, 1);
     440             : 
     441           0 :         LII_WRITE_4(sc, LII_SFC, v);
     442             :         v |= SFC_START;
     443           0 :         LII_WRITE_4(sc, LII_SFC, v);
     444             : 
     445           0 :         for (i = 0; i < 10; ++i) {
     446           0 :                 DELAY(1000);
     447           0 :                 if (!(LII_READ_4(sc, LII_SFC) & SFC_START))
     448             :                         break;
     449             :         }
     450           0 :         if (i == 10)
     451           0 :                 return EBUSY;
     452             : 
     453           0 :         *val = LII_READ_4(sc, LII_SF_DATA);
     454           0 :         return 0;
     455           0 : }
     456             : 
     457             : void
     458           0 : lii_read_macaddr(struct lii_softc *sc, uint8_t *ea)
     459             : {
     460             :         uint32_t offset = 0x100;
     461           0 :         uint32_t val, val1, addr0 = 0, addr1 = 0;
     462             :         uint8_t found = 0;
     463             : 
     464           0 :         while ((*sc->sc_memread)(sc, offset, &val) == 0) {
     465           0 :                 offset += 4;
     466             : 
     467             :                 /* Each chunk of data starts with a signature */
     468           0 :                 if ((val & 0xff) != 0x5a)
     469             :                         break;
     470           0 :                 if ((*sc->sc_memread)(sc, offset, &val1))
     471             :                         break;
     472             : 
     473           0 :                 offset += 4;
     474             : 
     475           0 :                 val >>= 16;
     476           0 :                 switch (val) {
     477             :                 case LII_MAC_ADDR_0:
     478           0 :                         addr0 = val1;
     479           0 :                         ++found;
     480           0 :                         break;
     481             :                 case LII_MAC_ADDR_1:
     482           0 :                         addr1 = val1;
     483           0 :                         ++found;
     484           0 :                         break;
     485             :                 default:
     486           0 :                         continue;
     487             :                 }
     488             :         }
     489             : 
     490             : #ifdef LII_DEBUG
     491             :         if (found < 2)
     492             :                 printf(": error reading MAC address, using registers...\n");
     493             : #endif
     494             : 
     495             :         addr0 = htole32(addr0);
     496             :         addr1 = htole32(addr1);
     497             : 
     498           0 :         if ((addr0 == 0xffffff && (addr1 & 0xffff) == 0xffff) ||
     499           0 :             (addr0 == 0 && (addr1 & 0xffff) == 0)) {
     500           0 :                 addr0 = htole32(LII_READ_4(sc, LII_MAC_ADDR_0));
     501           0 :                 addr1 = htole32(LII_READ_4(sc, LII_MAC_ADDR_1));
     502           0 :         }
     503             : 
     504           0 :         ea[0] = (addr1 & 0x0000ff00) >> 8;
     505           0 :         ea[1] = (addr1 & 0x000000ff);
     506           0 :         ea[2] = (addr0 & 0xff000000) >> 24;
     507           0 :         ea[3] = (addr0 & 0x00ff0000) >> 16;
     508           0 :         ea[4] = (addr0 & 0x0000ff00) >> 8;
     509           0 :         ea[5] = (addr0 & 0x000000ff);
     510           0 : }
     511             : 
     512             : int
     513           0 : lii_mii_readreg(struct device *dev, int phy, int reg)
     514             : {
     515           0 :         struct lii_softc *sc = (struct lii_softc *)dev;
     516             :         uint32_t val;
     517             :         int i;
     518             : 
     519           0 :         val = (reg & MDIOC_REG_MASK) << MDIOC_REG_SHIFT;
     520             : 
     521           0 :         val |= MDIOC_START | MDIOC_SUP_PREAMBLE;
     522             :         val |= MDIOC_CLK_25_4 << MDIOC_CLK_SEL_SHIFT;
     523             : 
     524           0 :         val |= MDIOC_READ;
     525             : 
     526           0 :         LII_WRITE_4(sc, LII_MDIOC, val);
     527             : 
     528           0 :         for (i = 0; i < MDIO_WAIT_TIMES; ++i) {
     529           0 :                 DELAY(2);
     530           0 :                 val = LII_READ_4(sc, LII_MDIOC);
     531           0 :                 if ((val & (MDIOC_START | MDIOC_BUSY)) == 0)
     532             :                         break;
     533             :         }
     534             : 
     535           0 :         if (i == MDIO_WAIT_TIMES) {
     536           0 :                 printf("%s: timeout reading PHY %d reg %d\n", DEVNAME(sc), phy,
     537             :                     reg);
     538           0 :         }
     539             : 
     540           0 :         return (val & 0x0000ffff);
     541             : }
     542             : 
     543             : void
     544           0 : lii_mii_writereg(struct device *dev, int phy, int reg, int data)
     545             : {
     546           0 :         struct lii_softc *sc = (struct lii_softc *)dev;
     547             :         uint32_t val;
     548             :         int i;
     549             : 
     550           0 :         val = (reg & MDIOC_REG_MASK) << MDIOC_REG_SHIFT;
     551           0 :         val |= (data & MDIOC_DATA_MASK) << MDIOC_DATA_SHIFT;
     552             : 
     553           0 :         val |= MDIOC_START | MDIOC_SUP_PREAMBLE;
     554             :         val |= MDIOC_CLK_25_4 << MDIOC_CLK_SEL_SHIFT;
     555             : 
     556             :         /* val |= MDIOC_WRITE; */
     557             : 
     558           0 :         LII_WRITE_4(sc, LII_MDIOC, val);
     559             : 
     560           0 :         for (i = 0; i < MDIO_WAIT_TIMES; ++i) {
     561           0 :                 DELAY(2);
     562           0 :                 val = LII_READ_4(sc, LII_MDIOC);
     563           0 :                 if ((val & (MDIOC_START | MDIOC_BUSY)) == 0)
     564             :                         break;
     565             :         }
     566             : 
     567           0 :         if (i == MDIO_WAIT_TIMES) {
     568           0 :                 printf("%s: timeout writing PHY %d reg %d\n", DEVNAME(sc), phy,
     569             :                     reg);
     570           0 :         }
     571           0 : }
     572             : 
     573             : void
     574           0 : lii_mii_statchg(struct device *dev)
     575             : {
     576           0 :         struct lii_softc *sc = (struct lii_softc *)dev;
     577             :         uint32_t val;
     578             : 
     579             :         DPRINTF(("lii_mii_statchg\n"));
     580             : 
     581           0 :         val = LII_READ_4(sc, LII_MACC);
     582             : 
     583           0 :         if ((sc->sc_mii.mii_media_active & IFM_GMASK) == IFM_FDX)
     584           0 :                 val |= MACC_FDX;
     585             :         else
     586           0 :                 val &= ~MACC_FDX;
     587             : 
     588           0 :         LII_WRITE_4(sc, LII_MACC, val);
     589           0 : }
     590             : 
     591             : int
     592           0 : lii_media_change(struct ifnet *ifp)
     593             : {
     594           0 :         struct lii_softc *sc = ifp->if_softc;
     595             : 
     596             :         DPRINTF(("lii_media_change\n"));
     597             : 
     598           0 :         if (ifp->if_flags & IFF_UP)
     599           0 :                 mii_mediachg(&sc->sc_mii);
     600           0 :         return 0;
     601             : }
     602             : 
     603             : void
     604           0 : lii_media_status(struct ifnet *ifp, struct ifmediareq *imr)
     605             : {
     606           0 :         struct lii_softc *sc = ifp->if_softc;
     607             : 
     608             :         DPRINTF(("lii_media_status\n"));
     609             : 
     610           0 :         mii_pollstat(&sc->sc_mii);
     611           0 :         imr->ifm_status = sc->sc_mii.mii_media_status;
     612           0 :         imr->ifm_active = sc->sc_mii.mii_media_active;
     613           0 : }
     614             : 
     615             : int
     616           0 : lii_init(struct ifnet *ifp)
     617             : {
     618           0 :         struct lii_softc *sc = ifp->if_softc;
     619             :         uint32_t val;
     620             :         int error;
     621             : 
     622             :         DPRINTF(("lii_init\n"));
     623             : 
     624           0 :         lii_stop(ifp);
     625             : 
     626           0 :         memset(sc->sc_ring, 0, sc->sc_ringsize);
     627             : 
     628             :         /* Disable all interrupts */
     629           0 :         LII_WRITE_4(sc, LII_ISR, 0xffffffff);
     630             : 
     631           0 :         LII_WRITE_4(sc, LII_DESC_BASE_ADDR_HI, 0);
     632             : /* XXX
     633             :             sc->sc_ringmap->dm_segs[0].ds_addr >> 32);
     634             : */
     635           0 :         LII_WRITE_4(sc, LII_RXD_BASE_ADDR_LO,
     636             :             (sc->sc_ringmap->dm_segs[0].ds_addr & 0xffffffff)
     637             :             + AT_RXD_PADDING);
     638           0 :         LII_WRITE_4(sc, LII_TXS_BASE_ADDR_LO,
     639             :             sc->sc_txsp & 0xffffffff);
     640           0 :         LII_WRITE_4(sc, LII_TXD_BASE_ADDR_LO,
     641             :             sc->sc_txdp & 0xffffffff);
     642             : 
     643           0 :         LII_WRITE_2(sc, LII_TXD_BUFFER_SIZE, AT_TXD_BUFFER_SIZE / 4);
     644           0 :         LII_WRITE_2(sc, LII_TXS_NUM_ENTRIES, AT_TXD_NUM);
     645           0 :         LII_WRITE_2(sc, LII_RXD_NUM_ENTRIES, AT_RXD_NUM);
     646             : 
     647             :         /*
     648             :          * Inter Paket Gap Time = 0x60 (IPGT)
     649             :          * Minimum inter-frame gap for RX = 0x50 (MIFG)
     650             :          * 64-bit Carrier-Sense window = 0x40 (IPGR1)
     651             :          * 96-bit IPG window = 0x60 (IPGR2)
     652             :          */
     653           0 :         LII_WRITE_4(sc, LII_MIPFG, 0x60405060);
     654             : 
     655             :         /*
     656             :          * Collision window = 0x37 (LCOL)
     657             :          * Maximum # of retrans = 0xf (RETRY)
     658             :          * Maximum binary expansion # = 0xa (ABEBT)
     659             :          * IPG to start jam = 0x7 (JAMIPG)
     660             :         */
     661           0 :         LII_WRITE_4(sc, LII_MHDC, 0x07a0f037 |
     662             :              MHDC_EXC_DEF_EN);
     663             : 
     664             :         /* 100 means 200us */
     665           0 :         LII_WRITE_2(sc, LII_IMTIV, 100);
     666           0 :         LII_WRITE_2(sc, LII_SMC, SMC_ITIMER_EN);
     667             : 
     668             :         /* 500000 means 100ms */
     669           0 :         LII_WRITE_2(sc, LII_IALTIV, 50000);
     670             : 
     671           0 :         LII_WRITE_4(sc, LII_MTU, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
     672             : 
     673             :         /* unit unknown for TX cur-through threshold */
     674           0 :         LII_WRITE_4(sc, LII_TX_CUT_THRESH, 0x177);
     675             : 
     676           0 :         LII_WRITE_2(sc, LII_PAUSE_ON_TH, AT_RXD_NUM * 7 / 8);
     677           0 :         LII_WRITE_2(sc, LII_PAUSE_OFF_TH, AT_RXD_NUM / 12);
     678             : 
     679           0 :         sc->sc_rxcur = 0;
     680           0 :         sc->sc_txs_cur = sc->sc_txs_ack = 0;
     681           0 :         sc->sc_txd_cur = sc->sc_txd_ack = 0;
     682           0 :         sc->sc_free_tx_slots = 1;
     683           0 :         LII_WRITE_2(sc, LII_MB_TXD_WR_IDX, sc->sc_txd_cur);
     684           0 :         LII_WRITE_2(sc, LII_MB_RXD_RD_IDX, sc->sc_rxcur);
     685             : 
     686           0 :         LII_WRITE_1(sc, LII_DMAR, DMAR_EN);
     687           0 :         LII_WRITE_1(sc, LII_DMAW, DMAW_EN);
     688             : 
     689           0 :         LII_WRITE_4(sc, LII_SMC, LII_READ_4(sc, LII_SMC) | SMC_MANUAL_INT);
     690             : 
     691           0 :         error = ((LII_READ_4(sc, LII_ISR) & ISR_PHY_LINKDOWN) != 0);
     692           0 :         LII_WRITE_4(sc, LII_ISR, 0x3fffffff);
     693           0 :         LII_WRITE_4(sc, LII_ISR, 0);
     694           0 :         if (error) {
     695           0 :                 printf("%s: init failed\n", DEVNAME(sc));
     696           0 :                 goto out;
     697             :         }
     698             : 
     699             :         /*
     700             :          * Initialise MAC. 
     701             :          */
     702           0 :         val = LII_READ_4(sc, LII_MACC) & MACC_FDX;
     703             : 
     704           0 :         val |= MACC_RX_EN | MACC_TX_EN | MACC_MACLP_CLK_PHY |
     705             :             MACC_TX_FLOW_EN | MACC_RX_FLOW_EN | MACC_ADD_CRC |
     706             :             MACC_PAD;
     707             : 
     708           0 :         val |= 7 << MACC_PREAMBLE_LEN_SHIFT;
     709           0 :         val |= 2 << MACC_HDX_LEFT_BUF_SHIFT;
     710             : 
     711           0 :         LII_WRITE_4(sc, LII_MACC, val);
     712             : 
     713             :         /* Set the hardware MAC address. */
     714           0 :         LII_WRITE_4(sc, LII_MAC_ADDR_0, letoh32((sc->sc_ac.ac_enaddr[2] << 24) |
     715             :             (sc->sc_ac.ac_enaddr[3] << 16) | (sc->sc_ac.ac_enaddr[4] << 8) |
     716             :             sc->sc_ac.ac_enaddr[5]));
     717           0 :         LII_WRITE_4(sc, LII_MAC_ADDR_1,
     718             :             letoh32((sc->sc_ac.ac_enaddr[0] << 8) | sc->sc_ac.ac_enaddr[1]));
     719             : 
     720             :         /* Program promiscuous mode and multicast filters. */
     721           0 :         lii_iff(sc);
     722             : 
     723           0 :         mii_mediachg(&sc->sc_mii);
     724             : 
     725           0 :         LII_WRITE_4(sc, LII_IMR, IMR_NORMAL_MASK);
     726             : 
     727           0 :         timeout_add_sec(&sc->sc_tick, 1);
     728             : 
     729           0 :         ifp->if_flags |= IFF_RUNNING;
     730           0 :         ifq_clr_oactive(&ifp->if_snd);
     731             : 
     732             : out:
     733           0 :         return error;
     734             : }
     735             : 
     736             : void
     737           0 : lii_tx_put(struct lii_softc *sc, struct mbuf *m)
     738             : {
     739             :         int left;
     740             :         struct tx_pkt_header *tph =
     741           0 :             (struct tx_pkt_header *)(sc->sc_txdbase + sc->sc_txd_cur);
     742             : 
     743           0 :         memset(tph, 0, sizeof *tph);
     744           0 :         tph->txph_size = m->m_pkthdr.len;
     745             : 
     746           0 :         sc->sc_txd_cur = (sc->sc_txd_cur + 4) % AT_TXD_BUFFER_SIZE;
     747             : 
     748             :         /*
     749             :          * We already know we have enough space, so if there is a part of the
     750             :          * space ahead of txd_cur that is active, it doesn't matter because
     751             :          * left will be large enough even without it.
     752             :          */
     753           0 :         left  = AT_TXD_BUFFER_SIZE - sc->sc_txd_cur;
     754             : 
     755           0 :         if (left > m->m_pkthdr.len) {
     756           0 :                 m_copydata(m, 0, m->m_pkthdr.len,
     757           0 :                     sc->sc_txdbase + sc->sc_txd_cur);
     758           0 :                 sc->sc_txd_cur += m->m_pkthdr.len;
     759           0 :         } else {
     760           0 :                 m_copydata(m, 0, left, sc->sc_txdbase + sc->sc_txd_cur);
     761           0 :                 m_copydata(m, left, m->m_pkthdr.len - left, sc->sc_txdbase);
     762           0 :                 sc->sc_txd_cur = m->m_pkthdr.len - left;
     763             :         }
     764             : 
     765             :         /* Round to a 32-bit boundary */
     766           0 :         sc->sc_txd_cur = ((sc->sc_txd_cur + 3) & ~3) % AT_TXD_BUFFER_SIZE;
     767           0 :         if (sc->sc_txd_cur == sc->sc_txd_ack)
     768           0 :                 sc->sc_free_tx_slots = 0;
     769           0 : }
     770             : 
     771             : int
     772           0 : lii_free_tx_space(struct lii_softc *sc)
     773             : {
     774             :         int space;
     775             : 
     776           0 :         if (sc->sc_txd_cur >= sc->sc_txd_ack)
     777           0 :                 space = (AT_TXD_BUFFER_SIZE - sc->sc_txd_cur) +
     778             :                     sc->sc_txd_ack;
     779             :         else
     780           0 :                 space = sc->sc_txd_ack - sc->sc_txd_cur;
     781             : 
     782             :         /* Account for the tx_pkt_header */
     783           0 :         return (space - 4);
     784             : }
     785             : 
     786             : void
     787           0 : lii_start(struct ifnet *ifp)
     788             : {
     789           0 :         struct lii_softc *sc = ifp->if_softc;
     790             :         struct mbuf *m0;
     791             : 
     792             :         DPRINTF(("lii_start\n"));
     793             : 
     794           0 :         if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
     795           0 :                 return;
     796             : 
     797           0 :         for (;;) {
     798           0 :                 m0 = ifq_deq_begin(&ifp->if_snd);
     799           0 :                 if (m0 == NULL)
     800             :                         break;
     801             : 
     802           0 :                 if (!sc->sc_free_tx_slots ||
     803           0 :                     lii_free_tx_space(sc) < m0->m_pkthdr.len) {
     804           0 :                         ifq_deq_rollback(&ifp->if_snd, m0);
     805           0 :                         ifq_set_oactive(&ifp->if_snd);
     806           0 :                         break;
     807             :                 }
     808             : 
     809           0 :                 lii_tx_put(sc, m0);
     810             : 
     811             :                 DPRINTF(("lii_start: put %d\n", sc->sc_txs_cur));
     812             : 
     813           0 :                 sc->sc_txs[sc->sc_txs_cur].txps_update = 0;
     814           0 :                 sc->sc_txs_cur = (sc->sc_txs_cur + 1) % AT_TXD_NUM;
     815           0 :                 if (sc->sc_txs_cur == sc->sc_txs_ack)
     816           0 :                         sc->sc_free_tx_slots = 0;
     817             : 
     818           0 :                 LII_WRITE_2(sc, LII_MB_TXD_WR_IDX, sc->sc_txd_cur/4);
     819             : 
     820           0 :                 ifq_deq_commit(&ifp->if_snd, m0);
     821             : 
     822             : #if NBPFILTER > 0
     823           0 :                 if (ifp->if_bpf != NULL)
     824           0 :                         bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
     825             : #endif
     826           0 :                 m_freem(m0);
     827             :         }
     828           0 : }
     829             : 
     830             : void
     831           0 : lii_stop(struct ifnet *ifp)
     832             : {
     833           0 :         struct lii_softc *sc = ifp->if_softc;
     834             : 
     835           0 :         timeout_del(&sc->sc_tick);
     836             : 
     837           0 :         ifp->if_timer = 0;
     838           0 :         ifp->if_flags &= ~IFF_RUNNING;
     839           0 :         ifq_clr_oactive(&ifp->if_snd);
     840             : 
     841           0 :         mii_down(&sc->sc_mii);
     842             : 
     843           0 :         lii_reset(sc);
     844             : 
     845           0 :         LII_WRITE_4(sc, LII_IMR, 0);
     846           0 : }
     847             : 
     848             : int
     849           0 : lii_intr(void *v)
     850             : {
     851           0 :         struct lii_softc *sc = v;
     852             :         uint32_t status;
     853             : 
     854           0 :         status = LII_READ_4(sc, LII_ISR);
     855           0 :         if (status == 0)
     856           0 :                 return 0;
     857             : 
     858             :         DPRINTF(("lii_intr (%x)\n", status));
     859             : 
     860             :         /* Clear the interrupt and disable them */
     861           0 :         LII_WRITE_4(sc, LII_ISR, status | ISR_DIS_INT);
     862             : 
     863           0 :         if (status & (ISR_PHY | ISR_MANUAL)) {
     864             :                 /* Ack PHY interrupt.  Magic register */
     865           0 :                 if (status & ISR_PHY)
     866           0 :                         (void)lii_mii_readreg(&sc->sc_dev, 1, 19);
     867           0 :                 mii_mediachg(&sc->sc_mii);
     868           0 :         }
     869             : 
     870           0 :         if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST | ISR_PHY_LINKDOWN)) {
     871           0 :                 lii_init(&sc->sc_ac.ac_if);
     872           0 :                 return 1;
     873             :         }
     874             : 
     875           0 :         if (status & ISR_RX_EVENT) {
     876             : #ifdef LII_DEBUG
     877             :                 if (!(status & ISR_RS_UPDATE))
     878             :                         printf("rxintr %08x\n", status);
     879             : #endif
     880           0 :                 lii_rxintr(sc);
     881           0 :         }
     882             : 
     883           0 :         if (status & ISR_TX_EVENT)
     884           0 :                 lii_txintr(sc);
     885             : 
     886             :         /* Re-enable interrupts */
     887           0 :         LII_WRITE_4(sc, LII_ISR, 0);
     888             : 
     889           0 :         return 1;
     890           0 : }
     891             : 
     892             : void
     893           0 : lii_rxintr(struct lii_softc *sc)
     894             : {
     895           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
     896           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
     897             :         struct rx_pkt *rxp;
     898             :         struct mbuf *m;
     899             :         uint16_t size;
     900             : 
     901             :         DPRINTF(("lii_rxintr\n"));
     902             : 
     903           0 :         for (;;) {
     904           0 :                 rxp = &sc->sc_rxp[sc->sc_rxcur];
     905           0 :                 if (rxp->rxp_update == 0)
     906             :                         break;
     907             : 
     908             :                 DPRINTF(("lii_rxintr: getting %u (%u) [%x]\n", sc->sc_rxcur,
     909             :                     rxp->rxp_size, rxp->rxp_flags));
     910           0 :                 sc->sc_rxcur = (sc->sc_rxcur + 1) % AT_RXD_NUM;
     911           0 :                 rxp->rxp_update = 0;
     912           0 :                 if (!(rxp->rxp_flags & LII_RXF_SUCCESS)) {
     913           0 :                         ++ifp->if_ierrors;
     914           0 :                         continue;
     915             :                 }
     916             : 
     917           0 :                 MGETHDR(m, M_DONTWAIT, MT_DATA);
     918           0 :                 if (m == NULL) {
     919           0 :                         ++ifp->if_ierrors;
     920           0 :                         continue;
     921             :                 }
     922           0 :                 size = rxp->rxp_size - ETHER_CRC_LEN;
     923           0 :                 if (size > MHLEN) {
     924           0 :                         MCLGET(m, M_DONTWAIT);
     925           0 :                         if ((m->m_flags & M_EXT) == 0) {
     926           0 :                                 m_freem(m);
     927           0 :                                 ++ifp->if_ierrors;
     928           0 :                                 continue;
     929             :                         }
     930             :                 }
     931             : 
     932             :                 /* Copy the packet withhout the FCS */
     933           0 :                 m->m_pkthdr.len = m->m_len = size;
     934           0 :                 memcpy(mtod(m, void *), &rxp->rxp_data[0], size);
     935             : 
     936           0 :                 ml_enqueue(&ml, m);
     937             :         }
     938             : 
     939           0 :         if_input(ifp, &ml);
     940             : 
     941           0 :         LII_WRITE_4(sc, LII_MB_RXD_RD_IDX, sc->sc_rxcur);
     942           0 : }
     943             : 
     944             : void
     945           0 : lii_txintr(struct lii_softc *sc)
     946             : {
     947           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
     948             :         struct tx_pkt_status *txs;
     949             :         struct tx_pkt_header *txph;
     950             : 
     951             :         DPRINTF(("lii_txintr\n"));
     952             : 
     953           0 :         for (;;) {
     954           0 :                 txs = &sc->sc_txs[sc->sc_txs_ack];
     955           0 :                 if (txs->txps_update == 0)
     956             :                         break;
     957             :                 DPRINTF(("lii_txintr: ack'd %d\n", sc->sc_txs_ack));
     958           0 :                 sc->sc_txs_ack = (sc->sc_txs_ack + 1) % AT_TXD_NUM;
     959           0 :                 sc->sc_free_tx_slots = 1;
     960             : 
     961           0 :                 txs->txps_update = 0;
     962             : 
     963           0 :                 txph =  (struct tx_pkt_header *)
     964           0 :                     (sc->sc_txdbase + sc->sc_txd_ack);
     965             : 
     966           0 :                 if (txph->txph_size != txs->txps_size) {
     967           0 :                         printf("%s: mismatched status and packet\n",
     968           0 :                             DEVNAME(sc));
     969           0 :                 }
     970             : 
     971             :                 /*
     972             :                  * Move ack by the packet size, taking the packet header in
     973             :                  * account and round to the next 32-bit boundary
     974             :                  * (7 = sizeof(header) + 3)
     975             :                  */
     976           0 :                 sc->sc_txd_ack = (sc->sc_txd_ack + txph->txph_size + 7 ) & ~3;
     977           0 :                 sc->sc_txd_ack %= AT_TXD_BUFFER_SIZE;
     978             : 
     979           0 :                 if (!ISSET(txs->txps_flags, LII_TXF_SUCCESS))
     980           0 :                         ++ifp->if_oerrors;
     981           0 :                 ifq_clr_oactive(&ifp->if_snd);
     982             :         }
     983             : 
     984           0 :         if (sc->sc_free_tx_slots)
     985           0 :                 lii_start(ifp);
     986           0 : }
     987             : 
     988             : int
     989           0 : lii_alloc_rings(struct lii_softc *sc)
     990             : {
     991           0 :         int nsegs;
     992             :         bus_size_t bs;
     993             : 
     994             :         /*
     995             :          * We need a big chunk of DMA-friendly memory because descriptors
     996             :          * are not separate from data on that crappy hardware, which means
     997             :          * we'll have to copy data from and to that memory zone to and from
     998             :          * the mbufs.
     999             :          *
    1000             :          * How lame is that?  Using the default values from the Linux driver,
    1001             :          * we allocate space for receiving up to 64 full-size Ethernet frames,
    1002             :          * and only 8kb for transmitting up to 64 Ethernet frames.
    1003             :          */
    1004             : 
    1005           0 :         sc->sc_ringsize = bs = AT_RXD_PADDING
    1006             :             + AT_RXD_NUM * sizeof(struct rx_pkt)
    1007             :             + AT_TXD_NUM * sizeof(struct tx_pkt_status)
    1008             :             + AT_TXD_BUFFER_SIZE;
    1009             : 
    1010           0 :         if (bus_dmamap_create(sc->sc_dmat, bs, 1, bs, (1<<30),
    1011           0 :             BUS_DMA_NOWAIT, &sc->sc_ringmap) != 0) {
    1012           0 :                 printf(": failed to create DMA map\n");
    1013           0 :                 return 1;
    1014             :         }
    1015             : 
    1016           0 :         if (bus_dmamem_alloc(sc->sc_dmat, bs, PAGE_SIZE, (1<<30),
    1017           0 :             &sc->sc_ringseg, 1, &nsegs, BUS_DMA_NOWAIT) != 0) {
    1018           0 :                 printf(": failed to allocate DMA memory\n");
    1019           0 :                 goto destroy;
    1020             :         }
    1021             : 
    1022           0 :         if (bus_dmamem_map(sc->sc_dmat, &sc->sc_ringseg, nsegs, bs,
    1023           0 :             (caddr_t *)&sc->sc_ring, BUS_DMA_NOWAIT) != 0) {
    1024           0 :                 printf(": failed to map DMA memory\n");
    1025           0 :                 goto free;
    1026             :         }
    1027             : 
    1028           0 :         if (bus_dmamap_load(sc->sc_dmat, sc->sc_ringmap, sc->sc_ring,
    1029           0 :             bs, NULL, BUS_DMA_NOWAIT) != 0) {
    1030           0 :                 printf(": failed to load DMA memory\n");
    1031             :                 goto unmap;
    1032             :         }
    1033             : 
    1034           0 :         sc->sc_rxp = (void *)(sc->sc_ring + AT_RXD_PADDING);
    1035           0 :         sc->sc_txs = (void *)(sc->sc_ring + AT_RXD_PADDING
    1036           0 :             + AT_RXD_NUM * sizeof(struct rx_pkt));
    1037           0 :         sc->sc_txdbase = ((char *)sc->sc_txs)
    1038           0 :             + AT_TXD_NUM * sizeof(struct tx_pkt_status);
    1039           0 :         sc->sc_txsp = sc->sc_ringmap->dm_segs[0].ds_addr
    1040           0 :             + ((char *)sc->sc_txs - (char *)sc->sc_ring);
    1041           0 :         sc->sc_txdp = sc->sc_ringmap->dm_segs[0].ds_addr
    1042           0 :             + ((char *)sc->sc_txdbase - (char *)sc->sc_ring);
    1043             : 
    1044           0 :         return 0;
    1045             : 
    1046             : unmap:
    1047           0 :         bus_dmamem_unmap(sc->sc_dmat, sc->sc_ring, bs);
    1048             : free:
    1049           0 :         bus_dmamem_free(sc->sc_dmat, &sc->sc_ringseg, nsegs);
    1050             : destroy:
    1051           0 :         bus_dmamap_destroy(sc->sc_dmat, sc->sc_ringmap);
    1052           0 :         return 1;
    1053           0 : }
    1054             : 
    1055             : void
    1056           0 : lii_watchdog(struct ifnet *ifp)
    1057             : {
    1058           0 :         struct lii_softc *sc = ifp->if_softc;
    1059             : 
    1060           0 :         printf("%s: watchdog timeout\n", DEVNAME(sc));
    1061           0 :         ++ifp->if_oerrors;
    1062           0 :         lii_init(ifp);
    1063           0 : }
    1064             : 
    1065             : int
    1066           0 : lii_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
    1067             : {
    1068           0 :         struct lii_softc *sc = ifp->if_softc;
    1069           0 :         struct ifreq *ifr = (struct ifreq *)addr;
    1070             :         int s, error = 0;
    1071             : 
    1072           0 :         s = splnet();
    1073             : 
    1074           0 :         switch(cmd) {
    1075             :         case SIOCSIFADDR:
    1076           0 :                 SET(ifp->if_flags, IFF_UP);
    1077             :                 /* FALLTHROUGH */
    1078             : 
    1079             :         case SIOCSIFFLAGS:
    1080           0 :                 if (ISSET(ifp->if_flags, IFF_UP)) {
    1081           0 :                         if (ISSET(ifp->if_flags, IFF_RUNNING))
    1082           0 :                                 error = ENETRESET;
    1083             :                         else
    1084           0 :                                 lii_init(ifp);
    1085             :                 } else {
    1086           0 :                         if (ISSET(ifp->if_flags, IFF_RUNNING))
    1087           0 :                                 lii_stop(ifp);
    1088             :                 }
    1089             :                 break;
    1090             : 
    1091             :         case SIOCSIFMEDIA:
    1092             :         case SIOCGIFMEDIA:
    1093           0 :                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
    1094           0 :                 break;
    1095             : 
    1096             :         default:
    1097           0 :                 error = ether_ioctl(ifp, &sc->sc_ac, cmd, addr);
    1098           0 :         }
    1099             : 
    1100           0 :         if (error == ENETRESET) {
    1101           0 :                 if (ifp->if_flags & IFF_RUNNING)
    1102           0 :                         lii_iff(sc);
    1103             :                 error = 0;
    1104           0 :         }
    1105             : 
    1106           0 :         splx(s);
    1107           0 :         return error;
    1108             : }
    1109             : 
    1110             : void
    1111           0 : lii_iff(struct lii_softc *sc)
    1112             : {
    1113           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
    1114             :         struct arpcom *ac = &sc->sc_ac;
    1115             :         struct ether_multi *enm;
    1116             :         struct ether_multistep step;
    1117           0 :         uint32_t hashes[2];
    1118             :         uint32_t crc, val;
    1119             : 
    1120           0 :         val = LII_READ_4(sc, LII_MACC);
    1121           0 :         val &= ~(MACC_ALLMULTI_EN | MACC_BCAST_EN | MACC_PROMISC_EN);
    1122           0 :         ifp->if_flags &= ~IFF_ALLMULTI;
    1123             : 
    1124             :         /*
    1125             :          * Always accept broadcast frames.
    1126             :          */
    1127           0 :         val |= MACC_BCAST_EN;
    1128             : 
    1129           0 :         if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
    1130           0 :                 ifp->if_flags |= IFF_ALLMULTI;
    1131           0 :                 if (ifp->if_flags & IFF_PROMISC)
    1132           0 :                         val |= MACC_PROMISC_EN;
    1133             :                 else
    1134           0 :                         val |= MACC_ALLMULTI_EN;
    1135           0 :                 hashes[0] = hashes[1] = 0xFFFFFFFF;
    1136           0 :         } else {
    1137             :                 /* Program new filter. */
    1138           0 :                 bzero(hashes, sizeof(hashes));
    1139             : 
    1140           0 :                 ETHER_FIRST_MULTI(step, ac, enm);
    1141           0 :                 while (enm != NULL) {
    1142           0 :                         crc = ether_crc32_be(enm->enm_addrlo,
    1143             :                             ETHER_ADDR_LEN);
    1144             : 
    1145           0 :                         hashes[((crc >> 31) & 0x1)] |=
    1146           0 :                             (1 << ((crc >> 26) & 0x1f));
    1147             : 
    1148           0 :                         ETHER_NEXT_MULTI(step, enm);
    1149             :                 }
    1150             :         }
    1151             : 
    1152           0 :         LII_WRITE_4(sc, LII_MHT, hashes[0]);
    1153           0 :         LII_WRITE_4(sc, LII_MHT + 4, hashes[1]);
    1154           0 :         LII_WRITE_4(sc, LII_MACC, val);
    1155           0 : }
    1156             : 
    1157             : void
    1158           0 : lii_tick(void *v)
    1159             : {
    1160           0 :         struct lii_softc *sc = v;
    1161             :         int s;
    1162             : 
    1163           0 :         s = splnet();
    1164           0 :         mii_tick(&sc->sc_mii);
    1165           0 :         splx(s);
    1166             : 
    1167           0 :         timeout_add_sec(&sc->sc_tick, 1);
    1168           0 : }

Generated by: LCOV version 1.13