Diff for /wikisrc/Converting_drivers_to_the_new_wifi_stack.mdwn between versions 1.5 and 1.6

version 1.5, 2020/09/29 18:27:59 version 1.6, 2020/10/17 17:47:24
Line 18  single radio hardware, which is naturall Line 18  single radio hardware, which is naturall
 being created (by pure software) using the same physical radio device.  being created (by pure software) using the same physical radio device.
   
  At the user level the radio hardware is hidden quite well - it only   At the user level the radio hardware is hidden quite well - it only
 shows up in dmesg or ``sysctl net.wlan.devices``.  shows up in `dmesg` or `sysctl net.wlan.devices`.
 There is no network interface for the raw hardware, so ifconfig will  There is no network interface for the raw hardware, so ifconfig will
 not show them.  not show them.
   
Line 30  use a command like: Line 30  use a command like:
  This split between common radio hardware and per-VAP network properties   This split between common radio hardware and per-VAP network properties
 reflects on the driver and causes most of the changes needed.  reflects on the driver and causes most of the changes needed.
   
  After creation of the ``wlan0`` VAP, it will also show up under   After creation of the `wlan0` VAP, it will also show up under
   
     sysctl net.wlan.wlan0      sysctl net.wlan.wlan0
   
Line 42  reflects on the driver and causes most o Line 42  reflects on the driver and causes most o
   
 # Step by Step at the driver level  # Step by Step at the driver level
   
  * The data is split into the generic ``struct ieee80211com``   * The data is split into the generic `struct ieee80211com`
    describing the radio hardware (often used as ``ic`` pointer),     describing the radio hardware (often used as `ic` pointer),
    which is part of the drivers softc. The individual VAPs are     which is part of the drivers softc. The individual VAPs are
    in a TAILQ in the ic structure, and often are a driver defined     in a TAILQ in the ic structure, and often are a driver defined
    structure 'derived' from ``struct ieee80211vap`` (with some     structure 'derived' from `struct ieee80211vap` (with some
    additional driver specific data). The VAP structure has the     additional driver specific data). The VAP structure has the
    network interface ``struct ifnet`` as ``iv_ifp.     network interface `struct ifnet` as `iv_ifp`.
    The ``if_softc`` pointer in     The `if_softc` pointer in the ifnet structure points to the VAP, the VAP structure
    the ifnet structure points to the VAP, the VAP structure     has a pointer to the ic `iv_ic`, the ic structure has a `ic_softc` pointer to the softc.
    has a pointer to the ic ``iv_ic``,  
    the ic structure has a ``ic_softc`` pointer to the softc.  
   
  * MAC addresses are now stored in ic_macaddr instead of ic_myaddr   * MAC addresses are now stored in ic_macaddr instead of ic_myaddr
    (in struct ieee80211com). It is typically read from the device     (in struct ieee80211com). It is typically read from the device
Line 60  reflects on the driver and causes most o Line 58  reflects on the driver and causes most o
   
     IEEE80211_ADDR_COPY(ic->ic_macaddr, rom->macaddr);      IEEE80211_ADDR_COPY(ic->ic_macaddr, rom->macaddr);
   
  * In the attach function, no ``struct ifnet ifp`` will be needed,   * In the attach function, no `struct ifnet ifp` will be needed,
    so get rid of code like:     so get rid of code like:
   
      struct ifnet *ifp = GET_IFP(sc);       struct ifnet *ifp = GET_IFP(sc);
Line 88  reflects on the driver and causes most o Line 86  reflects on the driver and causes most o
   
    Note that the way channels are set up has changed.     Note that the way channels are set up has changed.
    If your driver had a driver_init_channels() function, you can     If your driver had a driver_init_channels() function, you can
    use it mostly verbatim. Rename it to ``driver_get_radiocaps`` and     use it mostly verbatim. Rename it to `driver_get_radiocaps` and
    make it look like:     make it look like:
   
     ```      ```
Line 106  reflects on the driver and causes most o Line 104  reflects on the driver and causes most o
     }      }
     ```      ```
   
    and also assign this function to ``ic->ic_getradiocaps`` in     and also assign this function to `ic->ic_getradiocaps` in
    the attach function.     the attach function.
   
    An initial setup must happen before calling ``ieee80211_ifattach(ic)``.     An initial setup must happen before calling `ieee80211_ifattach(ic)`.
    You can just call the ``driver_get_radiocaps()`` function during     You can just call the `driver_get_radiocaps()` function during
    attach like:     attach like:
   
     ```      ```
