📄 driver_doc
字号:
================================================
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.
Return the number of packets which could be accepted at this time, zero
implies that the interface is saturated/busy.
static void
HRDWR_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
int total_len, unsigned long key)
=========================================================================
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.
NOTE: All data in/out of the driver is specified via a "scatter-gather"
list. This is just an array of address/length pairs which describe
sections of data to move (in the order given by the array).
Once the data has been successfully sent by the interface (or if an
error occurs), the driver should call 'eth_drv_tx_done()' using the
specified 'key'. Only then will the upper layers release the resources
for that packet and start another transmission.
FUTURE: This function may be extended so that the data need not be
copied by having the function return a "disposition" code (done, send
pending, etc). At this point, you should move the data to some "safe"
location before returning.
static void
HRDWR_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
=========================================================================
This function is actually a call back, only invoked after the
upper-level function
eth_drv_recv(struct eth_drv_sc *sc, int total_len)
has been called. This upper level function is called by the hardware
driver when it knows that a packet of data is available on the
interface. The 'eth_drv_recv()' function then arranges network buffers
and structures for the data and then calls "HRDWR_recv()" to actually
move the data from the interface.
static void
HRDWR_deliver(struct eth_drv_sc *sc)
=========================================================================
This function is actually a call back, and notifies the driver that delivery
is happening. This allows it to actually do the copy of packet data to/from
the hardware from/to the packet buffer. And once that's done, then do things
like unmask its interrupts, and free any relevant resources so it can process
further packets.
In general it will be called from the user thread responsible for delivering
network packets.
static void
HRDWR_poll(struct eth_drv_sc *sc)
=========================================================================
This function is used when in a non-interrupt driven system, e.g. when
interrupts are completely disabled. This allows the driver time to check
whether anything needs doing either for transmission, or to check if
anything has been received, or if any other processing needs doing..
static int
HRDWR_int_vector(struct eth_drv_sc *sc)
=========================================================================
This function returns the interrupt vector number used for RX interrupts.
This is so the common GDB stubs infrastructure can detect when to check
for incoming ctrl-c's when doing debugging over ethernet.
Upper layer functions - called by drivers
=========================================
These functions are defined by the upper layers (machine independent) of
the networking driver support. They are present to hide the interfaces
to the actual networking stack so that the hardware drivers may possibly
be used by any network stack implementation.
These functions require a pointer to a "struct eth_drv_sc" table which
describes the interface at a logical level. It is assumed that the
driver [lowest level hardware support] will keep track of this pointer
so it may be passed "up" as appropriate.
struct eth_drv_sc {
struct eth_drv_funs *funs; // Pointer to hardware functions (see above)
void *driver_private; // Device specific data
const char *dev_name;
struct arpcom sc_arpcom; // ethernet common
};
This structure is created, one per logical interface, via ETH_DRV_SC macro.
void eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr)
===============================================================
This function establishes the device at initialization time. The
hardware should be totally intialized (not "started") when this function
is called.
void eth_drv_tx_done(struct eth_drv_sc *sc, unsigned long key, int status)
==========================================================================
This function is called when a packet completes transmission on the
interface. The 'key' value must be one of the keys provided to
"HRDWR_send()" above. The value 'status' should be non-zero (currently
undefined) to indicate that an error occurred during the transmission.
void eth_drv_recv(struct eth_drv_sc *sc, int len)
=================================================
This function is called to indicate that a packet of length 'len' has
arrived at the interface. The callback "HRDWR_recv()" function
described above will be used to actually unload the data from the
interface into buffers used by the machine independent layers.
Calling graph for Transmit and Receive
--------------------------------------
It may be worth clarifying further the flow of control in the transmit
and receive cases, where the hardware driver does use interrupts and so
DSRs to tell the "foreground" when something asynchronous has occurred.
Transmit:
Foreground task calls into network stack to send a packet (or the
stack decides to send a packet in response to incoming traffic).
The driver calls the HRDWR_can_send() function in the hardware driver.
HRDWR_can_send() returns the number of available "slots" in which it
can store a pending transmit packet.
If it cannot send at this time, the packet is queued outside the
hardware driver for later; in this case, the hardware is already busy
transmitting, so expect an interrupt as described below for completion
of the packet currently outgoing.
If it can send right now, HRDWR_send() is called.
HRDWR_send() copies the data into special hardware buffers, or
instructs the hardware to "send that".
It also remembers the key that is associated with this tx request.
these calls return.
...
Asynchronously, the hardware makes an interrupt to say "transmit is
done"; the ISR quietens the interrupt source in the hardware and
requests that the associated DSR be run.
The DSR realizes that a transmit request has completed, and calls
eth_drv_tx_done() with the same key that it remembered for this tx.
eth_drv_tx_done() uses the key to find the resources associated with
this transmit request; thus the stack knows that the transmit has
completed and its resources can be freed.
eth_drv_tx_done() also enquires whether HRDWR_can_send() now says
"yes, we can send" and if so, dequeues a further transmit request
which may have been queued as described above. If so:
HRDWR_send() copies the data into the hardware buffers, or
instructs the hardware to "send that" and remembers the new key.
these calls return to the DSR and thus to the foreground.
...
Receive:
...
Asynchronously, the hardware makes an interrupt to say "there is ready
data in a receive buffer"; the ISR quietens the interrupt source in
the hardware and requests that the associated DSR be run.
The DSR realizes that there is data ready and calls eth_drv_recv()
with the length of the data that is available.
eth_drv_recv() prepares a set of scatter-gather buffers that can
accommodate that data.
It then calls back into the hardware driver routine HRDWR_recv().
HRDWR_recv() must copy the data from the hardware's buffers into
the scatter-gather buffers provided, and return.
eth_drv_recv() sends the new packet up the network stack and returns.
Back in the DSR now, the driver cleans the receive buffer and returns
it to the hardware's control, available to receive another packet from
the network.
The DSR returns to the foreground.
...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -