| USBNET(9) | Kernel Developer's Manual | USBNET(9) | 
usbnet —
#include <dev/usb/usbnet.h>
usbnet_set_link(struct
  usbnet *un, bool
  link);
void
  
  usbnet_set_dying(struct
    usbnet *un, bool
    dying);
struct ifnet *
  
  usbnet_ifp(struct
    usbnet *un);
struct ethercom *
  
  usbnet_ec(struct
    usbnet *un);
struct mii_data *
  
  usbnet_mii(struct
    usbnet *un);
krndsource_t *
  
  usbnet_rndsrc(struct
    usbnet *un);
void *
  
  usbnet_softc(struct
    usbnet *un);
bool
  
  usbnet_havelink(struct
    usbnet *un);
bool
  
  usbnet_isdying(struct
    usbnet *un);
void
  
  usbnet_lock(struct
    usbnet *un);
void
  
  usbnet_unlock(struct
    usbnet *un);
kmutex_t *
  
  usbnet_mutex(struct
    usbnet *un);
void
  
  usbnet_isowned(struct
    usbnet *un);
void
  
  usbnet_lock_rx(struct
    usbnet *un);
void
  
  usbnet_unlock_rx(struct
    usbnet *un);
kmutex_t *
  
  usbnet_mutex_rx(struct
    usbnet *un);
void
  
  usbnet_isowned_rx(struct
    usbnet *un);
void
  
  usbnet_lock_tx(struct
    usbnet *un);
void
  
  usbnet_unlock_tx(struct
    usbnet *un);
kmutex_t *
  
  usbnet_mutex_tx(struct
    usbnet *un);
void
  
  usbnet_isowned_tx(struct
    usbnet *un);
int
  
  usbnet_init_rx_tx(struct
    usbnet *un, unsigned
    rxflags, unsigned
    txflags);
void
  
  usbnet_lock_mii(struct
    usbnet *un);
void
  
  usbnet_lock_mii_un_locked(struct
    usbnet *un);
void
  
  usbnet_unlock_mii(struct
    usbnet *un);
void
  
  usbnet_unlock_mii_un_locked(struct
    usbnet *un);
kmutex_t *
  
  usbnet_mutex_mii(struct
    usbnet *un);
void
  
  usbnet_isowned_mii(struct
    usbnet *un);
int
  
  usbnet_miibus_readreg(device_t
    dev, int phy,
    int reg,
    uint16_t *val);
int
  
  usbnet_miibus_writereg(device_t
    dev, int phy,
    int reg,
    uint16_t val);
void
  
  usbnet_miibus_statchg(struct
    ifnet *);
void
  
  usbnet_enqueue(struct
    usbnet *un, uint8_t
    *buf, size_t
    buflen, int
    csum_flags, uint32_t
    csum_data, int
    mbuf_flags);
void
  
  usbnet_input(struct
    usbnet *un, uint8_t
    *buf, size_t
    buflen);
void
  
  usbnet_attach(struct
    usbnet *un, const char
    *detname);
void
  
  usbnet_attach_ifp(struct
    usbnet *un, unsigned
    if_flags, unsigned
    if_extflags, const struct
    usbnet_mii *unm);
int
  
  usbnet_detach(device_t
    dev, int
  flags);
int
  
  usbnet_activate(device_t
    dev, devact_t
  act);
void
  
  usbnet_stop(struct
    usbnet *un, struct ifnet
    *ifp, int
  disable);
usbnet framework provides methods usable for USB
  Ethernet drivers. The framework has support for these features:
usbnet provides many or all of the
    traditional “softc” members inside struct
    usbnet, which can be used directly as the device softc structure if no
    additional storage is required. A structure exists for receive and transmit
    chain management, struct usbnet_chain, that tracks the
    metadata for each transfer descriptor available, minimum of one each for Rx
    and Tx slot, and will be passed to the Rx and Tx callbacks.
There is a struct usbnet_ops structure that provides a number of optional and required callbacks that will be described below.
For autoconfiguration the device attach routine is expected to
    ensure that this device's struct usbnet is the first
    member of the device softc, if it can not be used directly as the device
    softc, as well as set up the necessary structure members, find end-points,
    find the Ethernet address if relevant, call
    usbnet_attach(), set up interface, Ethernet, and MII
    capabilities, and finally call usbnet_attach_ifp().
    The device detach routine should free any resources allocated by attach and
    then call usbnet_detach(), possibly directly using
    usbnet_detach() as most consumers have no additional
    resources not owned and released by the usbnet
    framework itself. The device activate function should be set to
    usbnet_activate().
To manage all Rx and Tx chains the “uno_init”
    callback of struct usbnet_ops should perform any
    device specific initialization and then call
    usbnet_init_rx_tx() which will allocate chains, set
    up and open pipes, and start the Rx transfers so that packets can arrived.
    These allocations and pipes can be closed and destroyed by calling
    usbnet_stop(). Both of
    usbnet_init_rx_tx() and
    usbnet_stop() must be called with the
    usbnet lock held, see
    usbnet_lock() and
    usbnet_unlock(). See the
    RECEIVE AND SEND section for
    details on using the chains.
The interface init, ioctl, start, and stop, routines are handled
    by the framework with callbacks for device-specific handling. For interface
    init (i.e., when bringing the interface up), the “uno_init”
    callback should perform any device specific initialization and then call
    usbnet_init_rx_tx() to finalize Rx and Tx queue
    initialization. For interface ioctl, most of the handling is in the
    framework and the optional “uno_ioctl” callback should be used
    to program special settings like multicast filters or offload handling. If
    ioctl handling requires capturing device-specific ioctls then the
    “uno_override_ioctl” callback may be used instead to replace
    the framework's ioctl handler completely (i.e., the replacement should call
    any generic ioctl handlers such as ether_ioctl() as
    required.) For interface start, the “uno_tx_prepare” callback
    must be used to convert an mbuf into a chain buffer ready for transmission.
    For interface stop, there is an optional “uno_stop” callback
    to turn off any chipset specific values if required.
For devices requiring MII handling there are callbacks for reading
    and writing registers, and for status change events. The framework provides
    an MII-specific lock per interface which will be held when calling these
    functions, and these locks should be used by internal code that also
    requires serialized access to registers with the
    usbnet_lock_mii(),
    usbnet_unlock_mii(),
    usbnet_lock_mii_un_locked(), and
    usbnet_unlock_mii_un_locked() functions. These
    functions handle device detach events safely, and as such take and release a
    reference on this device and use the usbnet lock for this. Sometimes the
    usbnet lock is already held and instead the “un_locked”
    versions should be used.
As receive must handle the case of multiple packets in one buffer,
    the support is split between the driver and the framework. A
    “uno_rx_loop” callback must be provided that loops over the
    incoming packet data found in a chain, performs necessary checking and
    passes the network frame up the stack via either
    usbnet_enqueue() or
    usbnet_input(). Typically Ethernet devices prefer
    usbnet_enqueue().
General accessor functions for struct usbnet:
usbnet_set_link(un,
    link)usbnet_set_dying(un,
    dying)usbnet_ifp(un)usbnet_ec(un)usbnet_mii(un)usbnet_rndsrc(un)usbnet_softc(un)bool(usbnet_havelink,
    un)bool(usbnet_isdying,
    un)Lock handling functions for struct usbnet:
usbnet_lock(un)usbnet_unlock(un)usbnet_isowned(un)usbnet_lock_rx(un)usbnet_unlock_rx(un)usbnet_isowned_rx(un)usbnet_lock_tx(un)usbnet_unlock_tx(un)usbnet_isowned_tx(un)usbnet_lock_mii(un)usbnet_lock_mii_un_locked(un)usbnet_unlock_mii(un)usbnet_unlock_mii_un_locked(un)usbnet_isowned_mii(un)usbnet. The four locks are the
      “softc” lock, the “Tx” lock, the
      “Rx” lock, and the “MII” lock. The MII lock is
      special in that it blocks device detach using an internal reference count
      and is frequently required when both the “softc” lock is
      held or unheld, and two versions are provided that either hold the
      “softc” lock while increasing or decreasing the reference
      count, or assume (and in debug builds, assert) the lock is held for the
      “un_locked” versions.MII access functions for struct usbnet:
usbnet_mii_readreg(dev,
    phy, reg,
    valp)usbnet_mii_writereg(dev,
    phy, reg,
    val)usbnet_mii_statchg(ifp)Buffer enqueue handling for struct usbnet:
usbnet_enqueue(un,
    buf, buflen,
    csum_flags, csum_data,
    mbuf_flags)usbnet_input(un,
    buf, buflen)Autoconfiguration handling for struct usbnet. See the AUTOCONFIGURATION section for more details about these functions.
usbnet_attach(un,
    detachname)usbnet_attach_ifp(un,
    if_flags, if_extflags,
    unm)NULL then an MII
      interface will be created using the values provided in the
      struct usbnet_mii structure, which has these members
      passed to mii_attach():
    A default unm can be set using the
        USBNET_MII_DECL_DEFAULT() macro. The
        if_flags and if_extflags
        will be or-ed into the interface flags and extflags.
usbnet_detach(dev,
    flags)usbnet_activate(dev,
    act)usbnet_stop(un,
    ifp, disable)usbd_device2interface_handle() for more
    details.(*uno_stop)(struct ifnet
        *ifp, int disable)(*uno_ioctl)(struct ifnet
        *ifp, u_long cmd, void
        *data)(*uno_override_ioctl)(struct
        ifnet *ifp, u_long cmd, void
        *data)(*uno_init)(struct ifnet
        *ifp)usbnet_rx_tx_init().(*uno_read_reg)(struct usbnet
        *un, int phy, int reg,
        uint16_t *val)(*uno_write_reg)(struct usbnet
        *un, int phy, int reg,
        uint16_t val)(*uno_statchg)(struct ifnet
        *ifp)(*uno_tx_prepare)(struct usbnet
        *un, struct mbuf *m, struct
        usbnet_chain *c)(*uno_rx_loop)(struct usbnet
        *un, struct usbnet_chain *c,
        uint32_t total_len)(*uno_intr)(struct usbnet
        *un, usbd_status status)(*uno_tick)(struct usbnet
        *un)NULL, points to a buffer passed to
          usbd_open_pipe_intr() in the device init
          callback, along with the size and interval.USBNET_ENDPT_RX,
      USBNET_ENDPT_TX, and
      USBNET_ENDPT_INTR. The Rx and Tx endpoints are
      required.usbnet.usbnet_attach_ifp() if the device has
    Ethernet.usbnet framework will
      not touch this value.usbd_setup_xfer() for receiving
    packets.usbd_setup_xfer() for sending
    packets.The device detach and activate callbacks can typically be set to
    usbnet_detach() and
    usbnet_activate() unless device-specific handling is
    required, in which case, they can be called before or after such
  handling.
The capabilities described in both struct
    ifp and struct ethercom must be set before
    calling usbnet_attach_ifp().
un_ed,
  un_rx_xfer_flags, and
  un_tx_xfer_flags members, and the
  uno_stop(), uno_init(),
  uno_tx_prepare(), and
  uno_rx_loop() callbacks of
  usbnet_ops.
Typically, the device attach routine will fill in members of the
    usbnet structure, as listed in
    AUTOCONFIGURATION. The
    un_ed() member should have the
    USBNET_ENDPT_RX and
    USBNET_ENDPT_TX array entries filled in, and
    optionally the USBNET_ENDPT_INTR entry filled in if
    applicable.
The optional uno_stop() callback performs
    device-specific operations to shutdown the transmit or receive handling.
    uno_stop() will be called with the usbnet lock
  held.
The uno_init() callback both performs
    device-specific enablement and then calls
    usbnet_rx_tx_init(), which sets up the receive,
    transmit, and, optionally, the interrupt pipes, as well as starting the
    receive pipes. All USB transfer setup is handled internally to the
    framework, and the driver callbacks merely copy data in or out of a chain
    entry using what is typically a device-specific method.
The uno_rx_loop() callback converts the
    provided usbnet_chain data and length into a series
    (one or more) of packets that are enqueued with the higher layers using
    either usbnet_enqueue() (for most devices) or
    usbnet_input() for devices that use
    if_input() (this currently relies upon the
    struct ifnet having the “_if_input”
    member set as well, which is true for current consumers.) The Rx lock will
    be held during this call, see usbnet_lock_rx() and
    usbnet_unlock_rx().
The uno_tx_prepare() callback must convert
    the provided struct mbuf into the provided
    struct usbnet_chain performing any device-specific
    padding, checksum, header or other. Note that this callback must check that
    it is not attempting to copy more than the chain buffer size, as set in the
    usbnet “un_tx_bufsz” member. This
    callback is only called once per packet. The Tx lock will be held during
    this call, see usbnet_lock_tx() and
    usbnet_unlock_tx().
The struct usbnet_chain structure which contains a “unc_buf” member which has the chain buffer allocated where data should be copied to or from for receive or transmit operations. It also contains pointers back to the owning struct usbnet, and the struct usbd_xfer associated with this transfer.
usbnet_lock_mii() and
  usbnet_unlock_mii().
usbnet using the
  usbd_open_pipe_intr() function (instead of the
  usbd_open_pipe() function.) The
  usbnet framework provides most of the interrupt
  handling and the callback simply inspects the returned buffer as necessary. To
  enable the this callback point the struct usbnet member
  “un_intr” to a struct usbnet_intr
  structure with these members set:
These values will be passed to
    usbd_open_pipe_intr().
usbnet framework
  is largely an effort in deleting code. The process involves making these
  changes:
Many drivers can use the usbnet
        structure as the device private storage passed to
        CFATTACH_DECL_NEW. Many internal functions to
        the driver may look better if switched to operate on the device's
        usbnet as, for example, the
        usbd_device value is now available (and must be
        set by the driver) in the usbnet, which may be
        needed for any call to usbd_do_request(). The
        standard endpoint values must be stored in the
        usbnet “un_ed[]” array.
As usbnet manages xfer chains all code
        related to the opening, closing, aborting and transferring of data on
        pipes is performed by the framework based upon the buffer size and more
        provided in subnet, so all code related to them
        should be deleted.
usbnet_attach_ifp(). All calls to
      ifmedia_init(),
      mii_attach(),
      ifmedia_add(),
      ifmedia_set(),
      if_attach(),
      ether_ifattach(),
      rnd_attach_source(), and
      usbd_add_drv_event() should be eliminated. The
      device “ioctl” routine can use the default handling with a
      callback for additional device specific programming (multicast filters,
      etc.), which can be empty, or, the override ioctl can be used for heavier
      requirements. The device “stop” routine is replaced with a
      simple call that turns off the device-specific transmitter and receiver if
      necessary, as the framework handles pipes and transfers and buffers.usbnet framework provides four locks for the
      system: normal device/softc lock, receive and transmit locks, and the MII
      lock. The normal locking order for these locks is ifnet lock -> usbnet
      lock -> usbnet rxlock -> usbne txlock, or, ifnet lock -> usbnet
      lock -> MII lock.usbnet_isowned_mii()”), and do not
      require any checking for running, or up, or dying devices unless they drop
      and retake the MII lock. Local “link” variables need to be
      replaced with accesses to usbnet_set_link() and
      usbnet_havelink(). Other ifmedia callbacks that
      were passed to ifmedia_init() should be deleted
      and any work moved into “uno_statchg”.usbnet framework handles the majority of
      handling of both network directions. The interface init routine should
      keep all of the device specific setup but replace all pipe management with
      a call to usbnet_init_rx_tx(). The typical receive
      handling will normally be replaced with a receive loop functions that can
      accept one or more packets, “uno_rx_loop”, which can use
      either usbnet_enqueue() or
      usbnet_input() to pass the packets upto higher
      layers. The typical interface “if_start” function and any
      additional functions used will normal be replaced with a relatively simple
      “uno_tx_prepare” function that simply converts an
      mbuf into a usbnet_chain
      useful for this device that will be passed onto
      usbd_transfer(). The framework's handling of the
      Tx interrupt is all internal.usbd_open_pipe_intr() method), most of the
      interrupt handler should be deleted, leaving only code that inspects the
      result of the interrupt transfer.usbent_set_link() during any status change
      event.
    Many locking issues are hidden without
        LOCKDEBUG, including hard-hangs. It's highly
        recommended to develop with LOCKDEBUG.
The usbnet “un_ed” array is unsigned and should use “0” as the no-endpoint value.
usbnet interface first appeared in
  NetBSD 9.0. Portions of the original design are based
  upon ideas from Nick Hudson
  <skrll@NetBSD.org>.
| August 22, 2019 | NetBSD 9.3 |