adds deferred processing capability to mnrs network driver

This commit is contained in:
2026-02-08 08:38:04 +01:00
parent 47588180b9
commit 889470ed04
2 changed files with 133 additions and 174 deletions

View File

@@ -1,15 +1,14 @@
/*************************************************************************** /***************************************************************************
* Copyright (c) 2024 Microsoft Corporation * Copyright (c) 2024 Microsoft Corporation
* Copyright (c) 2025-present Eclipse ThreadX Contributors * Copyright (c) 2025-present Eclipse ThreadX Contributors
* *
* This program and the accompanying materials are made available under the * This program and the accompanying materials are made available under the
* terms of the MIT License which is available at * terms of the MIT License which is available at
* https://opensource.org/licenses/MIT. * https://opensource.org/licenses/MIT.
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
**************************************************************************/ **************************************************************************/
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/** */ /** */
@@ -20,11 +19,11 @@
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/* Include necessary system files. */ /* Include necessary system files. */
#include "gen/ethmac.h" #include "gen/ethmac.h"
#include "nx_api.h" #include "nx_api.h"
#include "nx_user.h"
#include "platform.h" #include "platform.h"
#include "tx_port.h" #include "tx_port.h"
#include <string.h> #include <string.h>
@@ -71,14 +70,13 @@ const ULONG mnrs_mac_address_msw = 0x0200;
const ULONG mnrs_mac_address_lsw = 0x00334450; const ULONG mnrs_mac_address_lsw = 0x00334450;
/* Define driver prototypes. */ /* Define driver prototypes. */
VOID _nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr);
VOID _nx_mnrs_network_driver(NX_IP_DRIVER *driver_req_ptr); void _nx_mnrs_network_driver_output(NX_PACKET* packet_ptr, UINT interface_instance_id);
void _nx_mnrs_network_driver_output(NX_PACKET *packet_ptr, UINT interface_instance_id); void _nx_mnrs_network_driver_receive(NX_IP* ip_ptr, NX_PACKET* packet_ptr, UINT interface_instance_id);
void _nx_mnrs_network_driver_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT interface_instance_id); UINT _nx_mnrs_eth_send_packet(NX_PACKET* packet_ptr, volatile ethmac_t* ethmac);
UINT _nx_mnrs_eth_send_packet(NX_PACKET *packet_ptr, volatile ethmac_t* ethmac); VOID _nx_mnrs_eth_recv_packet(UINT i);
VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac); VOID _nx_mnrs_eth_recv_packet_eth0(VOID);
VOID _nx_mnrs_eth_recv_packet_eth0(VOID); VOID _nx_mnrs_eth_recv_packet_eth1(VOID);
VOID _nx_mnrs_eth_recv_packet_eth1(VOID);
#define NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES 3 #define NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES 3
typedef struct MAC_ADDRESS_STRUCT typedef struct MAC_ADDRESS_STRUCT
@@ -87,7 +85,6 @@ typedef struct MAC_ADDRESS_STRUCT
ULONG nx_mac_address_lsw; ULONG nx_mac_address_lsw;
} MAC_ADDRESS; } MAC_ADDRESS;
/* Define an application-specific data structure that holds internal /* Define an application-specific data structure that holds internal
data (such as the state information) of a device driver. data (such as the state information) of a device driver.
@@ -98,26 +95,24 @@ typedef struct _nx_mnrs_network_driver_instance_type
{ {
UINT nx_mnrs_network_driver_in_use; UINT nx_mnrs_network_driver_in_use;
UINT nx_mnrs_network_driver_id; UINT nx_mnrs_network_driver_id;
NX_INTERFACE *nx_mnrs_driver_interface_ptr; NX_INTERFACE* nx_mnrs_driver_interface_ptr;
NX_IP *nx_mnrs_driver_ip_ptr; NX_IP* nx_mnrs_driver_ip_ptr;
MAC_ADDRESS nx_mnrs_driver_mac_address; MAC_ADDRESS nx_mnrs_driver_mac_address;
MAC_ADDRESS nx_mnrs_driver_mcast_address[NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES]; MAC_ADDRESS nx_mnrs_driver_mcast_address[NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES];
volatile ethmac_t* ethmac; volatile ethmac_t* ethmac;
} _nx_mnrs_network_driver_instance_type; } _nx_mnrs_network_driver_instance_type;
/* In this example, there are four instances of the MNRS ETH driver. /* In this example, there are four instances of the MNRS ETH driver.
Therefore an array of four driver instances are created to keep track of Therefore an array of four driver instances are created to keep track of
the interface information of each driver. */ the interface information of each driver. */
static _nx_mnrs_network_driver_instance_type nx_mnrs_driver[NX_MAX_PHYSICAL_INTERFACES]; static _nx_mnrs_network_driver_instance_type nx_mnrs_driver[NX_MAX_PHYSICAL_INTERFACES];
/**************************************************************************/ /**************************************************************************/
/* */ /* */
/* FUNCTION RELEASE */ /* FUNCTION RELEASE */
@@ -178,13 +173,13 @@ VOID _nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr)
UINT interface_index; UINT interface_index;
USHORT ether_type; USHORT ether_type;
#ifndef NX_ENABLE_VLAN #ifndef NX_ENABLE_VLAN
ULONG *ethernet_frame_ptr; ULONG* ethernet_frame_ptr;
#endif /* NX_ENABLE_VLAN */ #endif /* NX_ENABLE_VLAN */
/* Setup the IP pointer from the driver request. */ /* Setup the IP pointer from the driver request. */
ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; ip_ptr = driver_req_ptr->nx_ip_driver_ptr;
/* Default to successful return. */ /* Default to successful return. */
driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; driver_req_ptr->nx_ip_driver_status = NX_SUCCESS;
#ifdef NX_ENABLE_VLAN #ifdef NX_ENABLE_VLAN
/* Let link layer to preprocess the driver request and return actual interface. */ /* Let link layer to preprocess the driver request and return actual interface. */
if (nx_link_driver_request_preprocess(driver_req_ptr, &interface_ptr) != NX_SUCCESS) if (nx_link_driver_request_preprocess(driver_req_ptr, &interface_ptr) != NX_SUCCESS)
@@ -193,23 +188,15 @@ ULONG *ethernet_frame_ptr;
} }
#else #else
/* Setup interface pointer. */ /* Setup interface pointer. */
interface_ptr = driver_req_ptr -> nx_ip_driver_interface; interface_ptr = driver_req_ptr->nx_ip_driver_interface;
#endif /* NX_ENABLE_VLAN */ #endif /* NX_ENABLE_VLAN */
/* Obtain the index number of the network interface. */ /* Obtain the index number of the network interface. */
interface_index = interface_ptr -> nx_interface_index; interface_index = interface_ptr->nx_interface_index;
/* Find out the driver interface if the driver command is not ATTACH. */ /* Find out the driver interface if the driver command is not ATTACH. */
if (driver_req_ptr->nx_ip_driver_command != NX_LINK_INTERFACE_ATTACH) if (driver_req_ptr->nx_ip_driver_command != NX_LINK_INTERFACE_ATTACH)
{ {
for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++) for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
{ {
if (nx_mnrs_driver[i].nx_mnrs_network_driver_in_use == 0)
{
continue;
}
if (nx_mnrs_driver[i].nx_mnrs_driver_ip_ptr != ip_ptr)
{
continue;
}
if (nx_mnrs_driver[i].nx_mnrs_driver_interface_ptr == interface_ptr) if (nx_mnrs_driver[i].nx_mnrs_driver_interface_ptr == interface_ptr)
{ {
break; break;
@@ -221,6 +208,7 @@ ULONG *ethernet_frame_ptr;
return; return;
} }
} }
/* Process according to the driver request type in the IP control /* Process according to the driver request type in the IP control
block. */ block. */
switch (driver_req_ptr->nx_ip_driver_command) switch (driver_req_ptr->nx_ip_driver_command)
@@ -559,26 +547,15 @@ ULONG *ethernet_frame_ptr;
case NX_LINK_GET_INTERFACE_TYPE: case NX_LINK_GET_INTERFACE_TYPE:
{ {
/* Return the link's interface type in the supplied return pointer. Unsupported feature. */ /* Return the link's interface type in the supplied return pointer. Unsupported feature. */
*(driver_req_ptr->nx_ip_driver_return_ptr) = NX_INTERFACE_TYPE_UNKNOWN; *(driver_req_ptr->nx_ip_driver_return_ptr) = NX_INTERFACE_TYPE_ETHERNET;
break; break;
} }
case NX_LINK_DEFERRED_PROCESSING: case NX_LINK_DEFERRED_PROCESSING:
{ {
/* Driver defined deferred processing. This is typically used to defer interrupt /* Driver defined deferred processing. This is typically used to defer interrupt
processing to the thread level. processing to the thread level.
A typical use case of this command is:
On receiving an Ethernet frame, the RX ISR does not process the received frame,
but instead records such an event in its internal data structure, and issues
a notification to the IP stack (the driver sends the notification to the IP
helping thread by calling "_nx_ip_driver_deferred_processing()". When the IP stack
gets a notification of a pending driver deferred process, it calls the
driver with the NX_LINK_DEFERRED_PROCESSING command. The driver shall complete
the pending receive process.
*/ */
_nx_mnrs_eth_recv_packet(i);
/* The MNRS ETH driver doesn't require a deferred process so it breaks out of
the switch case. */
break; break;
} }
case NX_LINK_SET_PHYSICAL_ADDRESS: case NX_LINK_SET_PHYSICAL_ADDRESS:
@@ -686,10 +663,10 @@ void _nx_mnrs_network_driver_output(NX_PACKET* packet_ptr, UINT interface_instan
UINT old_threshold = 0; UINT old_threshold = 0;
#ifdef NX_DEBUG_PACKET #ifdef NX_DEBUG_PACKET
UCHAR *ptr; UCHAR* ptr;
UINT i, j; UINT i, j;
ptr = packet_ptr -> nx_packet_prepend_ptr; ptr = packet_ptr->nx_packet_prepend_ptr;
printf("Ethernet Packet: "); printf("Ethernet Packet: ");
for (j = 0; j < 6; j++) for (j = 0; j < 6; j++)
{ {
@@ -719,9 +696,9 @@ UINT i, j;
/* Disable preemption. */ /* Disable preemption. */
tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold); tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold);
_nx_mnrs_eth_send_packet(packet_ptr, nx_mnrs_driver[interface_instance_id].ethmac); _nx_mnrs_eth_send_packet(packet_ptr, nx_mnrs_driver[interface_instance_id].ethmac);
#ifdef NX_ENABLE_VLAN #ifdef NX_ENABLE_VLAN
/* Release the packet. */ /* Release the packet. */
nx_link_packet_transmitted(nx_mnrs_driver[interface_instance_id].nx_mnrs_driver_ip_ptr, nx_link_packet_transmitted(nx_mnrs_driver[interface_instance_id].nx_mnrs_driver_ip_ptr,
nx_mnrs_driver[interface_instance_id].nx_mnrs_driver_interface_ptr->nx_interface_index, nx_mnrs_driver[interface_instance_id].nx_mnrs_driver_interface_ptr->nx_interface_index,
packet_ptr, packet_ptr,
@@ -729,9 +706,9 @@ UINT i, j;
#else #else
/* Remove the Ethernet header. In real hardware environments, this is typically /* Remove the Ethernet header. In real hardware environments, this is typically
done after a transmit complete interrupt. */ done after a transmit complete interrupt. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE; packet_ptr->nx_packet_prepend_ptr = packet_ptr->nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
/* Adjust the packet length. */ /* Adjust the packet length. */
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE; packet_ptr->nx_packet_length = packet_ptr->nx_packet_length - NX_ETHERNET_SIZE;
/* Now that the Ethernet frame has been removed, release the packet. */ /* Now that the Ethernet frame has been removed, release the packet. */
nx_packet_transmit_release(packet_ptr); nx_packet_transmit_release(packet_ptr);
#endif /* NX_ENABLE_VLAN */ #endif /* NX_ENABLE_VLAN */
@@ -739,7 +716,6 @@ UINT i, j;
tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold); tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
} }
/**************************************************************************/ /**************************************************************************/
/* */ /* */
/* FUNCTION RELEASE */ /* FUNCTION RELEASE */
@@ -819,41 +795,37 @@ void _nx_mnrs_network_driver_receive(NX_IP* ip_ptr, NX_PACKET* packet_ptr, UINT
the first 32-bit word). */ the first 32-bit word). */
/* Clean off the Ethernet header. */ /* Clean off the Ethernet header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE; packet_ptr->nx_packet_prepend_ptr = packet_ptr->nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
/* Adjust the packet length. */ /* Adjust the packet length. */
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE; packet_ptr->nx_packet_length = packet_ptr->nx_packet_length - NX_ETHERNET_SIZE;
/* Route to the ip receive function. */ /* Route to the ip receive function. */
#ifdef NX_DEBUG_PACKET #ifdef NX_DEBUG_PACKET
printf("NetX MNRS ETH Driver IP Packet Receive - %s\n", ip_ptr -> nx_ip_name); printf("NetX MNRS ETH Driver IP Packet Receive - %s\n", ip_ptr->nx_ip_name);
#endif #endif
#ifdef NX_DIRECT_ISR_CALL
_nx_ip_packet_receive(ip_ptr, packet_ptr);
#else
_nx_ip_packet_deferred_receive(ip_ptr, packet_ptr); _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr);
#endif
} }
#ifndef NX_DISABLE_IPV4 #ifndef NX_DISABLE_IPV4
else if (packet_type == NX_ETHERNET_ARP) else if (packet_type == NX_ETHERNET_ARP)
{ {
/* Clean off the Ethernet header. */ /* Clean off the Ethernet header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE; packet_ptr->nx_packet_prepend_ptr = packet_ptr->nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
/* Adjust the packet length. */ /* Adjust the packet length. */
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE; packet_ptr->nx_packet_length = packet_ptr->nx_packet_length - NX_ETHERNET_SIZE;
/* Route to the ARP receive function. */ /* Route to the ARP receive function. */
#ifdef NX_DEBUG #ifdef NX_DEBUG
printf("NetX MNRS ETH Driver ARP Receive - %s\n", ip_ptr -> nx_ip_name); printf("NetX MNRS ETH Driver ARP Receive - %s\n", ip_ptr->nx_ip_name);
#endif #endif
_nx_arp_packet_deferred_receive(ip_ptr, packet_ptr); _nx_arp_packet_deferred_receive(ip_ptr, packet_ptr);
} }
else if (packet_type == NX_ETHERNET_RARP) else if (packet_type == NX_ETHERNET_RARP)
{ {
/* Clean off the Ethernet header. */ /* Clean off the Ethernet header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE; packet_ptr->nx_packet_prepend_ptr = packet_ptr->nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
/* Adjust the packet length. */ /* Adjust the packet length. */
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE; packet_ptr->nx_packet_length = packet_ptr->nx_packet_length - NX_ETHERNET_SIZE;
/* Route to the RARP receive function. */ /* Route to the RARP receive function. */
#ifdef NX_DEBUG #ifdef NX_DEBUG
printf("NetX MNRS ETH Driver RARP Receive - %s\n", ip_ptr -> nx_ip_name); printf("NetX MNRS ETH Driver RARP Receive - %s\n", ip_ptr->nx_ip_name);
#endif #endif
_nx_rarp_packet_deferred_receive(ip_ptr, packet_ptr); _nx_rarp_packet_deferred_receive(ip_ptr, packet_ptr);
} }
@@ -883,60 +855,36 @@ UINT _nx_mnrs_eth_send_packet(NX_PACKET* packet_ptr, volatile ethmac_t* ethmac)
data = packet_ptr->nx_packet_prepend_ptr; data = packet_ptr->nx_packet_prepend_ptr;
size = packet_ptr->nx_packet_length; size = packet_ptr->nx_packet_length;
words = (size + 3) / 4; words = (size + 3) / 4;
/* wait until ethmac is ready to receive packets */
while (get_ethmac_mac_ctrl_tx_ready(ethmac) == 0) while (get_ethmac_mac_ctrl_tx_ready(ethmac) == 0)
; ;
/* write the length of the frame in bits into ethmac fifo*/
set_ethmac_mac_tx(ethmac, size * 8); set_ethmac_mac_tx(ethmac, size * 8);
for (i = 0; i < size; i += 4) /* process buffer in word size and write into ethmac tx fifo*/
for (i = 0; i + 3 < size; i += 4)
{ {
if (i < size - 3) memcpy(&buffer, data + i, 4);
{ while (!get_ethmac_mac_ctrl_tx_ready(ethmac))
memcpy(&buffer, data + i, 4); ;
} set_ethmac_mac_tx(ethmac, buffer);
else }
{ /* process remaining bytes */
memcpy(&buffer, data + i, size - i); if (i < size)
} {
memcpy(&buffer, data + i, size - i);
while (!get_ethmac_mac_ctrl_tx_ready(ethmac)) while (!get_ethmac_mac_ctrl_tx_ready(ethmac))
; ;
set_ethmac_mac_tx(ethmac, buffer); set_ethmac_mac_tx(ethmac, buffer);
} }
return NX_SUCCESS; return NX_SUCCESS;
} }
UINT mac_addr_hit(UINT i, MAC_ADDRESS* mac_addr)
{
UINT mcast_index;
if (nx_mnrs_driver[i].nx_mnrs_driver_mac_address.nx_mac_address_msw == mac_addr->nx_mac_address_msw &&
nx_mnrs_driver[i].nx_mnrs_driver_mac_address.nx_mac_address_lsw == mac_addr->nx_mac_address_lsw)
{
return 1;
}
return 0;
}
UINT mcast_mac_addr_hit_idx(UINT i, MAC_ADDRESS* mac_addr)
{
UINT mcast_index;
for (mcast_index = 0; mcast_index < NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES; mcast_index++)
{
if (nx_mnrs_driver[i].nx_mnrs_driver_mcast_address[mcast_index].nx_mac_address_msw ==
mac_addr->nx_mac_address_msw &&
nx_mnrs_driver[i].nx_mnrs_driver_mcast_address[mcast_index].nx_mac_address_lsw ==
mac_addr->nx_mac_address_lsw)
{
return i;
}
}
return -1;
}
static UCHAR nx_mnrs_receive_buffer[NX_MAX_PACKET_SIZE]; static UCHAR nx_mnrs_receive_buffer[NX_MAX_PACKET_SIZE];
VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac) VOID _nx_mnrs_eth_recv_packet(UINT i)
{ {
UINT bits_received; UINT bits_received;
UINT words_to_read; UINT words_to_read;
UINT i, j; UINT j;
UINT word; UINT word;
UINT status; UINT status;
NX_PACKET* packet_ptr; NX_PACKET* packet_ptr;
@@ -946,96 +894,110 @@ VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac)
UINT address_len; UINT address_len;
UINT packet_type; UINT packet_type;
set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac, 0); /* read the number of bits in the frame and convert it into number of words to read */
bits_received = get_ethmac_mac_rx(ethmac); bits_received = get_ethmac_mac_rx(nx_mnrs_driver[i].ethmac);
words_to_read = (bits_received + 31) / 32; words_to_read = (bits_received + 31) / 32;
if (words_to_read < 4) if (words_to_read < 4)
{ {
for (j = 0; j < words_to_read; j++) for (j = 0; j < words_to_read; j++)
{ {
while (!get_ethmac_mac_ctrl_rx_pending(ethmac)) while (!get_ethmac_mac_ctrl_rx_pending(nx_mnrs_driver[i].ethmac))
; ;
// be carefull of unaligned accesses since data is 2byte aligned // be carefull of unaligned accesses since data is 2byte aligned
word = get_ethmac_mac_rx(ethmac); word = get_ethmac_mac_rx(nx_mnrs_driver[i].ethmac);
memcpy(data + j * sizeof(UINT), &word, sizeof(UINT)); memcpy(data + j * sizeof(UINT), &word, sizeof(UINT));
} }
set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac, 1); set_ethmac_mac_intr_rx_data_avail_intr_enable(nx_mnrs_driver[i].ethmac, 1);
return; return;
} }
// find the diver instance belonging to our ethmac // get the IP diver instance belonging to our ethmac
for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; ++i) ip_ptr = nx_mnrs_driver[i].nx_mnrs_driver_ip_ptr;
status = nx_packet_allocate(ip_ptr->nx_ip_default_packet_pool, &packet_ptr, NX_RECEIVE_PACKET, NX_NO_WAIT);
if (status)
{ {
if (nx_mnrs_driver[i].ethmac == ethmac) packet_ptr = NX_NULL;
data = nx_mnrs_receive_buffer;
}
else if (ip_ptr->nx_ip_default_packet_pool->nx_packet_pool_payload_size >= (NX_LINK_MTU + 2))
{
data = packet_ptr->nx_packet_prepend_ptr + 2;
}
else
{
data = nx_mnrs_receive_buffer;
}
/* now get the remaining bytes from the ethmac peripheral */
for (j = 0; j < words_to_read; j++)
{
while (!get_ethmac_mac_ctrl_rx_pending(nx_mnrs_driver[i].ethmac))
;
// be carefull of unaligned accesses since data is 2byte aligned
word = get_ethmac_mac_rx(nx_mnrs_driver[i].ethmac);
memcpy(data + j * sizeof(UINT), &word, sizeof(UINT));
}
if (packet_ptr == NX_NULL)
{
/* No packet available. Drop it and continue. */
return;
}
/* Make sure IP header is 4-byte aligned. */
packet_ptr->nx_packet_prepend_ptr += 2;
packet_ptr->nx_packet_append_ptr += 2;
if (data == nx_mnrs_receive_buffer)
{
/* Copy data into packet. */
status = nx_packet_data_append(
packet_ptr, (VOID*)data, bytes_received, ip_ptr->nx_ip_default_packet_pool, NX_NO_WAIT);
if (status)
{ {
ip_ptr = nx_mnrs_driver[i].nx_mnrs_driver_ip_ptr; nx_packet_release(packet_ptr);
status = nx_packet_allocate(ip_ptr->nx_ip_default_packet_pool, &packet_ptr, NX_RECEIVE_PACKET, NX_NO_WAIT); return;
if (status)
{
packet_ptr = NX_NULL;
data = nx_mnrs_receive_buffer;
}
else if (ip_ptr->nx_ip_default_packet_pool->nx_packet_pool_payload_size >= (NX_LINK_MTU + 2))
{
data = packet_ptr->nx_packet_prepend_ptr + 2;
}
else
{
data = nx_mnrs_receive_buffer;
}
/* now get the remaining bytes from the ethmac peripheral */
for (j = 0; j < words_to_read; j++)
{
while (!get_ethmac_mac_ctrl_rx_pending(ethmac))
;
// be carefull of unaligned accesses since data is 2byte aligned
word = get_ethmac_mac_rx(ethmac);
memcpy(data + j * sizeof(UINT), &word, sizeof(UINT));
}
if (packet_ptr == NX_NULL)
{
/* No packet available. Drop it and continue. */
return;
}
/* Make sure IP header is 4-byte aligned. */
packet_ptr->nx_packet_prepend_ptr += 2;
packet_ptr->nx_packet_append_ptr += 2;
if (data == nx_mnrs_receive_buffer)
{
/* Copy data into packet. */
status = nx_packet_data_append(
packet_ptr, (VOID*)data, bytes_received, ip_ptr->nx_ip_default_packet_pool, NX_NO_WAIT);
if (status)
{
nx_packet_release(packet_ptr);
return;
}
}
else
{
packet_ptr->nx_packet_length = (ULONG)bytes_received;
packet_ptr->nx_packet_append_ptr += (ULONG)bytes_received;
}
_nx_mnrs_network_driver_receive(ip_ptr, packet_ptr, i);
break;
} }
} }
set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac, 1); else
{
packet_ptr->nx_packet_length = (ULONG)bytes_received;
packet_ptr->nx_packet_append_ptr += (ULONG)bytes_received;
}
_nx_mnrs_network_driver_receive(ip_ptr, packet_ptr, i);
set_ethmac_mac_intr_rx_data_avail_intr_enable(nx_mnrs_driver[i].ethmac, 1);
} }
VOID _nx_mnrs_eth_recv_packet_eth0(VOID) VOID _nx_mnrs_eth_recv_packet_eth0(VOID)
{ {
ULONG old_threshold;
if (get_ethmac_mac_ctrl_rx_pending(ethmac0)) if (get_ethmac_mac_ctrl_rx_pending(ethmac0))
{ {
_nx_mnrs_eth_recv_packet(0, ethmac0); set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac0, 0);
#ifndef NX_DRIVER_DEFERRED_PROCESSING
/* Disable preemption. */
tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold);
_nx_mnrs_eth_recv_packet(0);
/* Restore preemption. */
tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
#else
_nx_ip_driver_deferred_processing(nx_mnrs_driver[0].nx_mnrs_driver_ip_ptr);
#endif
} }
} }
VOID _nx_mnrs_eth_recv_packet_eth1(VOID) VOID _nx_mnrs_eth_recv_packet_eth1(VOID)
{ {
ULONG old_threshold;
if (get_ethmac_mac_ctrl_rx_pending(ethmac1)) if (get_ethmac_mac_ctrl_rx_pending(ethmac1))
{ {
_nx_mnrs_eth_recv_packet(1, ethmac1); set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac1, 0);
#ifndef NX_DRIVER_DEFERRED_PROCESSING
/* Disable preemption. */
tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold);
_nx_mnrs_eth_recv_packet(1);
/* Restore preemption. */
tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
#else
_nx_ip_driver_deferred_processing(nx_mnrs_driver[1].nx_mnrs_driver_ip_ptr);
#endif
} }
} }

View File

@@ -62,7 +62,6 @@
/* Define the base exponent of 2 for huge number. /* Define the base exponent of 2 for huge number.
* Only 16 and 32 are supported. */ * Only 16 and 32 are supported. */
#define NX_CRYPTO_HUGE_NUMBER_BITS 32 #define NX_CRYPTO_HUGE_NUMBER_BITS 32
#define NX_DIRECT_ISR_CALL 1
/* Define various build options for the NetX Duo port. The application should either make changes /* Define various build options for the NetX Duo port. The application should either make changes
here by commenting or un-commenting the conditional compilation defined OR supply the defines here by commenting or un-commenting the conditional compilation defined OR supply the defines
though the compiler's equivalent of the -D option. */ though the compiler's equivalent of the -D option. */
@@ -706,9 +705,7 @@
/* Defined, this option enables deferred driver packet handling. This allows the driver to place a raw /* Defined, this option enables deferred driver packet handling. This allows the driver to place a raw
packet on the IP instance and have the driver's real processing routine called from the NetX internal packet on the IP instance and have the driver's real processing routine called from the NetX internal
IP helper thread. */ IP helper thread. */
/*
#define NX_DRIVER_DEFERRED_PROCESSING #define NX_DRIVER_DEFERRED_PROCESSING
*/
/* Defined, the source address of incoming packet is checked. The default is disabled. */ /* Defined, the source address of incoming packet is checked. The default is disabled. */
/* /*