⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ethdrv.sgml

📁 开放源码实时操作系统源码.
💻 SGML
📖 第 1 页 / 共 3 页
字号:
</para>
<para>
In many packages it is possible for the
<acronym>ESA</acronym>
to be set from RedBoot,
(perhaps from 'fconfig' data), hard-coded from
<acronym>CDL</acronym>, or from an <acronym>EPROM</acronym>.
A driver should choose a run-time specified
<acronym>ESA</acronym>
(e.g. from RedBoot)
preferentially, otherwise (in order) it should use a <acronym>CDL</acronym> specified
<acronym>ESA</acronym>
if one has been set, otherwise an <acronym>EPROM</acronym> set
<acronym>ESA</acronym>, or otherwise
fail. See the <filename>cl/cs8900a</filename>
ethernet driver for an example.
</para></note>
</sect2>
<sect2 id="io-eth-drv-api-start">
<title>Start function</title>
<para>
<programlisting>
static void
<replaceable>HRDWR</replaceable>_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
</programlisting>
This function is called, perhaps much later than system initialization
time, when the system (an application) is ready for the interface to
become active.  The purpose of this function is to set up the hardware
interface to start accepting packets from the network and be able to
send packets out.  The receiver hardware should not be enabled prior to
this call.
</para><note><para>This function will be called whenever the
up/down state of the logical interface changes, e.g. when the IP address
changes, or when promiscuous mode is selected by means of an
<function>ioctl()</function> call in the application.
This may occur more than once, so this function needs to
be prepared for that case.
</para></note><note><para>
In future, the <parameter>flags</parameter>
field (currently unused) may be used to tell the
function how to start up, e.g. whether interrupts will be used,
alternate means of selecting promiscuous mode etc.
</para></note>
</sect2>
<sect2 id="io-eth-drv-api-stop">
<title>Stop function</title>
<para>
<programlisting>
static void <replaceable>HRDWR</replaceable>_stop(struct eth_drv_sc *sc)
</programlisting>
This function is the inverse of &ldquo;start.&rdquo;
It should shut down the hardware, disable the receiver, and keep it from
interacting with the physical network.
</para>
</sect2>
<sect2 id="io-eth-drv-api-control">
<title>Control function</title>
<para>
<programlisting>
static int
<replaceable>HRDWR</replaceable>_control(
	struct eth_drv_sc *sc, unsigned long key,
	void *data, int len)
</programlisting>
This function is used to perform low-level &ldquo;control&rdquo;
operations on the
interface.  These operations would typically be initiated via
<function>ioctl()</function> calls in the BSD
stack, and would be anything that might require the hardware setup to
change (i.e. cannot be performed totally by the
platform-independent layers).
</para><para>
The <parameter>key</parameter> parameter selects the operation, and the
<parameter>data</parameter> and <parameter>len</parameter> params point describe,
as required, some data for the operation in question.
</para>
<variablelist><title>Available Operations:</title>
<varlistentry><term>ETH_DRV_SET_MAC_ADDRESS</term>
<listitem><para>
This operation sets the ethernet station address (ESA or MAC) for the
device.  Normally this address is kept in non-volatile memory and is
unique in the world.  This function must at least set the interface to
use the new address.  It may also update the NVM as appropriate.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ETH_DRV_GET_IF_STATS_UD</term>
<term>ETH_DRV_GET_IF_STATS</term>
<listitem><para>
These acquire a set of statistical counters from the interface, and write
the information into the memory pointed to by <parameter>data</parameter>.
The &ldquo;UD&rdquo; variant explicitly instructs the driver to acquire
up-to-date values.  This is a separate option because doing so may take
some time, depending on the hardware.
</para><para>
The definition of the data structure is in
<filename>cyg/io/eth/eth_drv_stats.h</filename>.
</para><para>
This call is typically made by SNMP, see <xref linkend=net-snmp-ecos-port>.
</para>
</listitem>
</varlistentry>
<varlistentry><term>ETH_DRV_SET_MC_LIST</term>
<listitem><para>
This entry instructs the device to set up multicast packet filtering
to receive only packets addressed to the multicast ESAs in the list pointed
to by <parameter>data</parameter>.
</para><para>
The format of the data is a 32-bit count of the ESAs in the list, followed
by packed bytes which are the ESAs themselves, thus:
<programlisting>
#define ETH_DRV_MAX_MC 8
struct eth_drv_mc_list {
    int len;
    unsigned char addrs[ETH_DRV_MAX_MC][ETHER_ADDR_LEN];
};
</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry><term>ETH_DRV_SET_MC_ALL</term>
<listitem><para>
This entry instructs the device to receive all multicast packets, and
delete any explicit filtering which had been set up.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
This function should return zero if the specified operation was
completed successfully.  It should return non-zero if the operation
could not be performed, for any reason.
</para>
</sect2>
<sect2 id="io-eth-drv-api-can-send">
<title>Can-send function</title>
<para>
<programlisting>
static int <replaceable>HRDWR</replaceable>_can_send(struct eth_drv_sc *sc)
</programlisting>
This function is called to determine if it is possible to start the
transmission of a packet on the interface.  Some interfaces will allow
multiple packets to be "queued" and this function allows for the highest
possible utilization of that mode.
</para><para>
Return the number of packets which could be accepted at this time, zero
implies that the interface is saturated/busy.
</para>
</sect2>
<sect2 id="io-eth-drv-api-send">
<title>Send function</title>
<para>
<programlisting>
struct eth_drv_sg {
    CYG_ADDRESS  buf;
    CYG_ADDRWORD len;
};

