|
|
|
|
@@ -9,7 +9,6 @@
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************/
|
|
|
|
|
/**************************************************************************/
|
|
|
|
|
/** */
|
|
|
|
|
@@ -20,11 +19,11 @@
|
|
|
|
|
/**************************************************************************/
|
|
|
|
|
/**************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Include necessary system files. */
|
|
|
|
|
|
|
|
|
|
#include "gen/ethmac.h"
|
|
|
|
|
#include "nx_api.h"
|
|
|
|
|
#include "nx_user.h"
|
|
|
|
|
#include "platform.h"
|
|
|
|
|
#include "tx_port.h"
|
|
|
|
|
#include <string.h>
|
|
|
|
|
@@ -71,14 +70,13 @@ const ULONG mnrs_mac_address_msw = 0x0200;
|
|
|
|
|
const ULONG mnrs_mac_address_lsw = 0x00334450;
|
|
|
|
|
|
|
|
|
|
/* Define driver prototypes. */
|
|
|
|
|
|
|
|
|
|
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_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);
|
|
|
|
|
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_eth1(VOID);
|
|
|
|
|
VOID nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr);
|
|
|
|
|
static void _nx_mnrs_network_driver_output(NX_PACKET* packet_ptr, UINT interface_instance_id);
|
|
|
|
|
static void _nx_mnrs_network_driver_receive(NX_IP* ip_ptr, NX_PACKET* packet_ptr, UINT interface_instance_id);
|
|
|
|
|
static UINT _nx_mnrs_eth_send_packet(NX_PACKET* packet_ptr, volatile ethmac_t* ethmac);
|
|
|
|
|
static VOID _nx_mnrs_eth_recv_packet(UINT i);
|
|
|
|
|
static VOID _nx_mnrs_eth_recv_packet_eth0(VOID);
|
|
|
|
|
static VOID _nx_mnrs_eth_recv_packet_eth1(VOID);
|
|
|
|
|
|
|
|
|
|
#define NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES 3
|
|
|
|
|
typedef struct MAC_ADDRESS_STRUCT
|
|
|
|
|
@@ -87,7 +85,6 @@ typedef struct MAC_ADDRESS_STRUCT
|
|
|
|
|
ULONG nx_mac_address_lsw;
|
|
|
|
|
} MAC_ADDRESS;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Define an application-specific data structure that holds internal
|
|
|
|
|
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_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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
the interface information of each driver. */
|
|
|
|
|
static _nx_mnrs_network_driver_instance_type nx_mnrs_driver[NX_MAX_PHYSICAL_INTERFACES];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************/
|
|
|
|
|
/* */
|
|
|
|
|
/* FUNCTION RELEASE */
|
|
|
|
|
@@ -169,7 +164,7 @@ static _nx_mnrs_network_driver_instance_type nx_mnrs_driver[NX_MAX_PHYSICAL_INTE
|
|
|
|
|
/* resulting in version 6.4.0 */
|
|
|
|
|
/* */
|
|
|
|
|
/**************************************************************************/
|
|
|
|
|
VOID _nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr)
|
|
|
|
|
VOID nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr)
|
|
|
|
|
{
|
|
|
|
|
UINT i = 0;
|
|
|
|
|
NX_IP* ip_ptr;
|
|
|
|
|
@@ -178,13 +173,13 @@ VOID _nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr)
|
|
|
|
|
UINT interface_index;
|
|
|
|
|
USHORT ether_type;
|
|
|
|
|
#ifndef NX_ENABLE_VLAN
|
|
|
|
|
ULONG *ethernet_frame_ptr;
|
|
|
|
|
ULONG* ethernet_frame_ptr;
|
|
|
|
|
#endif /* NX_ENABLE_VLAN */
|
|
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
|
driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS;
|
|
|
|
|
driver_req_ptr->nx_ip_driver_status = NX_SUCCESS;
|
|
|
|
|
#ifdef NX_ENABLE_VLAN
|
|
|
|
|
/* 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)
|
|
|
|
|
@@ -193,23 +188,15 @@ ULONG *ethernet_frame_ptr;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
/* 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 */
|
|
|
|
|
/* 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. */
|
|
|
|
|
if (driver_req_ptr->nx_ip_driver_command != NX_LINK_INTERFACE_ATTACH)
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
@@ -221,6 +208,7 @@ ULONG *ethernet_frame_ptr;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Process according to the driver request type in the IP control
|
|
|
|
|
block. */
|
|
|
|
|
switch (driver_req_ptr->nx_ip_driver_command)
|
|
|
|
|
@@ -559,26 +547,15 @@ ULONG *ethernet_frame_ptr;
|
|
|
|
|
case NX_LINK_GET_INTERFACE_TYPE:
|
|
|
|
|
{
|
|
|
|
|
/* 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;
|
|
|
|
|
}
|
|
|
|
|
case NX_LINK_DEFERRED_PROCESSING:
|
|
|
|
|
{
|
|
|
|
|
/* Driver defined deferred processing. This is typically used to defer interrupt
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* The MNRS ETH driver doesn't require a deferred process so it breaks out of
|
|
|
|
|
the switch case. */
|
|
|
|
|
_nx_mnrs_eth_recv_packet(i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
#ifdef NX_DEBUG_PACKET
|
|
|
|
|
UCHAR *ptr;
|
|
|
|
|
UINT i, j;
|
|
|
|
|
UCHAR* ptr;
|
|
|
|
|
UINT i, j;
|
|
|
|
|
|
|
|
|
|
ptr = packet_ptr -> nx_packet_prepend_ptr;
|
|
|
|
|
ptr = packet_ptr->nx_packet_prepend_ptr;
|
|
|
|
|
printf("Ethernet Packet: ");
|
|
|
|
|
for (j = 0; j < 6; j++)
|
|
|
|
|
{
|
|
|
|
|
@@ -719,7 +696,7 @@ UINT i, j;
|
|
|
|
|
|
|
|
|
|
/* Disable preemption. */
|
|
|
|
|
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
|
|
|
|
|
/* Release the packet. */
|
|
|
|
|
nx_link_packet_transmitted(nx_mnrs_driver[interface_instance_id].nx_mnrs_driver_ip_ptr,
|
|
|
|
|
@@ -729,9 +706,9 @@ UINT i, j;
|
|
|
|
|
#else
|
|
|
|
|
/* Remove the Ethernet header. In real hardware environments, this is typically
|
|
|
|
|
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. */
|
|
|
|
|
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. */
|
|
|
|
|
nx_packet_transmit_release(packet_ptr);
|
|
|
|
|
#endif /* NX_ENABLE_VLAN */
|
|
|
|
|
@@ -739,7 +716,6 @@ UINT i, j;
|
|
|
|
|
tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************/
|
|
|
|
|
/* */
|
|
|
|
|
/* 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). */
|
|
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
|
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. */
|
|
|
|
|
#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
|
|
|
|
|
#ifdef NX_DIRECT_ISR_CALL
|
|
|
|
|
_nx_ip_packet_receive(ip_ptr, packet_ptr);
|
|
|
|
|
#else
|
|
|
|
|
_nx_ip_packet_deferred_receive(ip_ptr, packet_ptr);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#ifndef NX_DISABLE_IPV4
|
|
|
|
|
else if (packet_type == NX_ETHERNET_ARP)
|
|
|
|
|
{
|
|
|
|
|
/* 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. */
|
|
|
|
|
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. */
|
|
|
|
|
#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
|
|
|
|
|
_nx_arp_packet_deferred_receive(ip_ptr, packet_ptr);
|
|
|
|
|
}
|
|
|
|
|
else if (packet_type == NX_ETHERNET_RARP)
|
|
|
|
|
{
|
|
|
|
|
/* 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. */
|
|
|
|
|
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. */
|
|
|
|
|
#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
|
|
|
|
|
_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;
|
|
|
|
|
size = packet_ptr->nx_packet_length;
|
|
|
|
|
words = (size + 3) / 4;
|
|
|
|
|
/* wait until ethmac is ready to receive packets */
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
memcpy(&buffer, data + i, size - i);
|
|
|
|
|
}
|
|
|
|
|
memcpy(&buffer, data + i, 4);
|
|
|
|
|
while (!get_ethmac_mac_ctrl_tx_ready(ethmac))
|
|
|
|
|
;
|
|
|
|
|
set_ethmac_mac_tx(ethmac, buffer);
|
|
|
|
|
}
|
|
|
|
|
/* process remaining bytes */
|
|
|
|
|
if (i < size)
|
|
|
|
|
{
|
|
|
|
|
memcpy(&buffer, data + i, size - i);
|
|
|
|
|
while (!get_ethmac_mac_ctrl_tx_ready(ethmac))
|
|
|
|
|
;
|
|
|
|
|
set_ethmac_mac_tx(ethmac, buffer);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
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];
|
|
|
|
|
VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac)
|
|
|
|
|
VOID _nx_mnrs_eth_recv_packet(UINT i)
|
|
|
|
|
{
|
|
|
|
|
UINT bits_received;
|
|
|
|
|
UINT words_to_read;
|
|
|
|
|
UINT i, j;
|
|
|
|
|
UINT j;
|
|
|
|
|
UINT word;
|
|
|
|
|
UINT status;
|
|
|
|
|
NX_PACKET* packet_ptr;
|
|
|
|
|
@@ -946,96 +894,110 @@ VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac)
|
|
|
|
|
UINT address_len;
|
|
|
|
|
UINT packet_type;
|
|
|
|
|
|
|
|
|
|
set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac, 0);
|
|
|
|
|
bits_received = get_ethmac_mac_rx(ethmac);
|
|
|
|
|
/* read the number of bits in the frame and convert it into number of words to read */
|
|
|
|
|
bits_received = get_ethmac_mac_rx(nx_mnrs_driver[i].ethmac);
|
|
|
|
|
words_to_read = (bits_received + 31) / 32;
|
|
|
|
|
if (words_to_read < 4)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
word = get_ethmac_mac_rx(ethmac);
|
|
|
|
|
word = get_ethmac_mac_rx(nx_mnrs_driver[i].ethmac);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
// find the diver instance belonging to our ethmac
|
|
|
|
|
for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; ++i)
|
|
|
|
|
// get the IP diver instance belonging to our ethmac
|
|
|
|
|
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;
|
|
|
|
|
status = nx_packet_allocate(ip_ptr->nx_ip_default_packet_pool, &packet_ptr, NX_RECEIVE_PACKET, NX_NO_WAIT);
|
|
|
|
|
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;
|
|
|
|
|
nx_packet_release(packet_ptr);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
ULONG old_threshold;
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
ULONG old_threshold;
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|