Line 122  reflects on the driver and causes most o Line 120  reflects on the driver and causes most o
     ```      ```
   
  * If your driver used to override state machine functions (typical   * If your driver used to override state machine functions (typical
    ``newstate`` to controll LEDs when associating or similar),     `newstate` to controll LEDs when associating or similar),
    remove all traces for this from your softc and override a     remove all traces for this from your softc and override a
    custom VAP type instead (i.e. derive a struct from     custom VAP type instead (i.e. derive a struct from
    struct ieee80211vap and use your own struct in your vap_create     struct ieee80211vap and use your own struct in your vap_create
Line 133  reflects on the driver and causes most o Line 131  reflects on the driver and causes most o
    newstate function, which now is per VAP and moved into your     newstate function, which now is per VAP and moved into your
    derived per-VAP structure.     derived per-VAP structure.
   
  * Many functions will get a ``struct ieee80211vap *vap`` passed instead   * Many functions will get a `struct ieee80211vap *vap` passed instead
    of a softc. A typical change to adapt for that looks like:     of a softc. A typical change to adapt for that looks like:
   
     ```      ```
Line 164  reflects on the driver and causes most o Line 162  reflects on the driver and causes most o
    This device private send queue (writer: any of the current VAPs     This device private send queue (writer: any of the current VAPs
    of this interface, consumer: the devices transmit interrupt handler)     of this interface, consumer: the devices transmit interrupt handler)
    abuses the mbuf rcvif pointer to store the node pointer     abuses the mbuf rcvif pointer to store the node pointer
    ``struct ieee80211_node *`` of the target node for this packet.     `struct ieee80211_node *` of the target node for this packet.
    When dequeing a packet before handing it over to the output function,     When dequeing a packet before handing it over to the output function,
    the node is extracted and the rcvif pointer set to NULL.     the node is extracted and the rcvif pointer set to NULL.
    Yes - this is a hack.     Yes - this is a hack.
Line 175  reflects on the driver and causes most o Line 173  reflects on the driver and causes most o
     ic->ic_name = device_xname(self);      ic->ic_name = device_xname(self);
   
    Many drivers query the hardware/firmware for the number of available     Many drivers query the hardware/firmware for the number of available
    input / output queues and store these in e.g. ``sc->ntxchains``     input / output queues and store these in e.g. `sc->ntxchains`
    and ``sc->nrxchains`` or similar variables. This information     and `sc->nrxchains` or similar variables. This information
    needs to be propagated to the common radio structure:     needs to be propagated to the common radio structure:
   
     ```      ```
Line 188  reflects on the driver and causes most o Line 186  reflects on the driver and causes most o
   
     ic->ic_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;      ic->ic_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
   
    After calling ``ieee80211_ifattach(ic);`` some methods in ic     After calling `ieee80211_ifattach(ic);` some methods in ic
    need to be overwritten. The functions needed are explained     need to be overwritten. The functions needed are explained
    below, here is a typical setup:     below, here is a typical setup:
   
Line 208  reflects on the driver and causes most o Line 206  reflects on the driver and causes most o
   
   
  * detach does not deal with any interfaces any more, remove all traces   * detach does not deal with any interfaces any more, remove all traces
    of ``struct ifnet *ifp``.     of `struct ifnet *ifp`.
   
  * Add a new function for VAP creation and move all interface specific   * Add a new function for VAP creation and move all interface specific
    setup there. It looks like:     setup there. It looks like:
Line 228  reflects on the driver and causes most o Line 226  reflects on the driver and causes most o
     }      }
     ```      ```
   
    It allocates a new VAP with ``kmem_zalloc`` initializes it     It allocates a new VAP with `kmem_zalloc` initializes it
    by calling ``ieee80211_vap_setup`` for it and then ovverriding whatever     by calling `ieee80211_vap_setup` for it and then ovverriding whatever
    the driver needs, passes it to ``ieee80211_vap_attach`` and     the driver needs, passes it to `ieee80211_vap_attach` and
    attaches bpf to the interface.     attaches bpf to the interface.
   
    If your interrupt handler is called in hard interrupt context     If your interrupt handler is called in hard interrupt context
Line 295  reflects on the driver and causes most o Line 293  reflects on the driver and causes most o
    device.     device.
   
  * The set channel function is generic now, so gets passed a   * The set channel function is generic now, so gets passed a
    ``struct ieee80211com *ic`` instead of a softc, and sets     `struct ieee80211com *ic` instead of a softc, and sets
    the radio hardware to the current channel in that structure,     the radio hardware to the current channel in that structure,
    ``ic->ic_curchan``.     `ic->ic_curchan`.
   
  * The start function does not need a ``struct ifnet *ifp`` any more,   * The start function does not need a `struct ifnet *ifp` any more,
    but can use a softc or ``struct ieee80211com *ic`` instead. It is     but can use a softc or `struct ieee80211com *ic` instead. It is
    supposed to send management frames (from ic->ic_mgtq) first, then     supposed to send management frames (from ic->ic_mgtq) first, then
    everything in the device sc_sendq (see above).     everything in the device sc_sendq (see above).
   
  * Typicall generic "media change" and "status" functions will   * Typicall generic "media change" and "status" functions will
    be used: ``ieee80211_media_change`` and ``ieee80211_media_status``.     be used: `ieee80211_media_change` and `ieee80211_media_status`.
    Old drivers often implement their own function - remove that (unless     Old drivers often implement their own function - remove that (unless
    there is something actually chip specific in them).     there is something actually chip specific in them).
   
    If there is, override media_change and/or media_status, and make     If there is, override media_change and/or media_status, and make
    sure to call the generic variant for all the real work. Also     sure to call the generic variant for all the real work. Also
    make sure to pass your override function to ``ieee80211_vap_attach``.     make sure to pass your override function to `ieee80211_vap_attach`.
    run(4) is an example of this.     run(4) is an example of this.
   
    The overriden media_{change,status} functions are the only one     The overriden media_{change,status} functions are the only one
    in a wlan driver that should get a ``struct ifnet *`` argument     in a wlan driver that should get a `struct ifnet *` argument
    passed. Checking for this is a good measurement to know you are     passed. Checking for this is a good measurement to know you are
    done with conversion (besides the kernel build failing, of course).     done with conversion (besides the kernel build failing, of course).
   
Line 361  reflects on the driver and causes most o Line 359  reflects on the driver and causes most o
     struct urtwn_softc *sc = ic->ic_softc;      struct urtwn_softc *sc = ic->ic_softc;
     ```      ```
   
    The check for encrypting packets often was testing the ``ieee80211_frame`     The check for encrypting packets often was testing the `ieee80211_frame'
    wh->i_fc[1] & IEEE80211_FC1_WE`` before encapsulating the ``mbuf``     wh->i_fc[1] & IEEE80211_FC1_WE` before encapsulating the `mbuf`
    via ``ieee80211_crypto_encap()``. The check now is for     via `ieee80211_crypto_encap()`. The check now is for
    ``wh->i_fc[1] & IEEE80211_FC1_PROTECTED``, since WEP is a thing of the     `wh->i_fc[1] & IEEE80211_FC1_PROTECTED`, since WEP is a thing of the
    past and there are other protocols. Also the ``ieee80211_crypto_encap``     past and there are other protocols. Also the `ieee80211_crypto_encap`
    function lost its first argument (the radio common ic pointer).     function lost its first argument (the radio common ic pointer).
   
      XXXXX       XXXXX
   
    This function frees the ``mbuf`` and calls ``ieee80211_free_node(ni)``.     This function frees the `mbuf` and calls `ieee80211_free_node(ni)`.
   
  * If the driver_activate() function only passes deactivation requests   * If the driver_activate() function only passes deactivation requests
    on to if_deactivate() you can replace it by a shim that gets     on to if_deactivate() you can replace it by a shim that gets
Line 450  reflects on the driver and causes most o Line 448  reflects on the driver and causes most o
     }      }
     ```      ```
   
    There is no ``ieee80211_watchdog()`` function any more.     There is no `ieee80211_watchdog()` function any more.
   
   
  * ioctl functions   * ioctl functions

Removed from v.1.5  
changed lines
  Added in v.1.6


CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb