Chapter 5 - NetX Network Drivers

This chapter contains a description of network drivers for NetX. The information presented is designed to help developers write application-specific network drivers for Azure RTOS NetX.

Driver Introduction

The NX_IP structure contains everything to manage a single IP instance. This includes general TCP/IP protocol information as well as the application-specific physical network driver's entry routine. The driver's entry routine is defined during the nx_ip_create service. Additional devices may be added to the IP instance via the nx_ip_interface_attach service.

Communication between NetX and the application's network driver is accomplished through the NX_IP_DRIVER request structure. This structure is most often defined locally on the caller's stack and is therefore released after the driver and calling function return. The structure is defined as follows.

typedef struct NX_IP_DRIVER_STRUCT
{
    UINT nx_ip_driver_command;
    UINT nx_ip_driver_status;
    ULONG nx_ip_driver_physical_address_msw;
    ULONG nx_ip_driver_physical_address_lsw;
    NX_PACKET *nx_ip_driver_packet;
    ULONG *nx_ip_driver_return_ptr;
    NX_IP *nx_ip_driver_ptr;
    NX_INTERFACE *nx_ip_driver_interface;
} NX_IP_DRIVER;

Driver Entry

NetX invokes the network driver entry function for driver initialization and for sending packets and for various control and status operations, including initializing and enabling the network device. NetX issues commands to the network driver by setting the nx_ip_driver_command field in the NX_IP_DRIVER request structure. The driver entry function has the following format:

VOID my_driver_entry(NX_IP_DRIVER *request);

Driver Requests

NetX creates the driver request with a specific command and invokes the driver entry function to execute the command. Because each network driver has a single entry function, NetX makes all requests through the driver request data structure. The nx_ip_driver_command member of the driver request data structure (NX_IP_DRIVER) defines the request. Status information is reported back to the caller in the member nx_ip_driver_status. If this field is NX_SUCCESS, the driver request was completed successfully.

NetX serializes all access to the driver. Therefore, the driver does not need to handle multiple threads asynchronously calling the entry function. Note that the device driver function executes with the IP mutex locked. Therefore the device driver internal function shall not block itself.

Typically the device driver also handles interrupts. Therefore, all driver functions need to be interrupt-safe.

Driver Initialization

Although the actual driver initialization processing is application specific, it usually consists of data structure and physical hardware initialization. The information required from NetX for driver initialization is the IP Maximum Transmission Unit (MTU), which is the number of bytes available to the IP-layer payload, including IP header) and if the physical interface needs logical-to-physical mapping. The driver needs

to configure the interface MTU by setting the value in nx_interface_ip_mtu_size in the NX_INTERFACE structure.

The device driver also needs to set up the value in nx_ip_interface_address_mapping_needed in

NX_INTERFACE to inform NetX whether or not interface address mapping is required. If address mapping is needed, the driver is responsible for configuring the interface with valid MAC address, and supply the MAC address to NetX.

When the network driver receives the NX_LINK INITIALIZE request from NetX, it receives a pointer to the IP control block as part of the NX_IP_DRIVER request control block shown above.

After the application calls nx_ip_create, the IP helper thread sends a driver request with the command set to NX_LINK_INITIALIZE to the driver to initialize its physical network interface. The following NX_IP_DRIVER members are used for the initialize request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_INITIALIZE
nx_ip_driver_ptr Pointer to the IP instance. This value should be saved by the driver so that the driver function can find the IP instance to operate on.
nx_ip_driver_interface Pointer to the network interface structure within the IP instance. This information should be saved by the driver. On receiving packets, the driver shall use the interface structure information when sending the packet up the stack.
nx_ip_driver_status Completion status. If the driver is not able to initialize the specified interface to the IP instance, it will return a nonzero error status.

Important

Most of the driver commands are called from the IP helper thread that was created for the IP instance. Therefore the driver routine should avoid performing blocking operations, or the IP helper thread could stall, causing unbounded delays to applications that rely on the IP thread.

Next, the IP helper thread enables the physical network by setting the driver command to NX_LINK_ENABLE in the driver request and sending the request to the network driver. This happens shortly after the IP helper thread completes the initialization request. Enabling the link may be as simple as setting the nx_interface_link_up field in the interface instance. But it may also involve manipulation of the physical hardware. The following NX_IP_DRIVER members are used for the enable link request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_ENABLE
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to enable the specified interface, it will return a non-zero error status.

This request is made by NetX during the deletion of an IP instance by the nx_ip_delete service. Or an application may issue this command in order to temporarily disable the link in order to save power. This service disables the physical network interface on the IP instance. The processing to disable the link may be as simple as clearing the nx_interface_link_up flag in the interface instance. But it may also involve manipulation of the physical hardware. Typically it is a reverse operation of the Enable Link operation. After the link is disabled, the application request Enable Link operation to enable the interface. The following NX_IP_DRIVER members are used for the disable link request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_DISABLE
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to disable the specified interface in the IP instance, it will return a non-zero error status.

This request is made by NetX during the deletion of an IP instance by the nx_ip_delete service. This request uninitialize the interface, and release any resources created during initialization phase. Typically it is a reverse operation of the Initialize Link operation. After the interface is uninitalized, the device cannot be used until the interface is initialized again.

The following NX_IP_DRIVER members are used for the disable link request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_UNINITIALZE
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to uninitialize the specified interface to the IP instance, it will return a non-zero error status.

Packet Send

This request is made during internal IP send processing, processing, which all NetX protocols use to transmit packets (except for ARP, RARP). On receiving the packet send command, the nx_packet_prepend_ptr points to the beginning of the packet to be sent, which is the beginning of the IP header. nx_packet_length indicates the total size (in bytes) of the data being transmitted. If nx_packet_next is valid, the outgoing IP datagram is stored in multiple packets, the driver is required to follow the chained packet and transmit the entire frame. Note that valid data area in each chained packet is stored between nx_packet_prepend_ptr and nx_packet_append_ptr.

The driver is responsible for constructing physical header. If physical address to IP address mapping is required (such as Ethernet), the IP layer already resolved the MAC address. The destination MAC address is passed from the IP instance, stored in nx_ip_driver_physical_address_msw and nx_ip_driver_physical_address_lsw.

After adding the physical header, the packet send processing then calls the driver's output function to transmit the packet.

The following NX_IP_DRIVER members are used for the packet send request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_PACKET_SEND
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_packet Pointer to the packet to send
nx_ip_driver_interface Pointer to the interface instance.
nx_ip_driver_physical_address_msw Most significant 32-bits of physical address (only if physical mapping needed)
nx_ip_driver_physical_address_lsw Least significant 32-bits of physical address (only if physical mapping needed)
nx_ip_driver_status Completion status. If the driver is not able to send the packet, it will return a non-zero error status.

Packet Broadcast

This request is almost identical to the send packet request. The only difference is that the destination physical address fields are set to the Ethernet broadcast MAC address. The following NX_IP_DRIVER members are used for the packet broadcast request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_PACKET_BROADCAST
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_packet Pointer to the packet to end
nx_ip_driver_physical_address_ms w 0x0000FFFF broadcast)
nx_ip_driver_physical_address_lsw 0xFFFFFFFF broadcast)
nx_ip_driver_interface Pointer to the interface instance.
nx_ip_driver_status Completion status. If the driver is not able to send the packet, it will return a non-zero error status.

ARP Send

This request is also similar to the IP packet send request. The only difference is that the Ethernet header specifies an ARP packet instead of an IP packet, and destination physical address fields are set to MAC broadcast address. The following NX_IP_DRIVER members are used for the ARP send request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_ARP_SEND
nx_ip_driver_ptr Pointer to IP instance.
nx_ip_driver_packet Pointer to the packet to send.
nx_ip_driver_physical_address_msw 0x0000FFFF (broadcast)
nx_ip_driver_physical_address_lsw 0xFFFFFFFF (broadcast)
nx_ip_driver_interface Pointer to the interface instance.
nx_ip_driver_status Completion status. If the driver is not able to send the ARP packet, it will return a non-zero error status.

If physical mapping is not needed, implementation of this request is not required.

ARP Response Send

This request is almost identical to the ARP send packet request. The only difference is the destination physical address fields are passed from the IP instance. The following NX_IP_DRIVER members are used for the ARP response send request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_ARP_RESPONSE_SEND
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_packet Pointer to the packet to send
nx_ip_driver_physical_address_msw Most significant 32-bits of physical address
nx_ip_driver_physical_address_lsw Least significant 32-bits of physical address
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to send the ARP packet, it will return a non-zero error status.

Note

If physical mapping is not needed, implementation of this request is not required.

RARP Send

This request is almost identical to the ARP send packet request. The only differences are the type of packet header and the physical address fields are not required because the physical destination is always a broadcast address.

The following NX_IP_DRIVER members are used for the RARP send request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_RARP_SEND
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_packet Pointer to the packet to send
nx_ip_driver_physical_address_msw 0x0000FFFF (broadcast)
nx_ip_driver_physical_address_lsw 0xFFFFFFFF (broadcast)
NX_IP_DRIVER member Meaning
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to send the RARP packet, it will return a non-zero error status.

Note

Applications that require RARP service must implement this command.

Multicast Group Join

This request is made with the nx_igmp_multicast_interface join service. The network driver takes the supplied multicast group address and sets up the physical media to accept incoming packets from that multicast group address. Note that for drivers that don't support multicast filter, the driver receive logic may have to be in promiscuous mode. In this case, the driver may need to filter incoming frames based on destination MAC address, thus reducing the amount of traffic passed into the IP instance. The following NX_IP_DRIVER members are used for the multicast group join request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_MULTICAST_JOIN
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_physical_address_msw Most significant 32-bits of physical multicast address
nx_ip_driver_physical_address_lsw Least significant 32-bits of physical multicast address
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to join the multicast group, it will return a non-zero error status.

Multicast Group Leave

This request is invoked by explicitly calling the nx_igmp_multicast_leave service. The driver removes the supplied Ethernet multicast address from the multicast list. After a host has left a multicast group, packets on the network with this Ethernet multicast address are no longer received by this IP instance. The following NX_IP_DRIVER members are used for the multicast group leave request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_MULTICAST_LEAVE
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_physical_address_msw Most significant 32 bits of physical multicast ddress
nx_ip_driver_physical_address_lsw Least significant 32 bits of physical multicast address
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to leave the multicast group, it will return a non-zero error status.

Attach Interface

This request is invoked from the NetX to the device driver, allowing the driver to associate the driver instance with the corresponding IP instance and the physical interface instance within the IP. The following NX_IP_DRIVER members are used for the attach interface request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command X_LINK_INTERFACE_ATTACH
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_interface Pointer to the interface instance.
nx_ip_driver_status Completion status. If the driver is not able to detach the specified interface to the IP instance, it will return a non-zero error status.

Detach Interface

This request is invoked by NetX to the device driver, allowing the driver to disassociate the driver instance with the corresponding IP instance and the physical interface instance within the IP. The following NX_IP_DRIVER members are used for the attach interface request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_INTERFACE_DETACH
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_interface Pointer to the interface instance.
nx_ip_driver_status Completion status. If the driver is not able to attach the specified interface to the IP instance, it will return a non-zero error status.

The application can query the network interface link status using the NetX service nx_ip_interface_status_check service for any interface on the host. See Chapter 4, "Description of NetX Services" on page 107, for more details on these services.

The link status is contained in the nx_interface_link_up field in the NX_INTERFACE structure pointed to by nx_ip_driver_interface pointer. The following NX_IP_DRIVER members are used for the link status request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_GET_STATUS
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_return_ptr Pointer to the destination to place the status.
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to get specific status, it will return a non-zero error status.

Note

nx_ip_status_check is still available for checking the status of the primary interface. However, application developers are encouraged to use the interface-specific service nx_ip_interface_status_check.

This request is made from within the nx_ip_driver_direct_command service. The driver stores the link's line speed in the supplied destination. The following NX_IP_DRIVER members are used for the link line speed request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_GET_SPEED
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_return_ptr Pointer to the destination to place the line speed
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to get speed information, it will return a non-zero error status.

Note

This request is not used internally by NetX so its implementation is optional.

Get Duplex Type

This request is made from within the nx_ip_driver_direct_command service. The driver stores the link's duplex type in the supplied destination. The following NX_IP_DRIVER members are used for the duplex type request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_GET_DUPLEX_TYPE
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_return_ptr Pointer to the destination to place the duplex type
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to get duplex information, it will return a nonzero error status.

Note

This request is not used internally by NetX so its implementation is optional.

Get Error Count

This request is made from within the nx_ip_driver_direct_command service. The driver stores the link's error count in the supplied destination. To support this feature, the driver needs to track operation errors. The following NX_IP_DRIVER members are used for the link error count request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_GET_ERROR_COUNT
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_return_ptr Pointer to the destination to place the error count
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to get error count, it will return a non-zero error status.

Note

This request is not used internally by NetX so its implementation is optional.

Get Receive Packet Count

This request is made from within the nx_ip_driver_direct_command service. The driver stores the link's receive packet count in the supplied destination. To support this feature, the driver needs to keep track of the number of packets received. The following NX_IP_DRIVER members are used for the link receive packet count request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_GET_RX_COUNT
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_return_ptr Pointer to the destination to place the receive packet count
nx_ip_driver_interface Pointer to the physical network interface
nx_ip_driver_status Completion status. If the driver is not able to get receive count, it will return a non-zero error status.

Note

This request is not used internally by NetX so its implementation is optional.

Get Transmit Packet Count

This request is made from within the nx_ip_driver_direct_command service. The driver stores the link's transmit packet count in the supplied destination. To support this feature, the driver needs to keep track of each packet it transmits on each interface. The following NX_IP_DRIVER members are used for the link transmit packet count request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_GET_TX_COUNT
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_return_ptr Pointer to the destination to place the transmit packet count
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to get transmit count, it will return a non-zero error status.

Note

This request is not used internally by NetX so its implementation is optional.

Get Allocation Errors

This request is made from within the nx_ip_driver_direct_command service. The driver stores the link's packet pool allocation error count in the supplied destination. The following NX_IP_DRIVER members are used for the link allocation error count request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_GET_ALLOC_ERRORS
nx_ip_driver_ptr Pointer to IP instance
NX_IP_DRIVER member Meaning
nx_ip_driver_return_ptr Pointer to the destination to place the allocation error count
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to get allocation errors, it will return a non-zero error status.

This request is not used internally by NetX so its implementation is optional.

Driver Deferred Processing

This request is made from the IP helper thread in response to the driver calling the _nx_ip_driver_deferred_processing routine from a transmit or receive ISR. This allows the driver ISR to defer the packet receive and transmit processing to the IP helper thread and thus reduce the amount to process in the ISR. The nx_interface_additional_link_info field in the NX_INTERFACE structure pointed to by nx_ip_driver_interface may be used by the driver to store information about the deferred processing event from the IP helper thread context. The following NX_IP_DRIVER members are used for the deferred processing event.

NX_IP_DRIVER

member Meaning
nx_ip_driver_command NX_LINK_DEFERRED_PROCESSING
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_interface Pointer to the interface instance

User Commands

This request is made from within the nx_ip_driver_direct_command service. The driver processes the application specific user commands. The following NX_IP_DRIVER members are used for the user command request.

NX_IP_DRIVER member Meaning
nx_ip_driver_command NX_LINK_USER_COMMAND
nx_ip_driver_ptr Pointer to IP instance
nx_ip_driver_return_ptr User defined
nx_ip_driver_interface Pointer to the interface instance
nx_ip_driver_status Completion status. If the driver is not able to execute user commands, it will return a non-zero error status.

This request is not used internally by NetX so its implementation is optional.

Unimplemented Commands

Commands unimplemented by the network driver must have the return status field set to NX_UNHANDLED_COMMAND.

Driver Output

All previously mentioned packet transmit requests require an output function implemented in the driver. Specific transmit logic is hardware specific, but it usually consists of checking for hardware capacity to send the packet immediately. If possible, the packet payload (and additional payloads in the packet chain) are loaded into one or more of the hardware transmit buffers and a transmit operation is initiated. If the packet won't fit in the available transmit buffers, the packet should be queued, and be transmitted when the transmission buffers become available.

The recommended transmit queue is a singly-linked list, having both head and tail pointers. New packets are added to the end of the queue, keeping the oldest packet at the front. The nx_packet_queue_next field is used as the packet's next link in the queue. The driver defines the head and tail pointers of transmit queue.

Because this queue is accessed from thread and interrupt portions of the driver, interrupt protection must be placed around the queue manipulations.

Most physical hardware implementations generate an interrupt upon packet transmit completion. When the driver receives such an interrupt, it typically releases the resources associated with the packet just being transmitted. In case the transmit logic reads data directly from the NX_PACKET buffer, the driver should use the nx_packet_transmit_release service to release the packet associated with the transmit complete interrupt back to the available packet pool. Next, the driver examines the transmit queue for additional packets waiting to be sent. As many of the queued transmit packets that fit into the hardware transmit buffer(s) are de-queued and loaded into the buffers. This is followed by initiation of another send operation.

As soon as the data in the NX_PACKET has been moved into the transmitter FIFO (or in case a driver supports zerocopy operation, the data in NX_PACKET has been transmitted), the driver must move the nx_packet_prepend_ptr to the beginning of the IP header before calling nx_packet_transmit_release. Remember to adjust nx_packet_length field accordingly. If an IP frame is made up of multiple packets, only the head of the packet chain needs to be released.

Driver Input

