blob: bfbffd8368e29b3aacaffc58c5e4b4264199af30 [file] [log] [blame]
<!--
Documentation/_templates/layout.html
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. The
ASF licenses this file to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
-->
<!DOCTYPE html>
<html class="writer-html5" lang="en">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Network Drivers &mdash; NuttX latest documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../_static/css/theme.css" />
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
<link rel="stylesheet" type="text/css" href="../../_static/sphinx_collapse.css" />
<link rel="stylesheet" type="text/css" href="../../_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css" />
<link rel="stylesheet" type="text/css" href="../../_static/custom.css" />
<link rel="shortcut icon" href="../../_static/favicon.ico"/>
<script src="../../_static/jquery.js"></script>
<script src="../../_static/_sphinx_javascript_frameworks_compat.js"></script>
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/sphinx_highlight.js"></script>
<script src="../../_static/clipboard.min.js"></script>
<script src="../../_static/copybutton.js"></script>
<script src="../../_static/design-tabs.js"></script>
<script src="../../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
<link rel="next" title="MDIO Bus Driver" href="mdio.html" />
<link rel="prev" title="Network Devices" href="netdev.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../../index.html" class="icon icon-home"> NuttX
</a>
<!-- this version selector is quite ugly, should be probably replaced by something
more modern -->
<div class="version-selector">
<select onchange="javascript:location.href = this.value;">
<option value="../../../latest" selected="selected">latest</option>
<option value="../../../10.0.0" >10.0.0</option>
<option value="../../../10.0.1" >10.0.1</option>
<option value="../../../10.1.0" >10.1.0</option>
<option value="../../../10.2.0" >10.2.0</option>
<option value="../../../10.3.0" >10.3.0</option>
<option value="../../../11.0.0" >11.0.0</option>
<option value="../../../12.0.0" >12.0.0</option>
<option value="../../../12.1.0" >12.1.0</option>
<option value="../../../12.2.0" >12.2.0</option>
<option value="../../../12.2.1" >12.2.1</option>
<option value="../../../12.3.0" >12.3.0</option>
<option value="../../../12.4.0" >12.4.0</option>
<option value="../../../12.5.0" >12.5.0</option>
<option value="../../../12.5.1" >12.5.1</option>
<option value="../../../12.6.0" >12.6.0</option>
<option value="../../../12.7.0" >12.7.0</option>
<option value="../../../12.8.0" >12.8.0</option>
<option value="../../../12.9.0" >12.9.0</option>
<option value="../../../12.10.0" >12.10.0</option>
<option value="../../../12.11.0" >12.11.0</option>
</select>
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Table of Contents</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../../index.html">Home</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../introduction/index.html">Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../quickstart/index.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../contributing/index.html">Contributing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../introduction/inviolables.html">The Inviolable Principles of NuttX</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../platforms/index.html">Supported Platforms</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../index.html">OS Components</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../binfmt.html">Binary Loader</a></li>
<li class="toctree-l2"><a class="reference internal" href="../drivers/index.html">Device Drivers</a></li>
<li class="toctree-l2"><a class="reference internal" href="../nxflat.html">NXFLAT</a></li>
<li class="toctree-l2"><a class="reference internal" href="../nxgraphics/index.html">NX Graphics Subsystem</a></li>
<li class="toctree-l2"><a class="reference internal" href="../paging.html">On-Demand Paging</a></li>
<li class="toctree-l2"><a class="reference internal" href="../audio/index.html">Audio Subsystem</a></li>
<li class="toctree-l2"><a class="reference internal" href="../filesystem/index.html">NuttX File System</a></li>
<li class="toctree-l2"><a class="reference internal" href="../libs/index.html">NuttX libraries</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="index.html">Network Support</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="sixlowpan.html">6LoWPAN</a></li>
<li class="toctree-l3"><a class="reference internal" href="socketcan.html">SocketCAN Device Drivers</a></li>
<li class="toctree-l3"><a class="reference internal" href="pkt.html">“Raw” packet socket support</a></li>
<li class="toctree-l3"><a class="reference internal" href="ipfilter.html">IP Packet Filter</a></li>
<li class="toctree-l3"><a class="reference internal" href="nat.html">Network Address Translation (NAT)</a></li>
<li class="toctree-l3"><a class="reference internal" href="netdev.html">Network Devices</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">Network Drivers</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#how-to-change-full-network-driver-into-lower-half-one">How to change full network driver into lower-half one</a></li>
<li class="toctree-l4"><a class="reference internal" href="#lower-half-example">“Lower Half” Example</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="mdio.html">MDIO Bus Driver</a></li>
<li class="toctree-l3"><a class="reference internal" href="netguardsize.html">CONFIG_NET_GUARDSIZE</a></li>
<li class="toctree-l3"><a class="reference internal" href="netlink.html">Netlink Route support</a></li>
<li class="toctree-l3"><a class="reference internal" href="slip.html">SLIP</a></li>
<li class="toctree-l3"><a class="reference internal" href="wqueuedeadlocks.html">Work Queue Deadlocks</a></li>
<li class="toctree-l3"><a class="reference internal" href="tcp_network_perf.html">TCP Network Performance</a></li>
<li class="toctree-l3"><a class="reference internal" href="delay_act_and_tcp_perf.html">Delayed ACK and TCP Performance</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../mm/index.html">Memory Management</a></li>
<li class="toctree-l2"><a class="reference internal" href="../syscall.html">Syscall Layer</a></li>
<li class="toctree-l2"><a class="reference internal" href="../tools/index.html"><code class="docutils literal notranslate"><span class="pre">/tools</span></code> Host Tools</a></li>
<li class="toctree-l2"><a class="reference internal" href="../arch/index.html">Architecture-Specific Code</a></li>
<li class="toctree-l2"><a class="reference internal" href="../boards.html">Boards Support</a></li>
<li class="toctree-l2"><a class="reference internal" href="../cmake.html">CMake Support</a></li>
<li class="toctree-l2"><a class="reference internal" href="../openamp.html">OpenAMP Support</a></li>
<li class="toctree-l2"><a class="reference internal" href="../video.html">Video Subsystem</a></li>
<li class="toctree-l2"><a class="reference internal" href="../crypto.html">Crypto API Subsystem</a></li>
<li class="toctree-l2"><a class="reference internal" href="../wireless.html">Wireless Subsystem</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../applications/index.html">Applications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../implementation/index.html">Implementation Details</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../reference/index.html">API Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../faq/index.html">FAQ</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../debugging/index.html">Debugging</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../guides/index.html">Guides</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../standards/index.html">Standards</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../glossary.html">Glossary</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../logos/index.html">NuttX Logos</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../_tags/tagsindex.html">Tags</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../../index.html">NuttX</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="../index.html">OS Components</a></li>
<li class="breadcrumb-item"><a href="index.html">Network Support</a></li>
<li class="breadcrumb-item active">Network Drivers</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/apache/nuttx/blob/master/Documentation/components/net/netdriver.rst" class="fa fa-github"> Edit on GitHub</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="network-drivers">
<span id="netdriver"></span><h1>Network Drivers<a class="headerlink" href="#network-drivers" title="Permalink to this heading"></a></h1>
<p>The NuttX network driver is split into two parts:</p>
<ol class="arabic simple">
<li><p>An “upper half”, generic driver that provides the common network
interface to application level code, and</p></li>
<li><p>A “lower half”, platform-specific driver that implements the
low-level timer controls to implement the network functionality.</p></li>
</ol>
<p>Files supporting network driver can be found in the following locations:</p>
<ul class="simple">
<li><p><strong>Interface Definition</strong>. The header file for the NuttX network
driver resides at <code class="docutils literal notranslate"><span class="pre">include/nuttx/net/netdev_lowerhalf.h</span></code>. This
header file includes the interface between the “upper half” and
“lower half” drivers.</p></li>
<li><p><strong>“Upper Half” Driver</strong>. The generic, “upper half” network driver
resides at <code class="docutils literal notranslate"><span class="pre">drivers/net/netdev_upperhalf.c</span></code>.</p></li>
<li><p><strong>“Lower Half” Drivers</strong>. Platform-specific network drivers reside
in <code class="docutils literal notranslate"><span class="pre">arch/&lt;architecture&gt;/src/&lt;hardware&gt;</span></code> or <code class="docutils literal notranslate"><span class="pre">drivers/net</span></code>
directory for the specific processor <code class="docutils literal notranslate"><span class="pre">&lt;architecture&gt;</span></code> and for
the specific <code class="docutils literal notranslate"><span class="pre">&lt;chip&gt;</span></code> network peripheral devices.</p></li>
</ul>
<p><strong>Special Note</strong>: Not all network drivers are implemented with this
architecture. Known lower-half drivers:
<code class="docutils literal notranslate"><span class="pre">arch/sim/src/sim/sim_netdriver.c</span></code>, <code class="docutils literal notranslate"><span class="pre">drivers/virtio/virtio-net.c</span></code></p>
<section id="how-to-change-full-network-driver-into-lower-half-one">
<h2>How to change full network driver into lower-half one<a class="headerlink" href="#how-to-change-full-network-driver-into-lower-half-one" title="Permalink to this heading"></a></h2>
<p>We have many network drivers that are implemented as full network drivers
with <code class="docutils literal notranslate"><span class="pre">include/nuttx/net/netdev.h</span></code>, we can change them into lower-half
drivers to remove the common code (which is already in upper-half driver).
Here is a guide to do so:</p>
<ol class="arabic simple">
<li><p>Change <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">net_driver_s</span></code> to <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">netdev_lowerhalf_s</span></code> in
the network driver structure. If you really need to touch some fields
inside <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">net_driver_s</span></code> like MAC address, you can access them
through <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">netdev_lowerhalf_s::netdev</span></code>.</p></li>
<li><p>Change the function names called in the network driver file to the names
with prefix <code class="docutils literal notranslate"><span class="pre">netdev_lower_</span></code>, e.g. <code class="docutils literal notranslate"><span class="pre">netdev_lower_register</span></code> and
<code class="docutils literal notranslate"><span class="pre">netdev_lower_carrier_on</span></code>.</p></li>
<li><p>Change the core functions called by work queue like <code class="docutils literal notranslate"><span class="pre">txpoll</span></code> as
<code class="docutils literal notranslate"><span class="pre">transmit</span></code> and <code class="docutils literal notranslate"><span class="pre">receive</span></code> in the <code class="docutils literal notranslate"><span class="pre">netdev_ops_s</span></code> structure. You may
need to change <code class="docutils literal notranslate"><span class="pre">memcpy</span></code> for <code class="docutils literal notranslate"><span class="pre">d_buf</span></code> into <code class="docutils literal notranslate"><span class="pre">netpkt_copyin</span></code> and
<code class="docutils literal notranslate"><span class="pre">netpkt_copyout</span></code>.</p>
<ul class="simple">
<li><p>Note that the <code class="docutils literal notranslate"><span class="pre">receive</span></code> function just need to return the received
packet instead of calling functions like <code class="docutils literal notranslate"><span class="pre">ipv4_input</span></code> or doing reply.
The upper-half will call <code class="docutils literal notranslate"><span class="pre">receive</span></code> to get all packets until it
returns <code class="docutils literal notranslate"><span class="pre">NULL</span></code> and send these packets into the network stack.</p></li>
<li><p>Also remember to call <code class="docutils literal notranslate"><span class="pre">netpkt_free</span></code> for the transmitted packets.</p></li>
</ul>
</li>
<li><p>Remove work queues related to send and receive, and replace them
with calling <code class="docutils literal notranslate"><span class="pre">netdev_lower_txdone</span></code> and <code class="docutils literal notranslate"><span class="pre">netdev_lower_rxready</span></code>.
Then the upper-half driver will call <code class="docutils literal notranslate"><span class="pre">transmit</span></code> and <code class="docutils literal notranslate"><span class="pre">receive</span></code> to
send/get packets.</p></li>
<li><p>Remove any buffer related to <code class="docutils literal notranslate"><span class="pre">d_buf</span></code>, and make sure <code class="docutils literal notranslate"><span class="pre">d_buf</span></code> is not
used in the lower-half driver.</p></li>
<li><p>Remove <code class="docutils literal notranslate"><span class="pre">txavail</span></code> function, the upper-half driver will call <code class="docutils literal notranslate"><span class="pre">transmit</span></code>
when it has packets to send.</p></li>
<li><p>Remove the statistics macros like <code class="docutils literal notranslate"><span class="pre">NETDEV_TXPACKETS</span></code>, <code class="docutils literal notranslate"><span class="pre">NETDEV_TXDONE</span></code>,
<code class="docutils literal notranslate"><span class="pre">NETDEV_RXPACKETS</span></code> or <code class="docutils literal notranslate"><span class="pre">NETDEV_RXDROPPED</span></code>, these macros are well
handled in upper-half. But you may still keep macros like
<code class="docutils literal notranslate"><span class="pre">NETDEV_TXTIMEOUTS</span></code> and <code class="docutils literal notranslate"><span class="pre">NETDEV_RXERRORS</span></code> because the upper-half
cannot know whether these error happens.</p></li>
<li><p>Find a suitable <code class="docutils literal notranslate"><span class="pre">quota</span></code> for the driver, and set it in the driver
initialization function. The quota is the maximum number of buffers
that the driver can hold at the same time. For example, if the TX quota
is set to 5, it means that if the driver has 5 unreleased packets
(<code class="docutils literal notranslate"><span class="pre">netpkt_free</span></code>), the upper-half will not call <code class="docutils literal notranslate"><span class="pre">transmit</span></code> until they
are released.</p>
<ul class="simple">
<li><p>Note: An exception is that if the net stack is replying for RX packet,
this replied packet will always be put into <code class="docutils literal notranslate"><span class="pre">transmit</span></code>, which may
exceed the TX quota temporarily.</p></li>
</ul>
</li>
</ol>
</section>
<section id="lower-half-example">
<h2>“Lower Half” Example<a class="headerlink" href="#lower-half-example" title="Permalink to this heading"></a></h2>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">struct</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_priv_s</span>
<span class="p">{</span>
<span class="w"> </span><span class="cm">/* This holds the information visible to the NuttX network */</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">netdev_lowerhalf_s</span><span class="w"> </span><span class="n">dev</span><span class="p">;</span>
<span class="w"> </span><span class="p">...</span>
<span class="p">};</span>
<span class="k">static</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">netdev_ops_s</span><span class="w"> </span><span class="n">g_ops</span><span class="w"> </span><span class="o">=</span>
<span class="p">{</span>
<span class="w"> </span><span class="p">.</span><span class="n">ifup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_ifup</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">ifdown</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_ifdown</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">transmit</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_transmit</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">receive</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_receive</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">addmac</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_addmac</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">rmmac</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_rmmac</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">ioctl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_ioctl</span>
<span class="p">};</span>
<span class="cm">/* The Wi-Fi driver registration function can be implemented as follows,</span>
<span class="cm"> * where &lt;chip&gt; refers to the chip name. netdev_lower_register() is the</span>
<span class="cm"> * network device interface provided by upper-half drivers to register</span>
<span class="cm"> * network device drivers.</span>
<span class="cm"> */</span>
<span class="kt">int</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_netdev_init</span><span class="p">(</span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_priv_s</span><span class="w"> </span><span class="o">*</span><span class="n">priv</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">netdev_lowerhalf_s</span><span class="w"> </span><span class="o">*</span><span class="n">dev</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">priv</span><span class="o">-&gt;</span><span class="n">dev</span><span class="p">;</span>
<span class="w"> </span><span class="n">dev</span><span class="o">-&gt;</span><span class="n">ops</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">g_ops</span><span class="p">;</span>
<span class="w"> </span><span class="cm">/* The maximum number of buffers that the driver can hold</span>
<span class="cm"> * at the same time. For example, if the TX quota is set to 5, it</span>
<span class="cm"> * means that if the driver has 5 unreleased packets (netpkt_free),</span>
<span class="cm"> * the upper layer will not call transmit until they are released.</span>
<span class="cm"> * After the rx quota is used up and no new buffer can be allocated</span>
<span class="cm"> * (netpkt_alloc), it needs to notify the upper layer</span>
<span class="cm"> * (netdev_lower_rxready) and restore the quota by submitting buffer</span>
<span class="cm"> * back through receive function.</span>
<span class="cm"> * If the driver processes each packet individually (without</span>
<span class="cm"> * accumulating multiple packets before sending/receiving), it can be</span>
<span class="cm"> * set to 1.</span>
<span class="cm"> */</span>
<span class="w"> </span><span class="n">dev</span><span class="o">-&gt;</span><span class="n">quota</span><span class="p">[</span><span class="n">NETPKT_TX</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="n">dev</span><span class="o">-&gt;</span><span class="n">quota</span><span class="p">[</span><span class="n">NETPKT_RX</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">netdev_lower_register</span><span class="p">(</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">NET_LL_ETHERNET</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* The transmit function can be implemented as follows, where &lt;chip&gt;</span>
<span class="cm"> * refers to the chip name.</span>
<span class="cm"> */</span>
<span class="k">static</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_transmit</span><span class="p">(</span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">netdev_lowerhalf_s</span><span class="w"> </span><span class="o">*</span><span class="n">dev</span><span class="p">,</span>
<span class="w"> </span><span class="n">FAR</span><span class="w"> </span><span class="n">netpkt_t</span><span class="w"> </span><span class="o">*</span><span class="n">pkt</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_priv_s</span><span class="w"> </span><span class="o">*</span><span class="n">priv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_priv_s</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="n">dev</span><span class="p">;</span>
<span class="w"> </span><span class="kt">unsigned</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">netpkt_getdatalen</span><span class="p">(</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">pkt</span><span class="p">);</span>
<span class="cp">#if you want to do offloading</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">netpkt_is_fragmented</span><span class="p">(</span><span class="n">pkt</span><span class="p">))</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="cm">/* Contiguous memory, just use data pointer */</span>
<span class="w"> </span><span class="n">FAR</span><span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="o">*</span><span class="n">databuf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">netpkt_getdata</span><span class="p">(</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">pkt</span><span class="p">);</span>
<span class="w"> </span><span class="n">FAR</span><span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="o">*</span><span class="n">devbuf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">databuf</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_txhead_s</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Do Transmit. Note: `databuf` points to the L2 data, and there is</span>
<span class="cm"> * a reserved memory with size of `CONFIG_NET_LL_GUARDSIZE` before</span>
<span class="cm"> * databuf to be used for driver header, drivers can just fill data</span>
<span class="cm"> * there (`devbuf`) and start the transmission.</span>
<span class="cm"> */</span>
<span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span>
<span class="cp">#endif</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="cm">/* Copyout the L2 data and transmit. */</span>
<span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">devbuf</span><span class="p">[</span><span class="mi">1600</span><span class="p">];</span>
<span class="w"> </span><span class="n">netpkt_copyout</span><span class="p">(</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">devbuf</span><span class="p">,</span><span class="w"> </span><span class="n">pkt</span><span class="p">,</span><span class="w"> </span><span class="n">len</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Do Transmit */</span>
<span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">OK</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_txdone_interrupt</span><span class="p">(</span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_priv_s</span><span class="w"> </span><span class="o">*</span><span class="n">priv</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">netdev_lowerhalf_s</span><span class="w"> </span><span class="o">*</span><span class="n">dev</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">priv</span><span class="o">-&gt;</span><span class="n">dev</span><span class="p">;</span>
<span class="w"> </span><span class="cm">/* Perform some processing in the driver (if necessary) */</span>
<span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="cm">/* Free the buffer and notify the upper layer */</span>
<span class="w"> </span><span class="n">netpkt_free</span><span class="p">(</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">pkt</span><span class="p">,</span><span class="w"> </span><span class="n">NETPKT_TX</span><span class="p">);</span>
<span class="w"> </span><span class="n">netdev_lower_txdone</span><span class="p">(</span><span class="n">dev</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* The receive function can be implemented as follows, where &lt;chip&gt;</span>
<span class="cm"> * refers to the chip name.</span>
<span class="cm"> */</span>
<span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_rxready_interrupt</span><span class="p">(</span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_priv_s</span><span class="w"> </span><span class="o">*</span><span class="n">priv</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">netdev_lowerhalf_s</span><span class="w"> </span><span class="o">*</span><span class="n">dev</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">priv</span><span class="o">-&gt;</span><span class="n">dev</span><span class="p">;</span>
<span class="w"> </span><span class="n">netdev_lower_rxready</span><span class="p">(</span><span class="n">dev</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">static</span><span class="w"> </span><span class="n">FAR</span><span class="w"> </span><span class="n">netpkt_t</span><span class="w"> </span><span class="o">*&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_receive</span><span class="p">(</span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">netdev_lowerhalf_s</span><span class="w"> </span><span class="o">*</span><span class="n">dev</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="cm">/* It is also possible to allocate the pkt and receive the data in</span>
<span class="cm"> * advance, and then call rxready and return pkt through receive</span>
<span class="cm"> */</span>
<span class="w"> </span><span class="n">FAR</span><span class="w"> </span><span class="n">netpkt_t</span><span class="w"> </span><span class="o">*</span><span class="n">pkt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">netpkt_alloc</span><span class="p">(</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">NETPKT_RX</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pkt</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="cp">#if NETPKT_BUFLEN &gt; 15xx &amp;&amp; you want to do offloading</span>
<span class="w"> </span><span class="cm">/* Write directly to the buffer inside pkt, len corresponds to the</span>
<span class="cm"> * length of L2 data (need the NETPKT_BUFLEN to be large enough to</span>
<span class="cm"> * hold the data). The `&lt;chip&gt;_rxhead_s` is the driver header before</span>
<span class="cm"> * the actual data (maybe you don&#39;t have).</span>
<span class="cm"> */</span>
<span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">receive_data_into</span><span class="p">(</span><span class="n">netpkt_getbase</span><span class="p">(</span><span class="n">pkt</span><span class="p">));</span>
<span class="w"> </span><span class="n">netpkt_resetreserved</span><span class="p">(</span><span class="o">&amp;</span><span class="n">priv</span><span class="o">-&gt;</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">pkt</span><span class="p">,</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_rxhead_s</span><span class="p">));</span>
<span class="w"> </span><span class="n">netpkt_setdatalen</span><span class="p">(</span><span class="o">&amp;</span><span class="n">priv</span><span class="o">-&gt;</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">pkt</span><span class="p">,</span><span class="w"> </span><span class="n">len</span><span class="p">);</span>
<span class="cp">#else</span>
<span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">devbuf</span><span class="p">[</span><span class="mi">1600</span><span class="p">];</span>
<span class="w"> </span><span class="cm">/* Copy from src, len corresponds to the length of L2 data, you can</span>
<span class="cm"> * always use this method to receive data. The `&lt;chip&gt;_rxhead_s` is</span>
<span class="cm"> * the driver header before the actual data (maybe you don&#39;t have).</span>
<span class="cm"> */</span>
<span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">receive_data_into</span><span class="p">(</span><span class="n">devbuf</span><span class="p">);</span>
<span class="w"> </span><span class="n">netpkt_copyin</span><span class="p">(</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">pkt</span><span class="p">,</span><span class="w"> </span><span class="n">devbuf</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="o">&lt;</span><span class="n">chip</span><span class="o">&gt;</span><span class="n">_rxhead_s</span><span class="p">),</span><span class="w"> </span><span class="n">len</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="cp">#endif</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">pkt</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="netdev.html" class="btn btn-neutral float-left" title="Network Devices" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="mdio.html" class="btn btn-neutral float-right" title="MDIO Bus Driver" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, The Apache Software Foundation.</p>
</div>
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>