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

          Line data    Source code
       1             : /*      $OpenBSD: if_mue.c,v 1.4 2018/08/15 07:13:51 kevlo Exp $        */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2018 Kevin Lo <kevlo@openbsd.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : /* Driver for Microchip LAN7500/LAN7800 chipsets. */
      20             : 
      21             : #include "bpfilter.h"
      22             : 
      23             : #include <sys/param.h>
      24             : #include <sys/systm.h>
      25             : #include <sys/sockio.h>
      26             : #include <sys/rwlock.h>
      27             : #include <sys/mbuf.h>
      28             : #include <sys/kernel.h>
      29             : #include <sys/socket.h>
      30             : 
      31             : #include <sys/device.h>
      32             : 
      33             : #include <machine/bus.h>
      34             : 
      35             : #include <net/if.h>
      36             : #include <net/if_dl.h>
      37             : #include <net/if_media.h>
      38             : 
      39             : #if NBPFILTER > 0
      40             : #include <net/bpf.h>
      41             : #endif
      42             : 
      43             : #include <netinet/in.h>
      44             : #include <netinet/if_ether.h>
      45             : 
      46             : #include <dev/mii/miivar.h>
      47             : 
      48             : #include <dev/usb/usb.h>
      49             : #include <dev/usb/usbdi.h>
      50             : #include <dev/usb/usbdi_util.h>
      51             : #include <dev/usb/usbdivar.h>
      52             : #include <dev/usb/usbdevs.h>
      53             : 
      54             : #include <dev/usb/if_muereg.h>
      55             : 
      56             : #ifdef MUE_DEBUG
      57             : #define DPRINTF(x)      do { if (muedebug) printf x; } while (0)
      58             : #define DPRINTFN(n,x)   do { if (muedebug >= (n)) printf x; } while (0)
      59             : int     muedebug = 0;
      60             : #else
      61             : #define DPRINTF(x)
      62             : #define DPRINTFN(n,x)
      63             : #endif
      64             : 
      65             : /*
      66             :  * Various supported device vendors/products.
      67             :  */
      68             : struct mue_type {
      69             :         struct usb_devno        mue_dev;
      70             :         uint16_t                mue_flags;
      71             : #define LAN7500 0x0001          /* LAN7500 */
      72             : };
      73             : 
      74             : const struct mue_type mue_devs[] = {
      75             :         { { USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7500 }, LAN7500 },
      76             :         { { USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7505 }, LAN7500 },
      77             :         { { USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7800 }, 0 },
      78             :         { { USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7801 }, 0 },
      79             :         { { USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7850 }, 0 }
      80             : };
      81             : 
      82             : #define mue_lookup(v, p)        ((struct mue_type *)usb_lookup(mue_devs, v, p))
      83             : 
      84             : int     mue_match(struct device *, void *, void *);
      85             : void    mue_attach(struct device *, struct device *, void *);
      86             : int     mue_detach(struct device *, int);
      87             :  
      88             : struct cfdriver mue_cd = {
      89             :         NULL, "mue", DV_IFNET
      90             : };
      91             :           
      92             : const struct cfattach mue_ca = {
      93             :         sizeof(struct mue_softc), mue_match, mue_attach, mue_detach
      94             : };
      95             : 
      96             : uint32_t        mue_csr_read(struct mue_softc *, uint32_t);
      97             : int             mue_csr_write(struct mue_softc *, uint32_t, uint32_t);
      98             : 
      99             : void            mue_lock_mii(struct mue_softc *);
     100             : void            mue_unlock_mii(struct mue_softc *);
     101             : 
     102             : int             mue_mii_wait(struct mue_softc *);
     103             : int             mue_miibus_readreg(struct device *, int, int);
     104             : void            mue_miibus_writereg(struct device *, int, int, int);
     105             : void            mue_miibus_statchg(struct device *);
     106             : int             mue_ifmedia_upd(struct ifnet *);
     107             : void            mue_ifmedia_sts(struct ifnet *, struct ifmediareq *);
     108             : 
     109             : int             mue_eeprom_wait(struct mue_softc *);
     110             : uint8_t         mue_eeprom_getbyte(struct mue_softc *, int, uint8_t *);
     111             : int             mue_read_eeprom(struct mue_softc *, caddr_t, int, int);
     112             : int             mue_dataport_wait(struct mue_softc *);
     113             : void            mue_dataport_write(struct mue_softc *, uint32_t, uint32_t,
     114             :                     uint32_t, uint32_t *);
     115             : void            mue_init_ltm(struct mue_softc *);
     116             : int             mue_chip_init(struct mue_softc *);
     117             : void            mue_set_macaddr(struct mue_softc *);
     118             : 
     119             : int             mue_rx_list_init(struct mue_softc *);
     120             : int             mue_tx_list_init(struct mue_softc *);
     121             : int             mue_open_pipes(struct mue_softc *);
     122             : int             mue_encap(struct mue_softc *, struct mbuf *, int);
     123             : void            mue_iff(struct mue_softc *);
     124             : void            mue_rxeof(struct usbd_xfer *, void *, usbd_status);
     125             : void            mue_txeof(struct usbd_xfer *, void *, usbd_status);
     126             : 
     127             : void            mue_init(void *);
     128             : int             mue_ioctl(struct ifnet *, u_long, caddr_t);
     129             : void            mue_watchdog(struct ifnet *);
     130             : void            mue_reset(struct mue_softc *);
     131             : void            mue_start(struct ifnet *);
     132             : void            mue_stop(struct mue_softc *);
     133             : void            mue_tick(void *);
     134             : void            mue_tick_task(void *);
     135             : 
     136             : #define MUE_SETBIT(sc, reg, x)  \
     137             :         mue_csr_write(sc, reg, mue_csr_read(sc, reg) | (x))
     138             : 
     139             : #define MUE_CLRBIT(sc, reg, x)  \
     140             :         mue_csr_write(sc, reg, mue_csr_read(sc, reg) & ~(x))
     141             : 
     142             : #if defined(__arm__) || defined(__arm64__)
     143             : 
     144             : #include <dev/ofw/openfirm.h>
     145             : 
     146             : void
     147             : mue_enaddr_OF(struct mue_softc *sc)
     148             : {
     149             :         char *device = "/axi/usb/hub/ethernet";
     150             :         char prop[64];
     151             :         int node;
     152             : 
     153             :         if (sc->mue_dev.dv_unit != 0)
     154             :                 return;
     155             : 
     156             :         /* Get the Raspberry Pi MAC address from FDT. */
     157             :         if ((node = OF_finddevice("/aliases")) == -1)
     158             :                 return;
     159             :         if (OF_getprop(node, "ethernet0", prop, sizeof(prop)) > 0 ||
     160             :             OF_getprop(node, "ethernet", prop, sizeof(prop)) > 0)
     161             :                 device = prop;
     162             : 
     163             :         if ((node = OF_finddevice(device)) == -1)
     164             :                 return;
     165             :         if (OF_getprop(node, "local-mac-address", sc->arpcom.ac_enaddr,
     166             :             sizeof(sc->arpcom.ac_enaddr)) != sizeof(sc->arpcom.ac_enaddr)) {
     167             :                 OF_getprop(node, "mac-address", sc->arpcom.ac_enaddr,
     168             :                     sizeof(sc->arpcom.ac_enaddr));
     169             :         }
     170             : }
     171             : #else
     172             : #define mue_enaddr_OF(x) do {} while(0)
     173             : #endif
     174             : 
     175             : uint32_t
     176           0 : mue_csr_read(struct mue_softc *sc, uint32_t reg)
     177             : {
     178           0 :         usb_device_request_t req;
     179             :         usbd_status err;
     180           0 :         uDWord val;
     181             : 
     182           0 :         if (usbd_is_dying(sc->mue_udev))
     183           0 :                 return (0);
     184             : 
     185           0 :         USETDW(val, 0);
     186           0 :         req.bmRequestType = UT_READ_VENDOR_DEVICE;
     187           0 :         req.bRequest = MUE_UR_READREG;
     188           0 :         USETW(req.wValue, 0);
     189           0 :         USETW(req.wIndex, reg);
     190           0 :         USETW(req.wLength, 4);
     191             : 
     192           0 :         err = usbd_do_request(sc->mue_udev, &req, &val);
     193           0 :         if (err) {
     194             :                 DPRINTF(("%s: mue_csr_read: reg=0x%x err=%s\n",
     195             :                     sc->mue_dev.dv_xname, reg, usbd_errstr(err)));
     196           0 :                 return (0);
     197             :         }
     198             : 
     199           0 :         return (UGETDW(val));
     200           0 : }
     201             : 
     202             : int
     203           0 : mue_csr_write(struct mue_softc *sc, uint32_t reg, uint32_t aval)
     204             : {
     205           0 :         usb_device_request_t req;
     206             :         usbd_status err;
     207           0 :         uDWord val;
     208             : 
     209           0 :         if (usbd_is_dying(sc->mue_udev))
     210           0 :                 return (0);
     211             : 
     212           0 :         USETDW(val, aval);
     213           0 :         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
     214           0 :         req.bRequest = MUE_UR_WRITEREG;
     215           0 :         USETW(req.wValue, 0);
     216           0 :         USETW(req.wIndex, reg);
     217           0 :         USETW(req.wLength, 4);
     218             : 
     219           0 :         err = usbd_do_request(sc->mue_udev, &req, &val);
     220           0 :         if (err) {
     221             :                 DPRINTF(("%s: mue_csr_write: reg=0x%x err=%s\n",
     222             :                     sc->mue_dev.dv_xname, reg, usbd_errstr(err)));
     223           0 :                 return (-1);
     224             :         }
     225             : 
     226           0 :         return (0);
     227           0 : }
     228             : 
     229             : /* 
     230             :  * Get exclusive access to the MII registers.
     231             :  */
     232             : void
     233           0 : mue_lock_mii(struct mue_softc *sc)
     234             : {
     235           0 :         sc->mue_refcnt++;
     236           0 :         rw_enter_write(&sc->mue_mii_lock);
     237           0 : }
     238             : 
     239             : void
     240           0 : mue_unlock_mii(struct mue_softc *sc)
     241             : {
     242           0 :         rw_exit_write(&sc->mue_mii_lock);
     243           0 :         if (--sc->mue_refcnt < 0)
     244           0 :                 usb_detach_wakeup(&sc->mue_dev);
     245           0 : }
     246             : 
     247             : /*
     248             :  * Wait for the MII to become ready.
     249             :  */
     250             : int
     251           0 : mue_mii_wait(struct mue_softc *sc)
     252             : {
     253             :         int ntries;     
     254             : 
     255           0 :         for (ntries = 0; ntries < 100; ntries++) {
     256           0 :                 if (!(mue_csr_read(sc, MUE_MII_ACCESS) & MUE_MII_ACCESS_BUSY))
     257           0 :                         return (0);
     258           0 :                 DELAY(5);
     259             :         }
     260             : 
     261           0 :         printf("%s: MII timed out\n", sc->mue_dev.dv_xname); 
     262           0 :         return (1);
     263           0 : }
     264             : 
     265             : int
     266           0 : mue_miibus_readreg(struct device *dev, int phy, int reg)
     267             : {
     268           0 :         struct mue_softc *sc = (void *)dev;
     269             :         uint32_t val;
     270             : 
     271           0 :         if (usbd_is_dying(sc->mue_udev))
     272           0 :                 return (0);
     273             : 
     274           0 :         if (sc->mue_phyno != phy)
     275           0 :                 return (0);
     276             : 
     277           0 :         mue_lock_mii(sc);
     278           0 :         if (mue_mii_wait(sc) != 0)
     279           0 :                 return (0);
     280             : 
     281           0 :         mue_csr_write(sc, MUE_MII_ACCESS, MUE_MII_ACCESS_READ |
     282           0 :             MUE_MII_ACCESS_BUSY | MUE_MII_ACCESS_REGADDR(reg) |
     283           0 :             MUE_MII_ACCESS_PHYADDR(phy));
     284             : 
     285           0 :         if (mue_mii_wait(sc) != 0)
     286           0 :                 printf("%s: MII read timed out\n", sc->mue_dev.dv_xname);
     287             : 
     288           0 :         val = mue_csr_read(sc, MUE_MII_DATA);
     289           0 :         mue_unlock_mii(sc);
     290           0 :         return (val & 0xffff);
     291           0 : }
     292             : 
     293             : void
     294           0 : mue_miibus_writereg(struct device *dev, int phy, int reg, int data)
     295             : {
     296           0 :         struct mue_softc *sc = (void *)dev;
     297             : 
     298           0 :         if (usbd_is_dying(sc->mue_udev))
     299           0 :                 return;
     300             : 
     301           0 :         if (sc->mue_phyno != phy)
     302           0 :                 return;
     303             : 
     304           0 :         mue_lock_mii(sc);
     305           0 :         if (mue_mii_wait(sc) != 0)
     306           0 :                 return;
     307             : 
     308           0 :         mue_csr_write(sc, MUE_MII_DATA, data);
     309           0 :         mue_csr_write(sc, MUE_MII_ACCESS, MUE_MII_ACCESS_WRITE |
     310           0 :             MUE_MII_ACCESS_BUSY | MUE_MII_ACCESS_REGADDR(reg) |
     311           0 :             MUE_MII_ACCESS_PHYADDR(phy));
     312             : 
     313           0 :         if (mue_mii_wait(sc) != 0)
     314           0 :                 printf("%s: MII write timed out\n", sc->mue_dev.dv_xname);
     315             : 
     316           0 :         mue_unlock_mii(sc);
     317           0 : }
     318             : 
     319             : void
     320           0 : mue_miibus_statchg(struct device *dev)
     321             : {
     322           0 :         struct mue_softc *sc = (void *)dev;
     323           0 :         struct mii_data *mii = GET_MII(sc);
     324           0 :         struct ifnet *ifp = GET_IFP(sc);
     325             :         uint32_t flow, threshold;
     326             : 
     327           0 :         if (mii == NULL || ifp == NULL ||
     328           0 :             (ifp->if_flags & IFF_RUNNING) == 0)
     329           0 :                 return;
     330             : 
     331           0 :         sc->mue_link = 0;
     332           0 :         if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
     333             :             (IFM_ACTIVE | IFM_AVALID)) {
     334           0 :                 switch (IFM_SUBTYPE(mii->mii_media_active)) {
     335             :                 case IFM_10_T:
     336             :                 case IFM_100_TX:
     337             :                 case IFM_1000_T:
     338           0 :                         sc->mue_link++;
     339           0 :                         break;
     340             :                 default:
     341             :                         break;
     342             :                 }
     343             :         }
     344             : 
     345             :         /* Lost link, do nothing. */
     346           0 :         if (sc->mue_link == 0)
     347           0 :                 return;
     348             : 
     349           0 :         if (!(sc->mue_flags & LAN7500)) {
     350           0 :                 if (sc->mue_udev->speed == USB_SPEED_SUPER) {
     351           0 :                         if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
     352             :                                 /* Disable U2 and enable U1. */
     353           0 :                                 MUE_CLRBIT(sc, MUE_USB_CFG1,
     354             :                                     MUE_USB_CFG1_DEV_U2_INIT_EN);
     355           0 :                                 MUE_SETBIT(sc, MUE_USB_CFG1,
     356             :                                     MUE_USB_CFG1_DEV_U1_INIT_EN);
     357           0 :                         } else {
     358             :                                 /* Enable U1 and U2. */
     359           0 :                                 MUE_SETBIT(sc, MUE_USB_CFG1,
     360             :                                     MUE_USB_CFG1_DEV_U1_INIT_EN |
     361             :                                     MUE_USB_CFG1_DEV_U2_INIT_EN);
     362             :                         }
     363             :                 }
     364             :         }
     365             : 
     366             :         threshold = 0;
     367             :         flow = 0;
     368           0 :         if (IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) {
     369           0 :                 if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) {
     370             :                         flow |= MUE_FLOW_TX_FCEN | MUE_FLOW_PAUSE_TIME;
     371             : 
     372             :                         /* XXX magic numbers come from Linux driver. */
     373           0 :                         if (sc->mue_flags & LAN7500) {
     374             :                                 threshold = 0x820;
     375           0 :                         } else {
     376             :                                 threshold =
     377           0 :                                     (sc->mue_udev->speed == USB_SPEED_SUPER) ?
     378             :                                     0x817 : 0x211;
     379             :                         }
     380             :                 }
     381           0 :                 if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE)
     382           0 :                         flow |= MUE_FLOW_RX_FCEN;
     383             :         }
     384           0 :         mue_csr_write(sc, (sc->mue_flags & LAN7500) ?
     385             :             MUE_FCT_FLOW : MUE_7800_FCT_FLOW, threshold);
     386             : 
     387             :         /* Threshold value should be set before enabling flow. */
     388           0 :         mue_csr_write(sc, MUE_FLOW, flow);
     389           0 : }
     390             : 
     391             : /*
     392             :  * Set media options.
     393             :  */
     394             : int
     395           0 : mue_ifmedia_upd(struct ifnet *ifp)
     396             : {
     397           0 :         struct mue_softc *sc = ifp->if_softc;
     398           0 :         struct mii_data *mii = GET_MII(sc);
     399             : 
     400           0 :         if (mii->mii_instance) {
     401             :                 struct mii_softc *miisc;
     402           0 :                 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
     403           0 :                         mii_phy_reset(miisc);
     404           0 :         }
     405           0 :         return (mii_mediachg(mii));
     406             : }
     407             : 
     408             : /*
     409             :  * Report current media status.
     410             :  */
     411             : void
     412           0 : mue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
     413             : {
     414           0 :         struct mue_softc *sc = ifp->if_softc;
     415           0 :         struct mii_data *mii = GET_MII(sc);
     416             : 
     417           0 :         mii_pollstat(mii);
     418           0 :         ifmr->ifm_active = mii->mii_media_active;
     419           0 :         ifmr->ifm_status = mii->mii_media_status;
     420           0 : }
     421             : 
     422             : int
     423           0 : mue_eeprom_wait(struct mue_softc *sc)
     424             : {
     425             :         uint32_t val;
     426             :         int ntries;     
     427             : 
     428           0 :         for (ntries = 0; ntries < 100; ntries++) {
     429           0 :                 val = mue_csr_read(sc, MUE_E2P_CMD);
     430           0 :                 if (!(val & MUE_E2P_CMD_BUSY) || (val & MUE_E2P_CMD_TIMEOUT))
     431           0 :                         return (0);
     432           0 :                 DELAY(5);
     433             :         }
     434             : 
     435           0 :         return (1);
     436           0 : }
     437             : 
     438             : uint8_t
     439           0 : mue_eeprom_getbyte(struct mue_softc *sc, int addr, uint8_t *dest)
     440             : {
     441             :         uint32_t byte = 0;
     442             :         int ntries;
     443             : 
     444           0 :         for (ntries = 0; ntries < 100; ntries++) {
     445           0 :                 if (!(mue_csr_read(sc, MUE_E2P_CMD) & MUE_E2P_CMD_BUSY))
     446             :                         break;
     447           0 :                 DELAY(5);
     448             :         }
     449             : 
     450           0 :         if (ntries == 100) {
     451           0 :                 printf("%s: EEPROM failed to come ready\n",
     452           0 :                     sc->mue_dev.dv_xname); 
     453           0 :                 return (ETIMEDOUT);
     454             :         }
     455             : 
     456           0 :         mue_csr_write(sc, MUE_E2P_CMD, MUE_E2P_CMD_READ | MUE_E2P_CMD_BUSY |
     457           0 :             (addr & MUE_E2P_CMD_ADDR_MASK));
     458             : 
     459           0 :         if (mue_eeprom_wait(sc) != 0) {
     460           0 :                 printf("%s: EEPROM read timed out\n", sc->mue_dev.dv_xname);
     461           0 :                 return (ETIMEDOUT);
     462             :         }
     463             : 
     464           0 :         byte = mue_csr_read(sc, MUE_E2P_DATA);
     465           0 :         *dest = byte & 0xff;
     466             : 
     467           0 :         return (0);
     468           0 : }
     469             : 
     470             : int
     471           0 : mue_read_eeprom(struct mue_softc *sc, caddr_t dest, int off, int cnt)
     472             : {
     473             :         uint32_t val;
     474           0 :         uint8_t byte = 0;
     475             :         int i, err = 0;
     476             : 
     477             :         /* 
     478             :          * EEPROM pins are muxed with the LED function on LAN7800 device.
     479             :          */
     480           0 :         val = mue_csr_read(sc, MUE_HW_CFG);
     481           0 :         if (sc->mue_product == USB_PRODUCT_SMC2_LAN7800) {
     482           0 :                 MUE_CLRBIT(sc, MUE_HW_CFG,
     483             :                     MUE_HW_CFG_LED0_EN | MUE_HW_CFG_LED1_EN);
     484           0 :         }
     485             : 
     486           0 :         for (i = 0; i < cnt; i++) {
     487           0 :                 err = mue_eeprom_getbyte(sc, off + i, &byte);
     488           0 :                 if (err)
     489             :                         break;
     490           0 :                 *(dest + i) = byte;
     491             :         }
     492             : 
     493           0 :         if (sc->mue_product == USB_PRODUCT_SMC2_LAN7800)
     494           0 :                 mue_csr_write(sc, MUE_HW_CFG, val);
     495             : 
     496           0 :         return (err ? 1 : 0);
     497           0 : }
     498             : 
     499             : int             
     500           0 : mue_dataport_wait(struct mue_softc *sc)
     501             : {
     502             :         int ntries;     
     503             : 
     504           0 :         for (ntries = 0; ntries < 100; ntries++) {
     505           0 :                 if (mue_csr_read(sc, MUE_DP_SEL) & MUE_DP_SEL_DPRDY)
     506           0 :                         return (0);
     507           0 :                 DELAY(5);
     508             :         }
     509             : 
     510           0 :         printf("%s: dataport timed out\n", sc->mue_dev.dv_xname); 
     511           0 :         return (1);
     512           0 : }
     513             : 
     514             : void
     515           0 : mue_dataport_write(struct mue_softc *sc, uint32_t sel, uint32_t addr,
     516             :     uint32_t cnt, uint32_t *data)
     517             : {
     518             :         int i;
     519             : 
     520           0 :         if (mue_dataport_wait(sc) != 0)
     521           0 :                 return;
     522             : 
     523           0 :         mue_csr_write(sc, MUE_DP_SEL,
     524           0 :             (mue_csr_read(sc, MUE_DP_SEL) & ~MUE_DP_SEL_RSEL_MASK) | sel);
     525             : 
     526           0 :         for (i = 0; i < cnt; i++) {
     527           0 :                 mue_csr_write(sc, MUE_DP_ADDR, addr + i);
     528           0 :                 mue_csr_write(sc, MUE_DP_DATA, data[i]);
     529           0 :                 mue_csr_write(sc, MUE_DP_CMD, MUE_DP_CMD_WRITE);
     530           0 :                 if (mue_dataport_wait(sc) != 0)
     531           0 :                         return;
     532             :         }
     533           0 : }
     534             : 
     535             : void
     536           0 : mue_init_ltm(struct mue_softc *sc)
     537             : {
     538           0 :         uint8_t idx[6] = { 0 };
     539             :         int i;
     540             : 
     541           0 :         if (mue_csr_read(sc, MUE_USB_CFG1) & MUE_USB_CFG1_LTM_ENABLE) {
     542           0 :                 uint8_t temp[2];
     543             : 
     544           0 :                 if (mue_read_eeprom(sc, (caddr_t)&temp, MUE_EE_LTM_OFFSET, 2)) {
     545           0 :                         if (temp[0] != 24)
     546           0 :                                 goto done;
     547           0 :                         mue_read_eeprom(sc, (caddr_t)&idx, temp[1] << 1, 24);
     548           0 :                 }
     549           0 :         }
     550             : done:
     551           0 :         for (i = 0; i < sizeof(idx); i++)
     552           0 :                 mue_csr_write(sc, MUE_LTM_INDEX(i), idx[i]);
     553           0 : }
     554             : 
     555             : int
     556           0 : mue_chip_init(struct mue_softc *sc)
     557             : {
     558             :         uint32_t val;
     559             :         int ntries;
     560             : 
     561           0 :         if (sc->mue_flags & LAN7500) {
     562           0 :                 for (ntries = 0; ntries < 100; ntries++) {
     563           0 :                         if (mue_csr_read(sc, MUE_PMT_CTL) & MUE_PMT_CTL_READY)
     564             :                                 break;
     565           0 :                         DELAY(1000);    /* 1 msec */
     566             :                 }
     567           0 :                 if (ntries == 100) {
     568           0 :                         printf("%s: timeout waiting for device ready\n",
     569           0 :                             sc->mue_dev.dv_xname);
     570           0 :                         return (ETIMEDOUT);
     571             :                 }
     572             :         }
     573             : 
     574           0 :         MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_LRST);
     575             : 
     576           0 :         for (ntries = 0; ntries < 1000; ntries++) {
     577           0 :                 if (!(mue_csr_read(sc, MUE_HW_CFG) & MUE_HW_CFG_LRST))
     578             :                         break;
     579           0 :                 DELAY(5);
     580             :         }
     581           0 :         if (ntries == 1000) {
     582           0 :                 printf("%s: timeout on lite software reset\n",
     583           0 :                     sc->mue_dev.dv_xname);
     584           0 :                 return (ETIMEDOUT);
     585             :         }
     586             : 
     587             :         /* Respond to the IN token with a NAK. */
     588           0 :         if (sc->mue_flags & LAN7500)
     589           0 :                 MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_BIR);
     590             :         else
     591           0 :                 MUE_SETBIT(sc, MUE_USB_CFG0, MUE_USB_CFG0_BIR);
     592             : 
     593           0 :         if (sc->mue_flags & LAN7500) {
     594           0 :                 mue_csr_write(sc, MUE_BURST_CAP,
     595           0 :                     (sc->mue_udev->speed == USB_SPEED_HIGH) ?
     596             :                     MUE_BURST_MIN_BUFSZ : MUE_BURST_MAX_BUFSZ);
     597           0 :                 mue_csr_write(sc, MUE_BULK_IN_DELAY, MUE_DEFAULT_BULKIN_DELAY);
     598             : 
     599           0 :                 MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_BCE | MUE_HW_CFG_MEF);
     600             : 
     601             :                 /* Set undocumented FIFO sizes. */
     602           0 :                 mue_csr_write(sc, MUE_FCT_RX_FIFO_END, 0x27);
     603           0 :                 mue_csr_write(sc, MUE_FCT_TX_FIFO_END, 0x17);
     604           0 :         } else {
     605             :                 /* Init LTM. */
     606           0 :                 mue_init_ltm(sc);
     607             : 
     608           0 :                 val = (sc->mue_udev->speed == USB_SPEED_SUPER) ?
     609             :                     MUE_7800_BURST_MIN_BUFSZ : MUE_7800_BURST_MAX_BUFSZ;
     610           0 :                 mue_csr_write(sc, MUE_7800_BURST_CAP, val);
     611           0 :                 mue_csr_write(sc, MUE_7800_BULK_IN_DELAY,
     612             :                     MUE_7800_DEFAULT_BULKIN_DELAY);
     613             : 
     614           0 :                 MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_MEF);
     615           0 :                 MUE_SETBIT(sc, MUE_USB_CFG0, MUE_USB_CFG0_BCE);
     616             :         }
     617             : 
     618           0 :         mue_csr_write(sc, MUE_INT_STATUS, 0xffffffff);
     619           0 :         mue_csr_write(sc, (sc->mue_flags & LAN7500) ?
     620             :             MUE_FCT_FLOW : MUE_7800_FCT_FLOW, 0);
     621           0 :         mue_csr_write(sc, MUE_FLOW, 0);
     622             :  
     623             :         /* Reset PHY. */
     624           0 :         MUE_SETBIT(sc, MUE_PMT_CTL, MUE_PMT_CTL_PHY_RST);
     625           0 :         for (ntries = 0; ntries < 100; ntries++) {
     626           0 :                 val = mue_csr_read(sc, MUE_PMT_CTL);
     627           0 :                 if (!(val & MUE_PMT_CTL_PHY_RST) && (val & MUE_PMT_CTL_READY))
     628             :                         break;
     629           0 :                 DELAY(10000);
     630             :         }
     631           0 :         if (ntries == 100) {
     632           0 :                 printf("%s: timeout waiting for PHY reset\n",
     633           0 :                     sc->mue_dev.dv_xname);
     634           0 :                 return (ETIMEDOUT);
     635             :         }
     636             : 
     637             :         /* LAN7801 only has RGMII mode. */
     638           0 :         if (sc->mue_product == USB_PRODUCT_SMC2_LAN7801)
     639           0 :                 MUE_CLRBIT(sc, MUE_MAC_CR, MUE_MAC_CR_GMII_EN);
     640             : 
     641           0 :         if (sc->mue_flags & LAN7500 || !sc->mue_eeprom_present) {
     642             :                 /* Allow MAC to detect speed and duplex from PHY. */
     643           0 :                 MUE_SETBIT(sc, MUE_MAC_CR, MUE_MAC_CR_AUTO_SPEED |
     644             :                     MUE_MAC_CR_AUTO_DUPLEX);
     645           0 :         }
     646             : 
     647           0 :         MUE_SETBIT(sc, MUE_MAC_TX, MUE_MAC_TX_TXEN);
     648           0 :         MUE_SETBIT(sc, (sc->mue_flags & LAN7500) ?
     649             :             MUE_FCT_TX_CTL : MUE_7800_FCT_TX_CTL, MUE_FCT_TX_CTL_EN);
     650             : 
     651             :         /* Set the maximum frame size. */
     652           0 :         MUE_CLRBIT(sc, MUE_MAC_RX, MUE_MAC_RX_RXEN);
     653           0 :         MUE_SETBIT(sc, MUE_MAC_RX, MUE_MAC_RX_MAX_LEN(ETHER_MAX_LEN));
     654           0 :         MUE_SETBIT(sc, MUE_MAC_RX, MUE_MAC_RX_RXEN);
     655             : 
     656           0 :         MUE_SETBIT(sc, (sc->mue_flags & LAN7500) ?
     657             :             MUE_FCT_RX_CTL : MUE_7800_FCT_RX_CTL, MUE_FCT_RX_CTL_EN);
     658             : 
     659           0 :         return (0);
     660           0 : }
     661             : 
     662             : void
     663           0 : mue_set_macaddr(struct mue_softc *sc)
     664             : {
     665           0 :         struct ifnet *ifp = &sc->arpcom.ac_if;
     666           0 :         const uint8_t *eaddr = LLADDR(ifp->if_sadl);
     667             :         uint32_t val, reg;
     668             : 
     669           0 :         reg = (sc->mue_flags & LAN7500) ? MUE_ADDR_FILTX : MUE_7800_ADDR_FILTX;
     670             : 
     671           0 :         val = (eaddr[3] << 24) | (eaddr[2] << 16) | (eaddr[1] << 8) | eaddr[0];
     672           0 :         mue_csr_write(sc, MUE_RX_ADDRL, val);
     673           0 :         mue_csr_write(sc, reg + 4, val);
     674           0 :         val = (eaddr[5] << 8) | eaddr[4];
     675           0 :         mue_csr_write(sc, MUE_RX_ADDRH, val);
     676           0 :         mue_csr_write(sc, reg, val | MUE_ADDR_FILTX_VALID);
     677           0 : }
     678             : 
     679             : /* 
     680             :  * Probe for a Microchip chip.
     681             :  */
     682             : int
     683           0 : mue_match(struct device *parent, void *match, void *aux)
     684             : {
     685           0 :         struct usb_attach_arg *uaa = aux;
     686             : 
     687           0 :         if (uaa->iface == NULL || uaa->configno != 1)
     688           0 :                 return (UMATCH_NONE);
     689             : 
     690           0 :         return (mue_lookup(uaa->vendor, uaa->product) != NULL ?
     691             :             UMATCH_VENDOR_PRODUCT_CONF_IFACE : UMATCH_NONE);
     692           0 : }
     693             : 
     694             : void
     695           0 : mue_attach(struct device *parent, struct device *self, void *aux)
     696             : {
     697           0 :         struct mue_softc *sc = (struct mue_softc *)self;
     698           0 :         struct usb_attach_arg *uaa = aux;
     699             :         usb_interface_descriptor_t *id;
     700             :         usb_endpoint_descriptor_t *ed;
     701             :         struct mii_data *mii;
     702             :         struct ifnet *ifp;
     703           0 :         int i, s;
     704             : 
     705           0 :         sc->mue_udev = uaa->device;
     706           0 :         sc->mue_iface = uaa->iface;
     707           0 :         sc->mue_product = uaa->product;
     708           0 :         sc->mue_flags = mue_lookup(uaa->vendor, uaa->product)->mue_flags;
     709             : 
     710           0 :         usb_init_task(&sc->mue_tick_task, mue_tick_task, sc,
     711             :             USB_TASK_TYPE_GENERIC);
     712           0 :         rw_init(&sc->mue_mii_lock, "muemii");
     713           0 :         usb_init_task(&sc->mue_stop_task, (void (*)(void *))mue_stop, sc,
     714             :             USB_TASK_TYPE_GENERIC);
     715             : 
     716             :         /* Decide on what our bufsize will be. */
     717           0 :         if (sc->mue_flags & LAN7500)
     718           0 :                 sc->mue_bufsz = (sc->mue_udev->speed == USB_SPEED_HIGH) ?
     719             :                     MUE_MAX_BUFSZ : MUE_MIN_BUFSZ;
     720             :         else
     721           0 :                 sc->mue_bufsz = MUE_7800_BUFSZ;
     722             : 
     723             :         /* Find endpoints. */
     724           0 :         id = usbd_get_interface_descriptor(sc->mue_iface);
     725           0 :         for (i = 0; i < id->bNumEndpoints; i++) {
     726           0 :                 ed = usbd_interface2endpoint_descriptor(sc->mue_iface, i);
     727           0 :                 if (ed == NULL) {
     728           0 :                         printf("%s: couldn't get ep %d\n",
     729           0 :                             sc->mue_dev.dv_xname, i);
     730           0 :                         return;
     731             :                 }
     732           0 :                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
     733           0 :                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
     734           0 :                         sc->mue_ed[MUE_ENDPT_RX] = ed->bEndpointAddress;
     735           0 :                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
     736           0 :                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
     737           0 :                         sc->mue_ed[MUE_ENDPT_TX] = ed->bEndpointAddress;
     738           0 :                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
     739           0 :                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
     740           0 :                         sc->mue_ed[MUE_ENDPT_INTR] = ed->bEndpointAddress;
     741           0 :                 }
     742             :         }
     743             : 
     744           0 :         s = splnet();
     745             : 
     746           0 :         sc->mue_phyno = 1;
     747             : 
     748             :         /* Check if the EEPROM programmed indicator is present. */
     749           0 :         mue_read_eeprom(sc, (caddr_t)&i, MUE_EE_IND_OFFSET, 1);
     750           0 :         sc->mue_eeprom_present = (i == MUE_EEPROM_INDICATOR) ? 1 : 0;
     751             : 
     752           0 :         if (mue_chip_init(sc) != 0) {
     753           0 :                 printf("%s: chip initialization failed\n",
     754           0 :                     sc->mue_dev.dv_xname);
     755           0 :                 splx(s);
     756           0 :                 return;
     757             :         }
     758             : 
     759             :         /* Get station address from the EEPROM. */
     760           0 :         if (sc->mue_eeprom_present) {
     761           0 :                 if (mue_read_eeprom(sc, (caddr_t)&sc->arpcom.ac_enaddr,
     762             :                     MUE_EE_MAC_OFFSET, ETHER_ADDR_LEN)) {
     763           0 :                         printf("%s: failed to read station address\n",
     764           0 :                             sc->mue_dev.dv_xname);
     765           0 :                         splx(s);
     766           0 :                         return;
     767             :                 }
     768             :         } else
     769             :                 mue_enaddr_OF(sc);
     770             : 
     771             :         /* A Microchip chip was detected.  Inform the world. */
     772           0 :         printf("%s:", sc->mue_dev.dv_xname);
     773           0 :         if (sc->mue_flags & LAN7500)
     774           0 :                 printf(" LAN7500");
     775             :         else
     776           0 :                 printf(" LAN7800");
     777           0 :         printf(", address %s\n", ether_sprintf(sc->arpcom.ac_enaddr));
     778             : 
     779             :         /* Initialize interface info.*/
     780           0 :         ifp = GET_IFP(sc);
     781           0 :         ifp->if_softc = sc;
     782           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     783           0 :         ifp->if_ioctl = mue_ioctl;
     784           0 :         ifp->if_start = mue_start;
     785           0 :         ifp->if_watchdog = mue_watchdog;
     786           0 :         strlcpy(ifp->if_xname, sc->mue_dev.dv_xname, IFNAMSIZ);
     787             : 
     788           0 :         ifp->if_capabilities = IFCAP_VLAN_MTU;
     789             : 
     790             :         /* Initialize MII/media info. */
     791           0 :         mii = GET_MII(sc);
     792           0 :         mii->mii_ifp = ifp;
     793           0 :         mii->mii_readreg = mue_miibus_readreg;
     794           0 :         mii->mii_writereg = mue_miibus_writereg;
     795           0 :         mii->mii_statchg = mue_miibus_statchg;
     796           0 :         mii->mii_flags = MIIF_AUTOTSLEEP;
     797             : 
     798           0 :         ifmedia_init(&mii->mii_media, 0, mue_ifmedia_upd, mue_ifmedia_sts);
     799           0 :         mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
     800             :             MIIF_DOPAUSE);
     801             : 
     802           0 :         if (LIST_FIRST(&mii->mii_phys) == NULL) {
     803           0 :                 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
     804           0 :                 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
     805           0 :         } else
     806           0 :                 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
     807             : 
     808             :         /* Attach the interface. */
     809           0 :         if_attach(ifp);
     810           0 :         ether_ifattach(ifp);
     811             : 
     812           0 :         timeout_set(&sc->mue_stat_ch, mue_tick, sc);
     813             : 
     814           0 :         splx(s);
     815           0 : }
     816             : 
     817             : int
     818           0 : mue_detach(struct device *self, int flags)
     819             : {
     820           0 :         struct mue_softc *sc = (struct mue_softc *)self;
     821           0 :         struct ifnet *ifp = GET_IFP(sc);
     822             :         int s;
     823             : 
     824           0 :         if (timeout_initialized(&sc->mue_stat_ch))
     825           0 :                 timeout_del(&sc->mue_stat_ch);
     826             : 
     827           0 :         if (sc->mue_ep[MUE_ENDPT_TX] != NULL)
     828           0 :                 usbd_abort_pipe(sc->mue_ep[MUE_ENDPT_TX]);
     829           0 :         if (sc->mue_ep[MUE_ENDPT_RX] != NULL)
     830           0 :                 usbd_abort_pipe(sc->mue_ep[MUE_ENDPT_RX]);
     831           0 :         if (sc->mue_ep[MUE_ENDPT_INTR] != NULL)
     832           0 :                 usbd_abort_pipe(sc->mue_ep[MUE_ENDPT_INTR]);
     833             : 
     834             :         /*
     835             :          * Remove any pending tasks.  They cannot be executing because they run
     836             :          * in the same thread as detach.
     837             :          */
     838           0 :         usb_rem_task(sc->mue_udev, &sc->mue_tick_task);
     839           0 :         usb_rem_task(sc->mue_udev, &sc->mue_stop_task);
     840             : 
     841           0 :         s = splusb();
     842             : 
     843           0 :         if (--sc->mue_refcnt >= 0) {
     844             :                 /* Wait for processes to go away */
     845           0 :                 usb_detach_wait(&sc->mue_dev);
     846           0 :         }
     847             : 
     848           0 :         if (ifp->if_flags & IFF_RUNNING)
     849           0 :                 mue_stop(sc);
     850             : 
     851           0 :         mii_detach(&sc->mue_mii, MII_PHY_ANY, MII_OFFSET_ANY);
     852           0 :         ifmedia_delete_instance(&sc->mue_mii.mii_media, IFM_INST_ANY);
     853           0 :         if (ifp->if_softc != NULL) {
     854           0 :                 ether_ifdetach(ifp);
     855           0 :                 if_detach(ifp);
     856           0 :         }
     857             : 
     858           0 :         if (--sc->mue_refcnt >= 0) {
     859             :                 /* Wait for processes to go away. */
     860           0 :                 usb_detach_wait(&sc->mue_dev);
     861           0 :         }
     862           0 :         splx(s);
     863             : 
     864           0 :         return (0);
     865             : }
     866             : 
     867             : int
     868           0 : mue_rx_list_init(struct mue_softc *sc)
     869             : {
     870             :         struct mue_cdata *cd;
     871             :         struct mue_chain *c;
     872             :         int i;
     873             : 
     874             :         DPRINTF(("%s: %s: enter\n", sc->mue_dev.dv_xname, __func__));
     875             : 
     876           0 :         cd = &sc->mue_cdata;
     877           0 :         for (i = 0; i < MUE_RX_LIST_CNT; i++) {
     878           0 :                 c = &cd->mue_rx_chain[i];
     879           0 :                 c->mue_sc = sc;
     880           0 :                 c->mue_idx = i;
     881           0 :                 c->mue_mbuf = NULL;
     882           0 :                 if (c->mue_xfer == NULL) {
     883           0 :                         c->mue_xfer = usbd_alloc_xfer(sc->mue_udev);
     884           0 :                         if (c->mue_xfer == NULL)
     885           0 :                                 return (ENOBUFS);
     886           0 :                         c->mue_buf = usbd_alloc_buffer(c->mue_xfer,
     887           0 :                             sc->mue_bufsz);
     888           0 :                         if (c->mue_buf == NULL) {
     889           0 :                                 usbd_free_xfer(c->mue_xfer);
     890           0 :                                 return (ENOBUFS);
     891             :                         }
     892             :                 }
     893             :         }
     894             : 
     895           0 :         return (0);
     896           0 : }
     897             : 
     898             : int
     899           0 : mue_tx_list_init(struct mue_softc *sc)
     900             : {
     901             :         struct mue_cdata *cd;
     902             :         struct mue_chain *c;
     903             :         int i;
     904             : 
     905             :         DPRINTF(("%s: %s: enter\n", sc->mue_dev.dv_xname, __func__));
     906             : 
     907           0 :         cd = &sc->mue_cdata;
     908           0 :         for (i = 0; i < MUE_TX_LIST_CNT; i++) {
     909           0 :                 c = &cd->mue_tx_chain[i];
     910           0 :                 c->mue_sc = sc;
     911           0 :                 c->mue_idx = i;
     912           0 :                 c->mue_mbuf = NULL;
     913           0 :                 if (c->mue_xfer == NULL) {
     914           0 :                         c->mue_xfer = usbd_alloc_xfer(sc->mue_udev);
     915           0 :                         if (c->mue_xfer == NULL)
     916           0 :                                 return (ENOBUFS);
     917           0 :                         c->mue_buf = usbd_alloc_buffer(c->mue_xfer,
     918           0 :                             sc->mue_bufsz);
     919           0 :                         if (c->mue_buf == NULL) {
     920           0 :                                 usbd_free_xfer(c->mue_xfer);
     921           0 :                                 return (ENOBUFS);
     922             :                         }
     923             :                 }
     924             :         }
     925             : 
     926           0 :         return (0);
     927           0 : }
     928             : 
     929             : int
     930           0 : mue_open_pipes(struct mue_softc *sc)
     931             : {
     932             :         struct mue_chain *c;
     933             :         usbd_status err;
     934             :         int i;
     935             : 
     936             :         /* Open RX and TX pipes. */
     937           0 :         err = usbd_open_pipe(sc->mue_iface, sc->mue_ed[MUE_ENDPT_RX],
     938           0 :             USBD_EXCLUSIVE_USE, &sc->mue_ep[MUE_ENDPT_RX]);
     939           0 :         if (err) {
     940           0 :                 printf("%s: open rx pipe failed: %s\n",
     941           0 :                     sc->mue_dev.dv_xname, usbd_errstr(err));
     942           0 :                 return (EIO);
     943             :         }
     944           0 :         err = usbd_open_pipe(sc->mue_iface, sc->mue_ed[MUE_ENDPT_TX],
     945           0 :             USBD_EXCLUSIVE_USE, &sc->mue_ep[MUE_ENDPT_TX]);
     946           0 :         if (err) {
     947           0 :                 printf("%s: open tx pipe failed: %s\n",
     948           0 :                     sc->mue_dev.dv_xname, usbd_errstr(err));
     949           0 :                 return (EIO);
     950             :         }
     951             : 
     952             :         /* Start up the receive pipe. */
     953           0 :         for (i = 0; i < MUE_RX_LIST_CNT; i++) {
     954           0 :                 c = &sc->mue_cdata.mue_rx_chain[i];
     955           0 :                 usbd_setup_xfer(c->mue_xfer, sc->mue_ep[MUE_ENDPT_RX],
     956           0 :                     c, c->mue_buf, sc->mue_bufsz,
     957             :                     USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
     958             :                     mue_rxeof);
     959           0 :                 usbd_transfer(c->mue_xfer);
     960             :         }
     961             : 
     962           0 :         return (0);
     963           0 : }
     964             : 
     965             : int
     966           0 : mue_encap(struct mue_softc *sc, struct mbuf *m, int idx)
     967             : {
     968             :         struct mue_chain *c;
     969             :         usbd_status err;
     970             :         struct mue_txbuf_hdr hdr;
     971             :         int length;
     972             : 
     973           0 :         c = &sc->mue_cdata.mue_tx_chain[idx];
     974             : 
     975           0 :         hdr.tx_cmd_a = htole32((m->m_pkthdr.len & MUE_TX_CMD_A_LEN_MASK) |
     976             :             MUE_TX_CMD_A_FCS);
     977             :         /* Disable segmentation offload. */
     978             :         hdr.tx_cmd_b = htole32(0);
     979           0 :         memcpy(c->mue_buf, &hdr, sizeof(hdr)); 
     980             :         length = sizeof(hdr);
     981             : 
     982           0 :         m_copydata(m, 0, m->m_pkthdr.len, c->mue_buf + length);
     983           0 :         length += m->m_pkthdr.len;
     984             : 
     985           0 :         c->mue_mbuf = m;
     986             : 
     987           0 :         usbd_setup_xfer(c->mue_xfer, sc->mue_ep[MUE_ENDPT_TX],
     988           0 :             c, c->mue_buf, length, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
     989             :             10000, mue_txeof);
     990             : 
     991             :         /* Transmit */
     992           0 :         err = usbd_transfer(c->mue_xfer);
     993           0 :         if (err != USBD_IN_PROGRESS) {
     994           0 :                 mue_stop(sc);
     995           0 :                 return(EIO);
     996             :         }
     997             : 
     998           0 :         sc->mue_cdata.mue_tx_cnt++;
     999             : 
    1000           0 :         return(0);
    1001           0 : }
    1002             : 
    1003             : void
    1004           0 : mue_iff(struct mue_softc *sc)
    1005             : {
    1006           0 :         struct ifnet *ifp = GET_IFP(sc);
    1007             :         struct arpcom *ac = &sc->arpcom;
    1008             :         struct ether_multi *enm;
    1009             :         struct ether_multistep step;
    1010           0 :         uint32_t h = 0, hashtbl[MUE_DP_SEL_VHF_HASH_LEN], reg, rxfilt;
    1011             : 
    1012           0 :         if (usbd_is_dying(sc->mue_udev))
    1013           0 :                 return;
    1014             : 
    1015           0 :         reg = (sc->mue_flags & LAN7500) ? MUE_RFE_CTL : MUE_7800_RFE_CTL;
    1016           0 :         rxfilt = mue_csr_read(sc, reg);
    1017           0 :         rxfilt &= ~(MUE_RFE_CTL_PERFECT | MUE_RFE_CTL_MULTICAST_HASH |
    1018             :             MUE_RFE_CTL_UNICAST | MUE_RFE_CTL_MULTICAST);
    1019           0 :         ifp->if_flags &= ~IFF_ALLMULTI;
    1020             : 
    1021             :         /* Always accept broadcast frames. */
    1022           0 :         rxfilt |= MUE_RFE_CTL_BROADCAST;
    1023             : 
    1024           0 :         if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
    1025           0 :                 ifp->if_flags |= IFF_ALLMULTI;
    1026           0 :                 rxfilt |= MUE_RFE_CTL_MULTICAST;
    1027           0 :                 if (ifp->if_flags & IFF_PROMISC)
    1028           0 :                         rxfilt |= MUE_RFE_CTL_UNICAST | MUE_RFE_CTL_MULTICAST;
    1029             :         } else {
    1030           0 :                 rxfilt |= MUE_RFE_CTL_PERFECT | MUE_RFE_CTL_MULTICAST_HASH;
    1031             : 
    1032             :                 /* Clear hash table. */
    1033           0 :                 memset(hashtbl, 0, sizeof(hashtbl));
    1034             : 
    1035             :                 /* Now program new ones. */
    1036           0 :                 ETHER_FIRST_MULTI(step, ac, enm);
    1037           0 :                 while (enm != NULL) {
    1038           0 :                         h = ether_crc32_be(enm->enm_addrlo,
    1039           0 :                             ETHER_ADDR_LEN) >> 23;
    1040           0 :                         hashtbl[h / 32] |= 1 << (h % 32); 
    1041           0 :                         ETHER_NEXT_MULTI(step, enm);
    1042             :                 }
    1043             :         }
    1044             : 
    1045           0 :         mue_dataport_write(sc, MUE_DP_SEL_VHF, MUE_DP_SEL_VHF_VLAN_LEN,
    1046           0 :             MUE_DP_SEL_VHF_HASH_LEN, hashtbl);
    1047           0 :         mue_csr_write(sc, reg, rxfilt);
    1048           0 : }
    1049             : 
    1050             : void
    1051           0 : mue_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
    1052             : {
    1053           0 :         struct mue_chain *c = (struct mue_chain *)priv;
    1054           0 :         struct mue_softc *sc = c->mue_sc;
    1055           0 :         struct ifnet *ifp = GET_IFP(sc);
    1056           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
    1057             :         struct mbuf *m;
    1058           0 :         struct mue_rxbuf_hdr hdr;
    1059           0 :         u_char *buf = c->mue_buf;
    1060           0 :         uint32_t total_len;
    1061             :         int pktlen = 0;
    1062             :         int s;
    1063             : 
    1064           0 :         if (usbd_is_dying(sc->mue_udev))
    1065           0 :                 return;
    1066             : 
    1067           0 :         if (!(ifp->if_flags & IFF_RUNNING))
    1068           0 :                 return;
    1069             : 
    1070           0 :         if (status != USBD_NORMAL_COMPLETION) {
    1071           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    1072           0 :                         return;
    1073           0 :                 if (usbd_ratecheck(&sc->mue_rx_notice)) {
    1074           0 :                         printf("%s: usb errors on rx: %s\n",
    1075           0 :                             sc->mue_dev.dv_xname, usbd_errstr(status));
    1076           0 :                 }
    1077           0 :                 if (status == USBD_STALLED)
    1078           0 :                         usbd_clear_endpoint_stall_async(sc->mue_ep[MUE_ENDPT_RX]);
    1079             :                 goto done;
    1080             :         }
    1081             : 
    1082           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
    1083             : 
    1084           0 :         do {
    1085           0 :                 if (total_len < sizeof(hdr)) {
    1086           0 :                         ifp->if_ierrors++;
    1087           0 :                         goto done;
    1088             :                 }
    1089             : 
    1090           0 :                 buf += pktlen;
    1091             : 
    1092           0 :                 memcpy(&hdr, buf, sizeof(hdr));
    1093           0 :                 total_len -= sizeof(hdr);
    1094             : 
    1095           0 :                 if (letoh32(hdr.rx_cmd_a) & MUE_RX_CMD_A_RED) {
    1096           0 :                         ifp->if_ierrors++;
    1097           0 :                         goto done;
    1098             :                 }
    1099             : 
    1100           0 :                 pktlen = letoh32(hdr.rx_cmd_a) & MUE_RX_CMD_A_LEN_MASK;
    1101           0 :                 if (sc->mue_flags & LAN7500)
    1102           0 :                         pktlen -= 2;
    1103             : 
    1104           0 :                 if (pktlen > total_len) {
    1105           0 :                         ifp->if_ierrors++;
    1106           0 :                         goto done;
    1107             :                 }
    1108             : 
    1109           0 :                 buf += sizeof(hdr);
    1110             : 
    1111           0 :                 if (total_len < pktlen)
    1112           0 :                         total_len = 0;
    1113             :                 else
    1114           0 :                         total_len -= pktlen;
    1115             : 
    1116           0 :                 m = m_devget(buf, pktlen - ETHER_CRC_LEN, ETHER_ALIGN);
    1117           0 :                 if (m == NULL) {
    1118             :                         DPRINTF(("unable to allocate mbuf for next packet\n"));
    1119           0 :                         ifp->if_ierrors++;
    1120           0 :                         goto done;
    1121             :                 }
    1122           0 :                 ml_enqueue(&ml, m);
    1123           0 :         } while (total_len > 0);
    1124             : 
    1125             : done:
    1126           0 :         s = splnet();
    1127           0 :         if_input(ifp, &ml);
    1128           0 :         splx(s);
    1129             : 
    1130           0 :         memset(c->mue_buf, 0, sc->mue_bufsz);
    1131             : 
    1132             :         /* Setup new transfer. */
    1133           0 :         usbd_setup_xfer(xfer, sc->mue_ep[MUE_ENDPT_RX],
    1134           0 :             c, c->mue_buf, sc->mue_bufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY,
    1135             :             USBD_NO_TIMEOUT, mue_rxeof);
    1136           0 :         usbd_transfer(xfer);
    1137             : 
    1138             :         DPRINTFN(10,("%s: %s: start rx\n", sc->mue_dev.dv_xname, __func__));
    1139           0 : }
    1140             : 
    1141             : void
    1142           0 : mue_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
    1143             : {
    1144           0 :         struct mue_chain *c = priv;
    1145           0 :         struct mue_softc *sc = c->mue_sc;
    1146           0 :         struct ifnet *ifp = GET_IFP(sc);
    1147             :         int s;
    1148             : 
    1149           0 :         if (usbd_is_dying(sc->mue_udev))
    1150           0 :                 return;
    1151             : 
    1152           0 :         s = splnet();
    1153             : 
    1154             :         DPRINTFN(10,("%s: %s: enter status=%d\n", sc->mue_dev.dv_xname,
    1155             :             __func__, status));
    1156             : 
    1157           0 :         if (status != USBD_NORMAL_COMPLETION) {
    1158           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
    1159           0 :                         splx(s);
    1160           0 :                         return;
    1161             :                 }
    1162           0 :                 ifp->if_oerrors++;
    1163           0 :                 printf("%s: usb error on tx: %s\n", sc->mue_dev.dv_xname,
    1164           0 :                     usbd_errstr(status));
    1165           0 :                 if (status == USBD_STALLED)
    1166           0 :                         usbd_clear_endpoint_stall_async(sc->mue_ep[MUE_ENDPT_TX]);
    1167           0 :                 splx(s);
    1168           0 :                 return;
    1169             :         }
    1170             : 
    1171           0 :         ifp->if_timer = 0;
    1172           0 :         ifq_clr_oactive(&ifp->if_snd);
    1173             : 
    1174           0 :         m_freem(c->mue_mbuf);
    1175           0 :         c->mue_mbuf = NULL;
    1176             : 
    1177           0 :         if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    1178           0 :                 mue_start(ifp);
    1179             : 
    1180           0 :         splx(s);
    1181           0 : }
    1182             : 
    1183             : void
    1184           0 : mue_init(void *xsc)
    1185             : {
    1186           0 :         struct mue_softc *sc = xsc;
    1187           0 :         struct ifnet *ifp = GET_IFP(sc);
    1188             :         int s;
    1189             : 
    1190           0 :         s = splnet();
    1191             : 
    1192             :         /* Cancel pending I/O and free all TX/RX buffers. */
    1193           0 :         mue_reset(sc);
    1194             : 
    1195             :         /* Set MAC address. */
    1196           0 :         mue_set_macaddr(sc);
    1197             : 
    1198             :         /* Init RX ring. */
    1199           0 :         if (mue_rx_list_init(sc) == ENOBUFS) {
    1200           0 :                 printf("%s: rx list init failed\n", sc->mue_dev.dv_xname);
    1201           0 :                 splx(s);
    1202           0 :                 return;
    1203             :         }
    1204             : 
    1205             :         /* Init TX ring. */
    1206           0 :         if (mue_tx_list_init(sc) == ENOBUFS) {
    1207           0 :                 printf("%s: tx list init failed\n", sc->mue_dev.dv_xname);
    1208           0 :                 splx(s);
    1209           0 :                 return;
    1210             :         }
    1211             : 
    1212             :         /* Program promiscuous mode and multicast filters. */
    1213           0 :         mue_iff(sc);
    1214             : 
    1215           0 :         if (mue_open_pipes(sc) != 0) {
    1216           0 :                 splx(s);
    1217           0 :                 return;
    1218             :         }
    1219             : 
    1220           0 :         sc->mue_link = 0;
    1221           0 :         ifp->if_flags |= IFF_RUNNING;
    1222           0 :         ifq_clr_oactive(&ifp->if_snd);
    1223             : 
    1224           0 :         splx(s);
    1225             : 
    1226           0 :         timeout_add_sec(&sc->mue_stat_ch, 1);
    1227           0 : }
    1228             : 
    1229             : int
    1230           0 : mue_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    1231             : {
    1232           0 :         struct mue_softc *sc = ifp->if_softc;
    1233           0 :         struct ifreq *ifr = (struct ifreq *)data;
    1234             :         int s, error = 0;
    1235             : 
    1236           0 :         s = splnet();
    1237             : 
    1238           0 :         switch(cmd) {
    1239             :         case SIOCSIFADDR:
    1240           0 :                 ifp->if_flags |= IFF_UP;
    1241           0 :                 if (!(ifp->if_flags & IFF_RUNNING))
    1242           0 :                         mue_init(sc);
    1243             :                 break;
    1244             :         case SIOCSIFFLAGS:
    1245           0 :                 if (ifp->if_flags & IFF_UP) {
    1246           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1247           0 :                                 error = ENETRESET;
    1248             :                         else
    1249           0 :                                 mue_init(sc);
    1250             :                 } else {
    1251           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1252           0 :                                 mue_stop(sc);
    1253             :                 }
    1254             :                 break;
    1255             :         case SIOCGIFMEDIA:
    1256             :         case SIOCSIFMEDIA:
    1257           0 :                 error = ifmedia_ioctl(ifp, ifr, &sc->mue_mii.mii_media, cmd);
    1258           0 :                 break;
    1259             :         default:
    1260           0 :                 error = ether_ioctl(ifp, &sc->arpcom, cmd, data);
    1261           0 :         }
    1262             : 
    1263           0 :         if (error == ENETRESET) {
    1264           0 :                 if (ifp->if_flags & IFF_RUNNING)
    1265           0 :                         mue_iff(sc);
    1266             :                 error = 0;
    1267           0 :         }
    1268             : 
    1269           0 :         splx(s);
    1270             : 
    1271           0 :         return(error);
    1272             : }
    1273             : 
    1274             : void
    1275           0 : mue_watchdog(struct ifnet *ifp)
    1276             : {
    1277           0 :         struct mue_softc *sc = ifp->if_softc;
    1278             :         struct mue_chain *c;
    1279           0 :         usbd_status stat;
    1280             :         int s;
    1281             : 
    1282           0 :         ifp->if_oerrors++;
    1283           0 :         printf("%s: watchdog timeout\n", sc->mue_dev.dv_xname);
    1284             : 
    1285           0 :         s = splusb();
    1286           0 :         c = &sc->mue_cdata.mue_tx_chain[0];
    1287           0 :         usbd_get_xfer_status(c->mue_xfer, NULL, NULL, NULL, &stat);
    1288           0 :         mue_txeof(c->mue_xfer, c, stat);
    1289             : 
    1290           0 :         if (!IFQ_IS_EMPTY(&ifp->if_snd))
    1291           0 :                 mue_start(ifp);
    1292           0 :         splx(s);
    1293           0 : }
    1294             : 
    1295             : void
    1296           0 : mue_reset(struct mue_softc *sc)
    1297             : {
    1298           0 :         if (usbd_is_dying(sc->mue_udev))
    1299             :                 return;
    1300             : 
    1301             :         /* Wait a little while for the chip to get its brains in order. */
    1302           0 :         DELAY(1000);
    1303           0 : }
    1304             : 
    1305             : void
    1306           0 : mue_start(struct ifnet *ifp)
    1307             : {
    1308           0 :         struct mue_softc *sc = ifp->if_softc;
    1309             :         struct mbuf *m_head = NULL;
    1310             : 
    1311           0 :         if (!sc->mue_link)
    1312           0 :                 return;
    1313             : 
    1314           0 :         if (ifq_is_oactive(&ifp->if_snd))
    1315           0 :                 return;
    1316             : 
    1317           0 :         m_head = ifq_deq_begin(&ifp->if_snd);
    1318           0 :         if (m_head == NULL)
    1319           0 :                 return;
    1320             : 
    1321           0 :         if (mue_encap(sc, m_head, 0)) {
    1322           0 :                 ifq_deq_rollback(&ifp->if_snd, m_head);
    1323           0 :                 ifq_set_oactive(&ifp->if_snd);
    1324           0 :                 return;
    1325             :         }
    1326           0 :         ifq_deq_commit(&ifp->if_snd, m_head);
    1327             : 
    1328             :         /* If there's a BPF listener, bounce a copy of this frame to him. */
    1329             : #if NBPFILTER > 0
    1330           0 :         if (ifp->if_bpf)
    1331           0 :                 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
    1332             : #endif
    1333             : 
    1334           0 :         ifq_set_oactive(&ifp->if_snd);
    1335             : 
    1336             :         /* Set a timeout in case the chip goes out to lunch. */
    1337           0 :         ifp->if_timer = 5;
    1338           0 : }
    1339             : 
    1340             : void
    1341           0 : mue_stop(struct mue_softc *sc)
    1342             : {
    1343             :         struct ifnet *ifp;
    1344             : 
    1345           0 :         ifp = GET_IFP(sc);
    1346           0 :         ifp->if_timer = 0;
    1347           0 :         ifp->if_flags &= ~IFF_RUNNING;
    1348           0 :         ifq_clr_oactive(&ifp->if_snd);
    1349             : 
    1350           0 :         timeout_del(&sc->mue_stat_ch);
    1351             : 
    1352           0 :         sc->mue_link = 0;
    1353           0 : }
    1354             : 
    1355             : void
    1356           0 : mue_tick(void *xsc)
    1357             : {
    1358           0 :         struct mue_softc *sc = xsc;
    1359             : 
    1360           0 :         if (sc == NULL)
    1361           0 :                 return;
    1362             : 
    1363           0 :         if (usbd_is_dying(sc->mue_udev))
    1364           0 :                 return;
    1365             : 
    1366             :         /* Perform periodic stuff in process context. */
    1367           0 :         usb_add_task(sc->mue_udev, &sc->mue_tick_task);
    1368           0 : }
    1369             : 
    1370             : void
    1371           0 : mue_tick_task(void *xsc)
    1372             : {
    1373           0 :         struct mue_softc *sc =xsc;
    1374             :         struct mii_data *mii;
    1375             :         int s;
    1376             : 
    1377           0 :         if (sc == NULL)
    1378           0 :                 return;
    1379             : 
    1380           0 :         if (usbd_is_dying(sc->mue_udev))
    1381           0 :                 return;
    1382             : 
    1383           0 :         mii = GET_MII(sc);
    1384             : 
    1385           0 :         s = splnet();
    1386           0 :         mii_tick(mii);
    1387           0 :         if (sc->mue_link == 0)
    1388           0 :                 mue_miibus_statchg(&sc->mue_dev);
    1389           0 :         timeout_add_sec(&sc->mue_stat_ch, 1);
    1390           0 :         splx(s);
    1391           0 : }

Generated by: LCOV version 1.13