Upon reception of a received packet interrupt, the network driver retrieves the packet from the physical hardware receive buffers and builds a valid NetX packet. Building a valid NetX packet involves setting up the appropriate length field and chaining together multiple packets if the incoming packet's size is greater than a single packet payload. Once properly built, the prepend_ptr is moved after the physical layer header and the receive packet is dispatched to NetX.

NetX assumes that the IP and ARP headers are aligned on a ULONG boundary. The NetX driver must, therefore, ensure this alignment. In Ethernet environments this is done by starting the Ethernet header two bytes from the beginning of the packet. When the nx_packet_prepend_ptr is moved beyond the Ethernet header, the underlying IP or ARP header is 4byte aligned.

There are several receive packet functions available in NetX. If the received packet is an ARP packet, _nx_arp_packet_deferred_receive is called. If the received packet is an RARP packet, _nx_rarp_packet_deferred_receive is called. There are several options for handling incoming IP packets. For the fastest handling of IP packets, _nx_ip_packet_receive is called. This approach has the least overhead, but requires more processing in the driver's receive interrupt service handler (ISR). For minimal ISR processing _nx_ip_packet_deferred_receive is called.

After the new receive packet is properly built, the physical hardware's receive buffers are setup to receive more data. This might require allocating NetX packets and placing the payload address in the hardware receive buffer or it may simply amount to changing a setting in the hardware receive buffer. To minimize overrun possibilities, it is important that the hardware's receive buffers have available buffers as soon as possible after a packet is received.

The initial receive buffers are setup during driver initialization.

Deferred Receive Packet Handling

The driver may defer receive packet processing to the NetX IP helper thread. For some applications this may be necessary to minimize ISR processing as well as dropped packets. To use deferred packet handling, the NetX library must first becompiled with NX_DRIVER_DEFERRED_PROCESSING defined. This adds the deferred packet logic to the NetX IP helper thread. Next, on receiving a data packet, the driver must call _nx_ip_packet_deferred_receive():

_nx_ip_packet_deferred_receive(ip_ptr, packet_ptr);

The deferred receive function places the receive packet represented by packet_ptr on a FIFO (linked list) and notifies the IP helper thread. After executing, the IP helper repetitively calls the deferred handling function to process each deferred packet. The deferred handler processing typically includes removing the packet's physical layer header (usually Ethernet) and dispatching it to one of these NetX receive functions:

_nx_ip_packet_deferred_receive
_nx_arp_packet_deferred_receive
_nx_rarp_packet_deferred_receive

Example RAM Ethernet Network Driver

The NetX demonstration system is delivered with a small RAM-based network driver, defined in the file nx_ram_network_driver.c. This driver assumes the IP instances are all on the same network and simply assigns virtual hardware addresses (MAC addresses) to each device instance as they are created. This file provides a good example of the basic structure of NetX physical network drivers. Users may develop their own network drivers using the driver framework presented in this example.

The entry function of the network driver is _nx_ram_network_driver, which is passed to the IP instance create call. Entry functions for additional network interfaces can be passed into the nx_ip_interface_attach service. After the IP instance starts to run, the driver entry function is invoked to initialize and enable the device (refer to the case NX_LINK_INITIALIZE and NX_LINK_ENABLE). After the NX_LINK_ENABLE command is issued, the device should be ready to transmit and receive packets.

The IP instance transmits network packets via one of these commands:

NX_LINK_PACKET_SEND An IP packet is being transmitted,
NX_LINK_ARP_SEND An ARP request or ARP response packet is being transmitted,
NX_LINK_ARP_RARP_SEND A Reverse ARP request or response packet is being transmitted,

On processing these commands, the network driver needs to prepend the appropriate Ethernet frame header, and then send it to the underlying hardware for transmission. During the transmission process, the network driver has the exclusive ownership of the packet buffer area. Therefore once the data are being transmitted (or once the data has been copied into the driver internal transfer buffer), the network driver is responsible for releasing the packet buffer by first moving the prepend pointer past the Ethernet header to the IP header (and adjust packet length accordingly), and then by calling the nx_packet_transmit_release service to release the packet. Not releasing the packet after data transmission will cause packets to leak.

The network device driver is also responsible for handling incoming data packets. In the RAM driver example, the received packet is processed by the function _nx_ram_network_driver_receive.

Once the device receives an Ethernet frame, the driver is responsible for storing the data in

NX_PACKET structure. Note that NetX assumes the IP header starts from 4-byte aligned address. Since the length of Ethernet header is 14-byte, the driver needs to store the starting of the Ethernet header at 2-byte aligned address to guarantee that the IP header starts at 4-byte aligned address.