static void
<replaceable>HRDWR</replaceable>_send(
	struct eth_drv_sc *sc,
	struct eth_drv_sg *sg_list, int sg_len,
        int total_len, unsigned long key)
</programlisting>
This function is used to send a packet of data to the network.  It is
the responsibility of this function to somehow hand the data over to the
hardware interface.  This will most likely require copying, but just the
address/length values could be used by smart hardware.
</para><note><para>
All data in/out of the driver is specified via a
&ldquo;scatter-gather&rdquo;
list.  This is just an array of address/length pairs which describe
sections of data to move (in the order given by the array), as in the
<type>struct eth_drv_sg</type> defined above and pointed to by
<parameter>sg_list</parameter>.
</para></note><para>
Once the data has been successfully sent by the interface (or if an
error occurs), the driver should call
<function>(sc->funs->eth_drv->tx_done)()</function>
(see <xref linkend=io-eth-drv-tx-done>)
using the specified <parameter>key</parameter>.
Only then will the upper layers release the resources
for that packet and start another transmission.
</para><note><para>
In future, this function may be extended so that the data need not be
copied by having the function return a &ldquo;disposition&rdquo; code
(done, send pending, etc).  At this point, you should move the data to some
&ldquo;safe&rdquo; location before returning.
</para></note>
</sect2>
<sect2 id="io-eth-drv-api-deliver">
<title>Deliver function</title>
<para>
<programlisting>
static void
<replaceable>HRDWR</replaceable>_deliver(struct eth_drv_sc *sc)
</programlisting>
This function is called from the &ldquo;Network Delivery Thread&rdquo; in
order to let the device driver do the time-consuming work associated with
receiving a packet &mdash; usually copying the entire packet from the
hardware or a special memory location into the network stack's memory.
</para><para>
After handling any outstanding incoming packets or pending transmission
status, it can unmask the device's interrupts, and free any relevant
resources so it can process further packets.
</para><para>
It will be called when the interrupt handler for the network device
has called
<programlisting>
    eth_drv_dsr( vector, count, (cyg_addrword_t)sc );
</programlisting>
to alert the system that &ldquo;something requires attention.&rdquo;
This <function>eth_drv_dsr()</function> call must occur from within the
interrupt handler's DSR (not the ISR) or actually <emphasis>be</emphasis>
the DSR, whenever it is determined that
the device needs attention from the foreground.  The third parameter
(<parameter>data</parameter> in the prototype of
<function>eth_drv_dsr()</function> <emphasis>must</emphasis>
be a valid <type>struct eth_drv_sc</type> pointer <varname>sc</varname>.
</para><para>
The reason for this slightly convoluted train of events is to keep the DSR
(and ISR) execution time as short as possible, so that other activities of
higher priority than network servicing are not denied the CPU by network
traffic.
</para><para>
To deliver a newly-received packet into the network stack, the deliver
routine must call
<programlisting>
(sc->funs->eth_drv->recv)(sc, len);
</programlisting>
which will in turn call the receive function, which we talk about next.
See also <xref linkend=io-eth-drv-upper-recv> below.
</para>
</sect2>
<sect2 id="io-eth-drv-api-recv">
<title>Receive function</title>
<para>
<programlisting>
static void
<replaceable>HRDWR</replaceable>_recv(
	struct eth_drv_sc *sc,
	struct eth_drv_sg *sg_list, int sg_len)
</programlisting>
This function is a call back, only invoked after the
upper-level function
<programlisting>
(sc->funs->eth_drv->recv)(struct eth_drv_sc *sc, int total_len)
</programlisting>
has been called itself from your deliver function when it knows that a
packet of data is available on the
interface.  The <function>(sc->funs->eth_drv->recv)()</function>
function then arranges network buffers
and structures for the data and then calls
<function><replaceable>HRDWR</replaceable>_recv()</function> to actually
move the data from the interface.
</para><para>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -