From b411b2c7169d9cf341f4353c573d572b43e15eef Mon Sep 17 00:00:00 2001 From: Haithem Rahmani Date: Thu, 28 Mar 2024 11:23:31 +0100 Subject: [PATCH] add stm32 network drivers --- .../ethernet/lan8742/nx_stm32_phy_driver.c | 154 ++ .../ethernet/nx_stm32_eth_driver.c | 2070 ++++++++++++++++ .../ethernet/nx_stm32_eth_driver.h | 209 ++ .../ethernet/nx_stm32_phy_driver.h | 50 + .../ethernet/rtl8211/nx_stm32_phy_driver.c | 154 ++ .../template/ethernet/nx_stm32_eth_config.h | 78 + .../template/ethernet/nx_stm32_phy_driver.c | 92 + .../stm32_drivers/template/nx_custom_driver.c | 157 ++ .../stm32_drivers/template/nx_custom_driver.h | 64 + .../wifi/mxchip/mx_wifi_azure_rtos_conf.h | 120 + .../wifi/cypress/nx_driver_framework.c | 1578 +++++++++++++ .../wifi/cypress/nx_driver_framework.h | 151 ++ .../cypress/nx_stm32_cypress_whd_driver.c | 391 +++ .../cypress/nx_stm32_cypress_whd_driver.h | 50 + .../wifi/es_wifi/nx_driver_ism43362.c | 2093 +++++++++++++++++ .../wifi/es_wifi/nx_driver_ism43362.h | 58 + .../wifi/mxchip/mx_wifi_azure_rtos.c | 255 ++ .../wifi/mxchip/nx_driver_emw3080.c | 401 ++++ .../wifi/mxchip/nx_driver_emw3080.h | 48 + .../wifi/mxchip/nx_driver_framework.c | 1587 +++++++++++++ .../wifi/mxchip/nx_driver_framework.h | 138 ++ 21 files changed, 9898 insertions(+) create mode 100644 common/stm32_drivers/ethernet/lan8742/nx_stm32_phy_driver.c create mode 100644 common/stm32_drivers/ethernet/nx_stm32_eth_driver.c create mode 100644 common/stm32_drivers/ethernet/nx_stm32_eth_driver.h create mode 100644 common/stm32_drivers/ethernet/nx_stm32_phy_driver.h create mode 100644 common/stm32_drivers/ethernet/rtl8211/nx_stm32_phy_driver.c create mode 100644 common/stm32_drivers/template/ethernet/nx_stm32_eth_config.h create mode 100644 common/stm32_drivers/template/ethernet/nx_stm32_phy_driver.c create mode 100644 common/stm32_drivers/template/nx_custom_driver.c create mode 100644 common/stm32_drivers/template/nx_custom_driver.h create mode 100644 common/stm32_drivers/template/wifi/mxchip/mx_wifi_azure_rtos_conf.h create mode 100644 common/stm32_drivers/wifi/cypress/nx_driver_framework.c create mode 100644 common/stm32_drivers/wifi/cypress/nx_driver_framework.h create mode 100644 common/stm32_drivers/wifi/cypress/nx_stm32_cypress_whd_driver.c create mode 100644 common/stm32_drivers/wifi/cypress/nx_stm32_cypress_whd_driver.h create mode 100644 common/stm32_drivers/wifi/es_wifi/nx_driver_ism43362.c create mode 100644 common/stm32_drivers/wifi/es_wifi/nx_driver_ism43362.h create mode 100644 common/stm32_drivers/wifi/mxchip/mx_wifi_azure_rtos.c create mode 100644 common/stm32_drivers/wifi/mxchip/nx_driver_emw3080.c create mode 100644 common/stm32_drivers/wifi/mxchip/nx_driver_emw3080.h create mode 100644 common/stm32_drivers/wifi/mxchip/nx_driver_framework.c create mode 100644 common/stm32_drivers/wifi/mxchip/nx_driver_framework.h diff --git a/common/stm32_drivers/ethernet/lan8742/nx_stm32_phy_driver.c b/common/stm32_drivers/ethernet/lan8742/nx_stm32_phy_driver.c new file mode 100644 index 00000000..8db14841 --- /dev/null +++ b/common/stm32_drivers/ethernet/lan8742/nx_stm32_phy_driver.c @@ -0,0 +1,154 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +#include "nx_stm32_phy_driver.h" +#include "nx_stm32_eth_config.h" + + +/* LAN8742 IO functions */ +static int32_t lan8742_io_init(void); +static int32_t lan8742_io_deinit (void); + +static int32_t lan8742_io_write_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal); +static int32_t lan8742_io_read_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal); + +static int32_t lan8742_io_get_tick(void); + +/* LAN8742 IO context object */ +static lan8742_IOCtx_t LAN8742_IOCtx = { lan8742_io_init, + lan8742_io_deinit, + lan8742_io_write_reg, + lan8742_io_read_reg, + lan8742_io_get_tick + }; +/* LAN8742 main object */ +static lan8742_Object_t LAN8742; + +/** + * @brief Initialize the PHY interface + * @param none + * @retval ETH_PHY_STATUS_OK on success, ETH_PHY_STATUS_ERROR otherwise + */ + +int32_t nx_eth_phy_init(void) +{ + int32_t ret = ETH_PHY_STATUS_ERROR; + /* Set PHY IO functions */ + + LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx); + /* Initialize the LAN8742 ETH PHY */ + + if (LAN8742_Init(&LAN8742) == LAN8742_STATUS_OK) + { + ret = ETH_PHY_STATUS_OK; + } + + return ret; +} + +/** + * @brief set the Phy link state. + * @param LinkState + * @retval the link status. + */ + +int32_t nx_eth_phy_set_link_state(int32_t LinkState) +{ + return (LAN8742_SetLinkState(&LAN8742, LinkState)); +} + +/** + * @brief get the Phy link state. + * @param none + * @retval the link status. + */ + +int32_t nx_eth_phy_get_link_state(void) +{ + int32_t linkstate = LAN8742_GetLinkState(&LAN8742); + + return linkstate; +} + +/** + * @brief get the driver object handle + * @param none + * @retval pointer to the LAN8742 main object + */ + +nx_eth_phy_handle_t nx_eth_phy_get_handle(void) +{ + return (nx_eth_phy_handle_t)&LAN8742; +} + +/** + * @brief Initialize the PHY MDIO interface + * @param None + * @retval 0 if OK, -1 if ERROR + */ + +int32_t lan8742_io_init(void) +{ + /* We assume that MDIO GPIO configuration is already done + in the ETH_MspInit() else it should be done here + */ + + /* Configure the MDIO Clock */ + HAL_ETH_SetMDIOClockRange(ð_handle); + + return ETH_PHY_STATUS_OK; +} + +/** + * @brief De-Initialize the MDIO interface + * @param None + * @retval 0 if OK, -1 if ERROR + */ +int32_t lan8742_io_deinit (void) +{ + return ETH_PHY_STATUS_OK; +} + +/** + * @brief Read a PHY register through the MDIO interface. + * @param DevAddr: PHY port address + * @param RegAddr: PHY register address + * @param pRegVal: pointer to hold the register value + * @retval 0 if OK -1 if Error + */ +int32_t lan8742_io_read_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal) +{ + if(HAL_ETH_ReadPHYRegister(ð_handle, DevAddr, RegAddr, pRegVal) != HAL_OK) + { + return ETH_PHY_STATUS_ERROR; + } + + return ETH_PHY_STATUS_OK; +} + +int32_t lan8742_io_write_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal) +{ + if(HAL_ETH_WritePHYRegister(ð_handle, DevAddr, RegAddr, RegVal) != HAL_OK) + { + return ETH_PHY_STATUS_ERROR; + } + + return ETH_PHY_STATUS_OK; +} + +/** + * @brief Get the time in millisecons used for internal PHY driver process. + * @retval Time value + */ +int32_t lan8742_io_get_tick(void) +{ + return HAL_GetTick(); +} diff --git a/common/stm32_drivers/ethernet/nx_stm32_eth_driver.c b/common/stm32_drivers/ethernet/nx_stm32_eth_driver.c new file mode 100644 index 00000000..c58749a4 --- /dev/null +++ b/common/stm32_drivers/ethernet/nx_stm32_eth_driver.c @@ -0,0 +1,2070 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +/* Indicate that driver source is being compiled. */ + +#define NX_DRIVER_SOURCE + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific include area. Include driver-specific include file here! */ + +#ifndef NX_STM32_ETH_DRIVER_H + +/* Determine if the driver uses IP deferred processing or direct ISR processing. */ + +#define NX_DRIVER_ENABLE_DEFERRED /* Define this to enable deferred ISR processing. */ + +/* Include driver specific include file. */ +#include "nx_stm32_eth_driver.h" + +/* Include the phy driver header */ +#include "nx_stm32_phy_driver.h" + +#endif /* NX_STM32_ETH_DRIVER_H */ + +/****** DRIVER SPECIFIC ****** End of part/vendor specific include file area! */ + + +/* Define the driver information structure that is only available within this file. */ +/* Place Ethernet BD at uncacheable memory*/ +static NX_DRIVER_INFORMATION nx_driver_information; + +/* Rounded header size */ +static ULONG header_size; + +extern ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */ +extern ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */ + + +ETH_TxPacketConfig_t TxPacketCfg; +ETH_MACFilterConfigTypeDef FilterConfig; + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific data area. Include hardware-specific data here! */ + +/****** DRIVER SPECIFIC ****** End of part/vendor specific data area! */ + + +/* Define the routines for processing each driver entry request. The contents of these routines will change with +each driver. However, the main driver entry function will not change, except for the entry function name. */ + +static VOID _nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_enable(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_disable(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr); +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +static VOID _nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr); +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + +static VOID _nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr); + +static VOID _nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr); + + +/* Define the prototypes for the hardware implementation of this driver. The contents of these routines are +driver-specific. */ + +static UINT _nx_driver_hardware_initialize(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_enable(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_disable(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_packet_send(NX_PACKET *packet_ptr); +static UINT _nx_driver_hardware_multicast_join(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_multicast_leave(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_get_status(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_hardware_packet_received(VOID); +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +static UINT _nx_driver_hardware_capability_set(NX_IP_DRIVER *driver_req_ptr); +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_stm32_eth_driver */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This is the entry point of the NetX Ethernet Driver. This driver */ +/* function is responsible for initializing the Ethernet controller, */ +/* enabling or disabling the controller as need, preparing */ +/* a packet for transmission, and getting status information. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr The driver request from the */ +/* IP layer. */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_interface_attach Process attach request */ +/* _nx_driver_initialize Process initialize request */ +/* _nx_driver_enable Process link enable request */ +/* _nx_driver_disable Process link disable request */ +/* _nx_driver_packet_send Process send packet requests */ +/* _nx_driver_multicast_join Process multicast join request*/ +/* _nx_driver_multicast_leave Process multicast leave req */ +/* _nx_driver_get_status Process get status request */ +/* _nx_driver_deferred_processing Drive deferred processing */ +/* */ +/* CALLED BY */ +/* */ +/* IP layer */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +/****** DRIVER SPECIFIC ****** Start of part/vendor specific global driver entry function name. */ +VOID nx_stm32_eth_driver(NX_IP_DRIVER *driver_req_ptr) +/****** DRIVER SPECIFIC ****** End of part/vendor specific global driver entry function name. */ +{ + + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Process according to the driver request type in the IP control + block. */ + switch (driver_req_ptr -> nx_ip_driver_command) + { + + case NX_LINK_INTERFACE_ATTACH: + + /* Process link interface attach requests. */ + _nx_driver_interface_attach(driver_req_ptr); + break; + + case NX_LINK_INITIALIZE: + { + + /* Process link initialize requests. */ + _nx_driver_initialize(driver_req_ptr); + break; + } + + case NX_LINK_ENABLE: + { + + /* Process link enable requests. */ + _nx_driver_enable(driver_req_ptr); + break; + } + + case NX_LINK_DISABLE: + { + + /* Process link disable requests. */ + _nx_driver_disable(driver_req_ptr); + break; + } + + + case NX_LINK_ARP_SEND: + case NX_LINK_ARP_RESPONSE_SEND: + case NX_LINK_PACKET_BROADCAST: + case NX_LINK_RARP_SEND: + case NX_LINK_PACKET_SEND: + { + + /* Process packet send requests. */ + _nx_driver_packet_send(driver_req_ptr); + break; + } + + + case NX_LINK_MULTICAST_JOIN: + { + + /* Process multicast join requests. */ + _nx_driver_multicast_join(driver_req_ptr); + break; + } + + + case NX_LINK_MULTICAST_LEAVE: + { + + /* Process multicast leave requests. */ + _nx_driver_multicast_leave(driver_req_ptr); + break; + } + + case NX_LINK_GET_STATUS: + { + + /* Process get status requests. */ + _nx_driver_get_status(driver_req_ptr); + break; + } + + case NX_LINK_DEFERRED_PROCESSING: + { + + /* Process driver deferred requests. */ + + /* Process a device driver function on behave of the IP thread. */ + _nx_driver_deferred_processing(driver_req_ptr); + + break; + } + + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + case NX_INTERFACE_CAPABILITY_GET: + { + + /* Process get capability requests. */ + _nx_driver_capability_get(driver_req_ptr); + break; + } + + case NX_INTERFACE_CAPABILITY_SET: + { + + /* Process set capability requests. */ + _nx_driver_capability_set(driver_req_ptr); + break; + } +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + default: + + + /* Invalid driver request. */ + + /* Return the unhandled command status. */ + driver_req_ptr -> nx_ip_driver_status = NX_UNHANDLED_COMMAND; + + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_interface_attach */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the interface attach request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr) +{ + + + /* Setup the driver's interface. This example is for a simple one-interface + Ethernet driver. Additional logic is necessary for multiple port devices. */ + nx_driver_information.nx_driver_information_interface = driver_req_ptr -> nx_ip_driver_interface; + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + driver_req_ptr -> nx_ip_driver_interface -> nx_interface_capability_flag = NX_DRIVER_CAPABILITY; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + /* Return successful status. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_initialize */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the initialize request. The processing */ +/* in this function is generic. All ethernet controller logic is to */ +/* be placed in _nx_driver_hardware_initialize. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_initialize Process initialize request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr) +{ + + NX_IP *ip_ptr; + NX_INTERFACE *interface_ptr; + UINT status; + CHAR *payload_address; /* Address of the first payload*/ + VOID *rounded_pool_start; /* Rounded stating address */ + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Setup interface pointer. */ + interface_ptr = driver_req_ptr -> nx_ip_driver_interface; + + /* Initialize the driver's information structure. */ + + /* Default IP pointer to NULL. */ + nx_driver_information.nx_driver_information_ip_ptr = NX_NULL; + + /* Setup the driver state to not initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_NOT_INITIALIZED; + + /* Setup the default packet pool for the driver's received packets. */ + nx_driver_information.nx_driver_information_packet_pool_ptr = ip_ptr -> nx_ip_default_packet_pool; + + /* Get the rounded start pool start. */ + rounded_pool_start = nx_driver_information.nx_driver_information_packet_pool_ptr->nx_packet_pool_start; + + /* Calculate the address of payload. */ + payload_address = (CHAR *)((ALIGN_TYPE)rounded_pool_start + sizeof(NX_PACKET)); + + /* Align the address of payload. */ + payload_address = (CHAR *)((((ALIGN_TYPE)payload_address + NX_PACKET_ALIGNMENT - 1) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT); + + /* Calculate the header size. */ + header_size = (ULONG)((ALIGN_TYPE)payload_address - (ALIGN_TYPE)rounded_pool_start); + + /* Clear the deferred events for the driver. */ + nx_driver_information.nx_driver_information_deferred_events = 0; + + /* Call the hardware-specific ethernet controller initialization. */ + status = _nx_driver_hardware_initialize(driver_req_ptr); + + /* Determine if the request was successful. */ + if (status == NX_SUCCESS) + { + + /* Successful hardware initialization. */ + + /* Setup driver information to point to IP pointer. */ + nx_driver_information.nx_driver_information_ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Setup the link maximum transfer unit. */ + interface_ptr -> nx_interface_ip_mtu_size = NX_DRIVER_ETHERNET_MTU - NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Setup the physical address of this IP instance. Increment the + physical address lsw to simulate multiple nodes hanging on the + ethernet. */ + interface_ptr -> nx_interface_physical_address_msw = + (ULONG)(( eth_handle.Init.MACAddr[0] << 8) | ( eth_handle.Init.MACAddr[1])); + interface_ptr -> nx_interface_physical_address_lsw = + (ULONG)(( eth_handle.Init.MACAddr[2] << 24) | ( eth_handle.Init.MACAddr[3] << 16) | + ( eth_handle.Init.MACAddr[4] << 8) | ( eth_handle.Init.MACAddr[5])); + + /* Indicate to the IP software that IP to physical mapping + is required. */ + interface_ptr -> nx_interface_address_mapping_needed = NX_TRUE; + + /* Move the driver's state to initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED; + + /* Indicate successful initialize. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + + /* Initialization failed. Indicate that the request failed. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_enable */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the initialize request. The processing */ +/* in this function is generic. All ethernet controller logic is to */ +/* be placed in _nx_driver_hardware_enable. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_enable Process enable request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_enable(NX_IP_DRIVER *driver_req_ptr) +{ + + NX_IP *ip_ptr; + ETH_MACConfigTypeDef MACConf; + UINT status, duplex, speed = 0; + INT PHYLinkState; + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* See if we can honor the NX_LINK_ENABLE request. */ + if (nx_driver_information.nx_driver_information_state < NX_DRIVER_STATE_INITIALIZED) + { + + /* Mark the request as not successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + + /* Check if it is enabled by someone already */ + if (nx_driver_information.nx_driver_information_state >= NX_DRIVER_STATE_LINK_ENABLED) + { + + /* Yes, the request has already been made. */ + driver_req_ptr -> nx_ip_driver_status = NX_ALREADY_ENABLED; + return; + } + + if (nx_eth_phy_init() != ETH_PHY_STATUS_OK) + { + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + + PHYLinkState = nx_eth_phy_get_link_state(); + + /* Get link state */ + if(PHYLinkState <= ETH_PHY_STATUS_LINK_DOWN) + { + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + else + { + switch (PHYLinkState) + { +#if defined(ETH_PHY_1000MBITS_SUPPORTED) + case ETH_PHY_STATUS_1000MBITS_FULLDUPLEX: + duplex = ETH_FULLDUPLEX_MODE; + speed = ETH_SPEED_1000M; + break; + case ETH_PHY_STATUS_1000MBITS_HALFDUPLEX: + duplex = ETH_HALFDUPLEX_MODE; + speed = ETH_SPEED_1000M; + break; +#endif +case ETH_PHY_STATUS_100MBITS_FULLDUPLEX: + duplex = ETH_FULLDUPLEX_MODE; + speed = ETH_SPEED_100M; + break; + case ETH_PHY_STATUS_100MBITS_HALFDUPLEX: + duplex = ETH_HALFDUPLEX_MODE; + speed = ETH_SPEED_100M; + break; + case ETH_PHY_STATUS_10MBITS_FULLDUPLEX: + duplex = ETH_FULLDUPLEX_MODE; + speed = ETH_SPEED_10M; + break; + case ETH_PHY_STATUS_10MBITS_HALFDUPLEX: + duplex = ETH_HALFDUPLEX_MODE; + speed = ETH_SPEED_10M; + break; + default: + duplex = ETH_FULLDUPLEX_MODE; + speed = ETH_SPEED_100M; + break; + } + + /* Get MAC Config MAC */ + HAL_ETH_GetMACConfig(ð_handle, &MACConf); + MACConf.DuplexMode = duplex; + MACConf.Speed = speed; +#if defined(ETH_DMASBMR_BLEN4) /* ETH AXI support*/ +#if defined(ETH_PHY_1000MBITS_SUPPORTED) + MACConf.PortSelect = 0; +#else + MACConf.PortSelect = 1; +#endif +#endif + HAL_ETH_SetMACConfig(ð_handle, &MACConf); + } + + /* Call hardware specific enable. */ + status = _nx_driver_hardware_enable(driver_req_ptr); + + /* Was the hardware enable successful? */ + if (status == NX_SUCCESS) + { + + /* Update the driver state to link enabled. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_LINK_ENABLED; + + /* Mark request as successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Mark the IP instance as link up. */ + ip_ptr -> nx_ip_driver_link_up = NX_TRUE; + } + else + { + + /* Enable failed. Indicate that the request failed. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_disable */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the disable request. The processing */ +/* in this function is generic. All ethernet controller logic is to */ +/* be placed in _nx_driver_hardware_disable. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_disable Process disable request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_disable(NX_IP_DRIVER *driver_req_ptr) +{ + + NX_IP *ip_ptr; + UINT status; + + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Check if the link is enabled. */ + if (nx_driver_information.nx_driver_information_state != NX_DRIVER_STATE_LINK_ENABLED) + { + + /* The link is not enabled, so just return an error. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + + /* Call hardware specific disable. */ + status = _nx_driver_hardware_disable(driver_req_ptr); + + /* Was the hardware disable successful? */ + if (status == NX_SUCCESS) + { + + /* Mark the IP instance as link down. */ + ip_ptr -> nx_ip_driver_link_up = NX_FALSE; + + /* Update the driver state back to initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED; + + /* Mark request as successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + + /* Disable failed, return an error. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_packet_send */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the packet send request. The processing */ +/* in this function is generic. All ethernet controller packet send */ +/* logic is to be placed in _nx_driver_hardware_packet_send. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_packet_send Process packet send request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr) +{ + + NX_IP *ip_ptr; + NX_PACKET *packet_ptr; + ULONG *ethernet_frame_ptr; + UINT status; + + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Check to make sure the link is up. */ + if (nx_driver_information.nx_driver_information_state != NX_DRIVER_STATE_LINK_ENABLED) + { + + /* Inidate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(driver_req_ptr -> nx_ip_driver_packet); + return; + } + + /* Process driver send packet. */ + + /* Place the ethernet frame at the front of the packet. */ + packet_ptr = driver_req_ptr -> nx_ip_driver_packet; + + /* Adjust the prepend pointer. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr - NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Setup the ethernet frame pointer to build the ethernet frame. Backup another 2 + * bytes to get 32-bit word alignment. */ + ethernet_frame_ptr = (ULONG *) (packet_ptr -> nx_packet_prepend_ptr - 2); + + /* Set up the hardware addresses in the Ethernet header. */ + *ethernet_frame_ptr = driver_req_ptr -> nx_ip_driver_physical_address_msw; + *(ethernet_frame_ptr + 1) = driver_req_ptr -> nx_ip_driver_physical_address_lsw; + + *(ethernet_frame_ptr + 2) = (ip_ptr -> nx_ip_arp_physical_address_msw << 16) | + (ip_ptr -> nx_ip_arp_physical_address_lsw >> 16); + *(ethernet_frame_ptr + 3) = (ip_ptr -> nx_ip_arp_physical_address_lsw << 16); + + /* Set up the frame type field in the Ethernet harder. */ + if ((driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_SEND)|| + (driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_RESPONSE_SEND)) + { + + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_ARP; + } + else if(driver_req_ptr -> nx_ip_driver_command == NX_LINK_RARP_SEND) + { + + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_RARP; + } + +#ifdef FEATURE_NX_IPV6 + else if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6) + { + + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_IPV6; + } +#endif /* FEATURE_NX_IPV6 */ + + else + { + + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_IP; + } + + /* Endian swapping if NX_LITTLE_ENDIAN is defined. */ + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 1)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 2)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 3)); + + /* Determine if the packet exceeds the driver's MTU. */ + if (packet_ptr -> nx_packet_length > NX_DRIVER_ETHERNET_MTU) + { + + /* This packet exceeds the size of the driver's MTU. Simply throw it away! */ + + /* Remove the Ethernet header. */ + NX_DRIVER_ETHERNET_HEADER_REMOVE(packet_ptr); + + /* Indicate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(packet_ptr); + return; + } + + /* Transmit the packet through the Ethernet controller low level access routine. */ + status = _nx_driver_hardware_packet_send(packet_ptr); + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + + /* Driver's hardware send packet routine failed to send the packet. */ + + /* Remove the Ethernet header. */ + NX_DRIVER_ETHERNET_HEADER_REMOVE(packet_ptr); + + /* Indicate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(packet_ptr); + } + else + { + + /* Set the status of the request. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_multicast_join */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the multicast join request. The processing */ +/* in this function is generic. All ethernet controller multicast join */ +/* logic is to be placed in _nx_driver_hardware_multicast_join. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_multicast_join Process multicast join request*/ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr) +{ + + UINT status; + + + /* Call hardware specific multicast join function. */ + status = _nx_driver_hardware_multicast_join(driver_req_ptr); + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + else + { + + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_multicast_leave */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the multicast leave request. The */ +/* processing in this function is generic. All ethernet controller */ +/* multicast leave logic is to be placed in */ +/* _nx_driver_hardware_multicast_leave. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_multicast_leave Process multicast leave req */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr) +{ + + UINT status; + + + /* Call hardware specific multicast leave function. */ + status = _nx_driver_hardware_multicast_leave(driver_req_ptr); + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + else + { + + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_get_status */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the get status request. The processing */ +/* in this function is generic. All ethernet controller get status */ +/* logic is to be placed in _nx_driver_hardware_get_status. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_get_status Process get status request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr) +{ + + UINT status; + + + /* Call hardware specific get status function. */ + status = _nx_driver_hardware_get_status(driver_req_ptr); + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + else + { + + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_capability_get */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the get capability request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr) +{ + + /* Return the capability of the Ethernet controller. */ + *(driver_req_ptr -> nx_ip_driver_return_ptr) = NX_DRIVER_CAPABILITY; + + /* Return the success status. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_capability_set */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the set capability request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr) +{ + + UINT status; + + + /* Call hardware specific get status function. */ + status = _nx_driver_hardware_capability_set(driver_req_ptr); + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + else + { + + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_deferred_processing */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* XC, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the deferred ISR action within the context */ +/* of the IP thread. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_packet_transmitted Clean up after transmission */ +/* _nx_driver_packet_received Process a received packet */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr) +{ + + TX_INTERRUPT_SAVE_AREA + + ULONG deferred_events; + + + /* Disable interrupts. */ + TX_DISABLE + + /* Pickup deferred events. */ + deferred_events = nx_driver_information.nx_driver_information_deferred_events; + nx_driver_information.nx_driver_information_deferred_events = 0; + + /* Restore interrupts. */ + TX_RESTORE + /* Check for a transmit complete event. */ + if(deferred_events & NX_DRIVER_DEFERRED_PACKET_TRANSMITTED) + { + + /* Process transmitted packet(s). */ + HAL_ETH_ReleaseTxPacket(ð_handle); + } + /* Check for received packet. */ + if(deferred_events & NX_DRIVER_DEFERRED_PACKET_RECEIVED) + { + + /* Process received packet(s). */ + _nx_driver_hardware_packet_received(); + } + + /* Mark request as successful. */ + driver_req_ptr->nx_ip_driver_status = NX_SUCCESS; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_transfer_to_netx */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing incoming packets. This routine would */ +/* be called from the driver-specific receive packet processing */ +/* function _nx_driver_hardware. */ +/* */ +/* INPUT */ +/* */ +/* ip_ptr Pointer to IP protocol block */ +/* packet_ptr Packet pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Error indication */ +/* */ +/* CALLS */ +/* */ +/* _nx_ip_packet_receive NetX IP packet receive */ +/* _nx_ip_packet_deferred_receive NetX IP packet receive */ +/* _nx_arp_packet_deferred_receive NetX ARP packet receive */ +/* _nx_rarp_packet_deferred_receive NetX RARP packet receive */ +/* _nx_packet_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_hardware_packet_received Driver packet receive function*/ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr) +{ + + USHORT packet_type; + + + /* Set the interface for the incoming packet. */ + packet_ptr -> nx_packet_ip_interface = nx_driver_information.nx_driver_information_interface; + + /* Pickup the packet header to determine where the packet needs to be + sent. */ + packet_type = (USHORT)(((UINT) (*(packet_ptr -> nx_packet_prepend_ptr+12))) << 8) | + ((UINT) (*(packet_ptr -> nx_packet_prepend_ptr+13))); + + /* Route the incoming packet according to its ethernet type. */ + if (packet_type == NX_DRIVER_ETHERNET_IP || packet_type == NX_DRIVER_ETHERNET_IPV6) + { + /* Note: The length reported by some Ethernet hardware includes + bytes after the packet as well as the Ethernet header. In some + cases, the actual packet length after the Ethernet header should + be derived from the length in the IP header (lower 16 bits of + the first 32-bit word). */ + + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr += NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length -= NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Route to the ip receive function. */ + _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr); + } + else if (packet_type == NX_DRIVER_ETHERNET_ARP) + { + + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr += NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length -= NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Route to the ARP receive function. */ + _nx_arp_packet_deferred_receive(ip_ptr, packet_ptr); + } + else if (packet_type == NX_DRIVER_ETHERNET_RARP) + { + + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr += NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length -= NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Route to the RARP receive function. */ + _nx_rarp_packet_deferred_receive(ip_ptr, packet_ptr); + } + else + { + /* Invalid ethernet header... release the packet. */ + nx_packet_release(packet_ptr); + } +} + + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific internal driver functions. */ + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_initialize */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific initialization. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* ETH_BSP_Config Configure Ethernet */ +/* ETH_MACAddressConfig Setup MAC address */ +/* ETH_DMARxDescReceiveITConfig Enable receive descriptors */ +/* nx_packet_allocate Allocate receive packet(s) */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_initialize Driver initialize processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_initialize(NX_IP_DRIVER *driver_req_ptr) +{ + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Setup indices. */ + nx_driver_information.nx_driver_information_receive_current_index = 0; + nx_driver_information.nx_driver_information_transmit_current_index = 0; + nx_driver_information.nx_driver_information_transmit_release_index = 0; + + /* Clear the number of buffers in use counter. */ + nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use = 0; + + /* Make sure there are receive packets... otherwise, return an error. */ + if (nx_driver_information.nx_driver_information_packet_pool_ptr == NULL) + { + + /* There must be receive packets. If not, return an error! */ + return(NX_DRIVER_ERROR); + } + +#ifdef NX_DRIVER_ETH_HW_IP_INIT + nx_eth_init(); +#endif /* NX_DRIVER_ETH_HW_IP_INIT */ + + ETH_DMAConfigTypeDef dmaDefaultConf; +#if defined(ETH_DMASBMR_BLEN4) /* ETH AXI support*/ + dmaDefaultConf.DMAArbitration = ETH_DMAARBITRATION_TX; +#else + dmaDefaultConf.DMAArbitration = ETH_DMAARBITRATION_RX1_TX1; +#endif + dmaDefaultConf.AddressAlignedBeats = ENABLE; + dmaDefaultConf.BurstMode = ETH_BURSTLENGTH_FIXED; + dmaDefaultConf.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.FlushRxPacket = DISABLE; +#ifndef STM32_ETH_HAL_LEGACY + dmaDefaultConf.PBLx8Mode = DISABLE; +#if defined(ETH_DMASBMR_BLEN4) /* ETH AXI support*/ + dmaDefaultConf.RxOSRLimit = ETH_RX_OSR_LIMIT_3; + dmaDefaultConf.TxOSRLimit = ETH_TX_OSR_LIMIT_3; + dmaDefaultConf.AXIBLENMaxSize = ETH_BLEN_MAX_SIZE_16; +#else + dmaDefaultConf.RebuildINCRxBurst = DISABLE; +#endif + dmaDefaultConf.SecondPacketOperate = ENABLE; + dmaDefaultConf.TCPSegmentation = DISABLE; + dmaDefaultConf.MaximumSegmentSize = 536; +#endif +#ifdef STM32_ETH_HAL_LEGACY + dmaDefaultConf.DropTCPIPChecksumErrorFrame = ENABLE; + dmaDefaultConf.ReceiveStoreForward = DISABLE; + dmaDefaultConf.TransmitStoreForward = ENABLE; + dmaDefaultConf.TransmitThresholdControl = ENABLE; + dmaDefaultConf.ForwardErrorFrames = DISABLE; + dmaDefaultConf.ReceiveThresholdControl = DISABLE; + dmaDefaultConf.SecondFrameOperate = DISABLE; + dmaDefaultConf.EnhancedDescriptorFormat = DISABLE; + dmaDefaultConf.DescriptorSkipLength = DISABLE; +#endif + /* enable OSF bit to enhance throughput */ + HAL_ETH_SetDMAConfig(ð_handle, &dmaDefaultConf); +#ifdef STM32_ETH_PROMISCUOUS_ENABLE + FilterConfig.PromiscuousMode = ENABLE; +#else + FilterConfig.PromiscuousMode = DISABLE; +#endif + FilterConfig.HashUnicast = DISABLE; + FilterConfig.HashMulticast = DISABLE; + FilterConfig.DestAddrInverseFiltering = DISABLE; + FilterConfig.PassAllMulticast = DISABLE; + FilterConfig.BroadcastFilter = ENABLE; + FilterConfig.SrcAddrInverseFiltering = DISABLE; + FilterConfig.SrcAddrFiltering = DISABLE; + FilterConfig.HachOrPerfectFilter = DISABLE; + FilterConfig.ReceiveAllMode = DISABLE; + FilterConfig.ControlPacketsFilter = 0x00; + + /* Set Tx packet config common parameters */ + memset(&TxPacketCfg, 0, sizeof(ETH_TxPacketConfig_t)); + TxPacketCfg.Attributes = ETH_TX_PACKETS_FEATURES_CSUM ; + TxPacketCfg.CRCPadCtrl = ETH_CRC_PAD_DISABLE; + + /* Clear the number of buffers in use counter. */ + nx_driver_information.nx_driver_information_multicast_count = 0; + + /* Return success! */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_enable */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific link enable requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* ETH_Start Start Ethernet operation */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_enable Driver link enable processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_enable(NX_IP_DRIVER *driver_req_ptr) +{ + + /* Call STM32 library to start Ethernet operation. */ + HAL_ETH_Start_IT(ð_handle); + + /* Return success! */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_disable */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific link disable requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* ETH_MACTransmissionCmd Disable transmit */ +/* ETH_FlushTransmitFIFO Flush transmit FIFO */ +/* ETH_MACReceptionCmd Disable receive */ +/* ETH_DMATransmissionCmd Stop DMA transmission */ +/* ETH_DMAReceptionCmd Stop DMA reception */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_disable Driver link disable processing*/ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_disable(NX_IP_DRIVER *driver_req_ptr) +{ + + HAL_ETH_Stop(ð_handle); + + /* Return success! */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_packet_send */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific packet send requests. */ +/* */ +/* INPUT */ +/* */ +/* packet_ptr Pointer to packet to send */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* [_nx_driver_transmit_packet_enqueue] Optional internal transmit */ +/* packet queue routine */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_packet_send Driver packet send processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ + +static UINT _nx_driver_hardware_packet_send(NX_PACKET *packet_ptr) +{ + + NX_PACKET *pktIdx; + UINT buffLen = 0; + + ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT]; + memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef)); + + + int i = 0; + + for (pktIdx = packet_ptr;pktIdx != NX_NULL ; pktIdx = pktIdx -> nx_packet_next) + { + if (i >= ETH_TX_DESC_CNT) + { + return NX_DRIVER_ERROR; + } + + Txbuffer[i].buffer = pktIdx->nx_packet_prepend_ptr; + Txbuffer[i].len = (pktIdx -> nx_packet_append_ptr - pktIdx->nx_packet_prepend_ptr); + buffLen += (pktIdx -> nx_packet_append_ptr - pktIdx->nx_packet_prepend_ptr); + + if(i>0) + { + Txbuffer[i-1].next = &Txbuffer[i]; + } + + if (pktIdx-> nx_packet_next ==NULL) + { + Txbuffer[i].next = NULL; + } + + i++; + clean_cache_by_addr((uint32_t*)(pktIdx -> nx_packet_data_start), pktIdx -> nx_packet_data_end - pktIdx -> nx_packet_data_start); + } + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + if (packet_ptr -> nx_packet_interface_capability_flag & (NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM | + NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM | + NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM | + NX_INTERFACE_CAPABILITY_ICMPV6_TX_CHECKSUM)) + { + TxPacketCfg.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; + } + else if (packet_ptr -> nx_packet_interface_capability_flag & NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM) + { + TxPacketCfg.ChecksumCtrl = ETH_CHECKSUM_IPHDR_INSERT; + } +#else + TxPacketCfg.ChecksumCtrl = ETH_CHECKSUM_DISABLE; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + TxPacketCfg.Length = buffLen; + TxPacketCfg.TxBuffer = Txbuffer; + TxPacketCfg.pData = (uint32_t *)packet_ptr; + + if(HAL_ETH_Transmit_IT(ð_handle, &TxPacketCfg)) + { + return(NX_DRIVER_ERROR); + } + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_multicast_join */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific multicast join requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_multicast_join Driver multicast join */ +/* processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_multicast_join(NX_IP_DRIVER *driver_req_ptr) +{ + + + /* Increase the multicast count. */ + nx_driver_information.nx_driver_information_multicast_count++; + + /* Enable multicast frame reception. */ + FilterConfig.PassAllMulticast = ENABLE; + HAL_ETH_SetMACFilterConfig(ð_handle, &FilterConfig); + + /* Return success. */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_multicast_leave */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific multicast leave requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR]*/ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_multicast_leave Driver multicast leave */ +/* processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_multicast_leave(NX_IP_DRIVER *driver_req_ptr) +{ + + /* Decrease the multicast count. */ + nx_driver_information.nx_driver_information_multicast_count--; + + /* If multicast count reaches zero, disable multicast frame reception. */ + if (nx_driver_information.nx_driver_information_multicast_count == 0) + { + + /* Disable multicast frame reception. */ + FilterConfig.PassAllMulticast = DISABLE; + HAL_ETH_SetMACFilterConfig(ð_handle, &FilterConfig); + } + + /* Return success. */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_get_status */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific get status requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR]*/ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_get_status Driver get status processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_get_status(NX_IP_DRIVER *driver_req_ptr) +{ + INT PHYLinkState; + + /* Get link status. */ + PHYLinkState = nx_eth_phy_get_link_state(); + + /* Check link status. */ + if(PHYLinkState <= ETH_PHY_STATUS_LINK_DOWN) + { + /* Update Link status if physical link is down. */ + *(driver_req_ptr->nx_ip_driver_return_ptr) = NX_FALSE; + } + else + { + /* Update Link status if physical link is up. */ + *(driver_req_ptr->nx_ip_driver_return_ptr) = NX_TRUE; + } + + /* Return success. */ + return NX_SUCCESS; +} + +void HAL_ETH_TxFreeCallback(uint32_t * buff) +{ + NX_PACKET * release_packet = (NX_PACKET *) buff; + + /* Remove the Ethernet header and release the packet. */ + NX_DRIVER_ETHERNET_HEADER_REMOVE(release_packet); + + /* Release the packet. */ + nx_packet_transmit_release(release_packet); +} + +static VOID _nx_driver_hardware_packet_received(VOID) +{ + NX_PACKET *received_packet_ptr; + + while (HAL_ETH_ReadData(ð_handle, (void **)&received_packet_ptr) == HAL_OK) + { + /* Transfer the packet to NetX. */ + _nx_driver_transfer_to_netx(nx_driver_information.nx_driver_information_ip_ptr, received_packet_ptr); + } +} + +void HAL_ETH_RxAllocateCallback(uint8_t ** buff) +{ + NX_PACKET *packet_ptr; + if (nx_packet_allocate(nx_driver_information.nx_driver_information_packet_pool_ptr, &packet_ptr, + NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_SUCCESS) + { + /* Adjust the packet. */ + packet_ptr -> nx_packet_prepend_ptr += 2; + invalidate_cache_by_addr((uint32_t*)packet_ptr -> nx_packet_data_start, packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start); + *buff = packet_ptr -> nx_packet_prepend_ptr; + } + else + { + /* Rx Buffer Pool is exhausted. */ + *buff = NULL; + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION */ +/* */ +/* HAL_ETH_RxLinkCallback */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function chains all received packets before passing */ +/* the first one to NetXDuo stack. */ +/* */ +/* INPUT */ +/* */ +/* first_packet_ptr pointer to first received packet */ +/* last_packet_ptr pointer to last received packet */ +/* buff pointer to received data */ +/* length received data length */ +/* */ +/* OUTPUT */ +/* */ +/* received packet pointer */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* HAL_ETH_ReadData Read a received packet */ +/* */ +/**************************************************************************/ +void HAL_ETH_RxLinkCallback(void **first_packet_ptr, void **last_packet_ptr, uint8_t *buff, uint16_t Length) +{ + NX_PACKET **first_nx_packet_ptr = (NX_PACKET **)first_packet_ptr; + NX_PACKET **last_nx_packet_ptr = (NX_PACKET **)last_packet_ptr; + NX_PACKET *received_packet_ptr; + + /* Indicate the offset of the received data. */ + uint8_t *data_buffer_ptr = buff - 2U - header_size; + + received_packet_ptr = (NX_PACKET *)data_buffer_ptr; + received_packet_ptr->nx_packet_append_ptr = received_packet_ptr->nx_packet_prepend_ptr + Length; + received_packet_ptr->nx_packet_length = Length; + + /* Check whether this is the first packet. */ + if (*first_nx_packet_ptr == NULL) + { + /* Add the first buffer of the packet. */ + *first_nx_packet_ptr = received_packet_ptr; + } + /* This is not the first packet. */ + else + { + /* Add the rest of the buffer to the end of the packet. */ + (*last_nx_packet_ptr)->nx_packet_next = received_packet_ptr; + } + /* Save the current packet in order to use it in the next iteration. */ + *last_nx_packet_ptr = received_packet_ptr; +} + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_capability_set */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific capability set requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_capability_set Capability set processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* xx-xx-xxxx Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_capability_set(NX_IP_DRIVER *driver_req_ptr) +{ + + return NX_SUCCESS; +} +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +{ + + ULONG deffered_events; + deffered_events = nx_driver_information.nx_driver_information_deferred_events; + + nx_driver_information.nx_driver_information_deferred_events |= NX_DRIVER_DEFERRED_PACKET_RECEIVED; + + if (!deffered_events) + { + /* Call NetX deferred driver processing. */ + _nx_ip_driver_deferred_processing(nx_driver_information.nx_driver_information_ip_ptr); + } +} + +void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth) +{ + ULONG deffered_events; + deffered_events = nx_driver_information.nx_driver_information_deferred_events; + + + nx_driver_information.nx_driver_information_deferred_events |= NX_DRIVER_DEFERRED_PACKET_TRANSMITTED; + + if (!deffered_events) + { + /* Call NetX deferred driver processing. */ + _nx_ip_driver_deferred_processing(nx_driver_information.nx_driver_information_ip_ptr); + } +} + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific internal driver functions. */ diff --git a/common/stm32_drivers/ethernet/nx_stm32_eth_driver.h b/common/stm32_drivers/ethernet/nx_stm32_eth_driver.h new file mode 100644 index 00000000..4f3e2e56 --- /dev/null +++ b/common/stm32_drivers/ethernet/nx_stm32_eth_driver.h @@ -0,0 +1,209 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#ifndef NX_STM32_ETH_DRIVER_H +#define NX_STM32_ETH_DRIVER_H + + +#ifdef __cplusplus + +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { +#endif + + +/* Include ThreadX header file, if not already. */ + +#ifndef TX_API_H +#include "tx_api.h" +#endif + + +/* Include NetX header file, if not already. */ + +#ifndef NX_API_H +#include "nx_api.h" +#endif + + +/* Determine if the driver's source file is being compiled. The constants and typdefs are only valid within + the driver's source file compilation. */ + +#ifdef NX_DRIVER_SOURCE + + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific include area. Include any such files here! */ +#include "nx_stm32_eth_config.h" + +/****** DRIVER SPECIFIC ****** End of part/vendor specific include file area! */ + + +/* Define generic constants and macros for all NetX Ethernet drivers. */ + +#define NX_DRIVER_ETHERNET_IP 0x0800 +#define NX_DRIVER_ETHERNET_IPV6 0x86dd +#define NX_DRIVER_ETHERNET_ARP 0x0806 +#define NX_DRIVER_ETHERNET_RARP 0x8035 + +#define NX_DRIVER_ETHERNET_MTU 1514 +#define NX_DRIVER_ETHERNET_FRAME_SIZE 14 + +#define NX_DRIVER_DEFERRED_PACKET_RECEIVED 1 +#define NX_DRIVER_DEFERRED_DEVICE_RESET 2 +#define NX_DRIVER_DEFERRED_PACKET_TRANSMITTED 4 + +#define NX_DRIVER_STATE_NOT_INITIALIZED 1 +#define NX_DRIVER_STATE_INITIALIZE_FAILED 2 +#define NX_DRIVER_STATE_INITIALIZED 3 +#define NX_DRIVER_STATE_LINK_ENABLED 4 + +#define NX_DRIVER_ERROR 90 + + +#define NX_DRIVER_ETHERNET_HEADER_REMOVE(p) \ +{ \ + p -> nx_packet_prepend_ptr = p -> nx_packet_prepend_ptr + NX_DRIVER_ETHERNET_FRAME_SIZE; \ + p -> nx_packet_length = p -> nx_packet_length - NX_DRIVER_ETHERNET_FRAME_SIZE; \ +} + +/**************************************************************************/ +/* Cache maintenance. */ +/**************************************************************************/ +#if defined(__CORTEX_M) +#if (defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)) +#define invalidate_cache_by_addr(__ptr__, __size__) SCB_InvalidateDCache_by_Addr((void *)(__ptr__), (int32_t)(__size__)) +#define clean_cache_by_addr(__ptr__, __size__) SCB_CleanDCache_by_Addr((uint32_t *)(__ptr__), (int32_t)(__size__)) +#else +#define invalidate_cache_by_addr(__ptr__, __size__) +#define clean_cache_by_addr(__ptr__, __size__) +#endif +#else +#if defined(DATA_CACHE_ENABLE) && (DATA_CACHE_ENABLE == 1U) +__STATIC_FORCEINLINE void __invalidate_cache_by_addr(uint32_t start, uint32_t size) +{ + uint32_t current = start & ~31U; + uint32_t end = (start + size + 31U) & ~31U; + while (current < end) + { + L1C_CleanInvalidateDCacheMVA((void*)current); /* We clean also because buffers are not 32-byte aligned and read is done after this anyway. */ + current += 32U; + } +} + +__STATIC_FORCEINLINE void __clean_cache_by_addr(uint32_t start, uint32_t size) +{ + uint32_t current = start & ~31U; + uint32_t end = (start + size + 31U) & ~31U; + while (current < end) + { + L1C_CleanDCacheMVA((void*)current); + current += 32U; + } +} +#define invalidate_cache_by_addr(__ptr__, __size__) __invalidate_cache_by_addr((uint32_t)(__ptr__), (uint32_t)(__size__)) +#define clean_cache_by_addr(__ptr__, __size__) __clean_cache_by_addr((uint32_t)(__ptr__), (uint32_t)(__size__)) +#else +#define invalidate_cache_by_addr(__ptr__, __size__) +#define clean_cache_by_addr(__ptr__, __size__) +#endif +#endif + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific constants area. Include any such constants here! */ + +/* Define the number of descriptors and attached packets for transmit and receive operations. */ + +#ifndef NX_DRIVER_TX_DESCRIPTORS +#define NX_DRIVER_TX_DESCRIPTORS ETH_TX_DESC_CNT +#endif + +#ifndef NX_DRIVER_RX_DESCRIPTORS +#define NX_DRIVER_RX_DESCRIPTORS ETH_RX_DESC_CNT +#endif + +/****** DRIVER SPECIFIC ****** End of part/vendor specific constant area! */ + +#define NX_DRIVER_CAPABILITY ( NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_IPV4_RX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_TCP_RX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_UDP_RX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_ICMPV4_RX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_ICMPV6_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_ICMPV6_RX_CHECKSUM ) + + +/* Define basic Ethernet driver information typedef. Note that this typedefs is designed to be used only + in the driver's C file. */ + +typedef struct NX_DRIVER_INFORMATION_STRUCT +{ + /* NetX IP instance that this driver is attached to. */ + NX_IP *nx_driver_information_ip_ptr; + + /* Driver's current state. */ + ULONG nx_driver_information_state ; + + /* Packet pool used for receiving packets. */ + NX_PACKET_POOL *nx_driver_information_packet_pool_ptr; + + /* Define the driver interface association. */ + NX_INTERFACE *nx_driver_information_interface; + + /* Define the deferred event field. This will contain bits representing events + deferred from the ISR for processing in the thread context. */ + ULONG nx_driver_information_deferred_events; + + + /****** DRIVER SPECIFIC ****** Start of part/vendor specific driver information area. Include any such constants here! */ + + /* Indices to current receive/transmit descriptors. */ + UINT nx_driver_information_receive_current_index; + UINT nx_driver_information_transmit_current_index; + + /* Transmit release index. */ + UINT nx_driver_information_transmit_release_index; + + /* Define the number of transmit buffers in use. */ + UINT nx_driver_information_number_of_transmit_buffers_in_use; + + /* Define the association between buffer descriptors and NetX packets. */ + NX_PACKET *nx_driver_information_transmit_packets[NX_DRIVER_TX_DESCRIPTORS]; + NX_PACKET *nx_driver_information_receive_packets[NX_DRIVER_RX_DESCRIPTORS]; + + /* Define the size of a rx buffer size. */ + ULONG nx_driver_information_rx_buffer_size; + + ULONG nx_driver_information_multicast_count; + + /****** DRIVER SPECIFIC ****** End of part/vendor specific driver information area. */ + +} NX_DRIVER_INFORMATION; + +#endif + + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific external function prototypes. A typical NetX Ethernet driver + should expose its entry function as well as its interrupt handling function(s) here. All other + functions in the driver should have local scope, i.e., defined as static. */ + +/* Define global driver entry function. */ + +VOID nx_stm32_eth_driver(NX_IP_DRIVER *driver_req_ptr); + +/****** DRIVER SPECIFIC ****** End of part/vendor specific external function prototypes. */ + + +#ifdef __cplusplus +/* Yes, C++ compiler is present. Use standard C. */ + } +#endif +#endif /* NX_STM32_ETH_DRIVER_H */ diff --git a/common/stm32_drivers/ethernet/nx_stm32_phy_driver.h b/common/stm32_drivers/ethernet/nx_stm32_phy_driver.h new file mode 100644 index 00000000..2961e781 --- /dev/null +++ b/common/stm32_drivers/ethernet/nx_stm32_phy_driver.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +#ifndef NX_STM32_PHY_DRIVER_H +#define NX_STM32_PHY_DRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif +#include + + +#define ETH_PHY_STATUS_ERROR ((int32_t)-1) +#define ETH_PHY_STATUS_OK ((int32_t) 0) + +#define ETH_PHY_STATUS_LINK_ERROR ((int32_t) 0) +#define ETH_PHY_STATUS_LINK_DOWN ((int32_t) 1) + +#define ETH_PHY_STATUS_100MBITS_FULLDUPLEX ((int32_t) 2) +#define ETH_PHY_STATUS_100MBITS_HALFDUPLEX ((int32_t) 3) +#define ETH_PHY_STATUS_10MBITS_FULLDUPLEX ((int32_t) 4) +#define ETH_PHY_STATUS_10MBITS_HALFDUPLEX ((int32_t) 5) +#define ETH_PHY_STATUS_AUTONEGO_NOT_DONE ((int32_t) 6) +#if defined(ETH_PHY_1000MBITS_SUPPORTED) +#define ETH_PHY_STATUS_1000MBITS_FULLDUPLEX ((int32_t) 7) +#define ETH_PHY_STATUS_1000MBITS_HALFDUPLEX ((int32_t) 8) +#endif + +typedef void * nx_eth_phy_handle_t; + +int32_t nx_eth_phy_init(void); + +int32_t nx_eth_phy_get_link_state(void); + +int32_t nx_eth_phy_set_link_state(int32_t linkstate); + +nx_eth_phy_handle_t nx_eth_phy_get_handle(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/common/stm32_drivers/ethernet/rtl8211/nx_stm32_phy_driver.c b/common/stm32_drivers/ethernet/rtl8211/nx_stm32_phy_driver.c new file mode 100644 index 00000000..59b04b74 --- /dev/null +++ b/common/stm32_drivers/ethernet/rtl8211/nx_stm32_phy_driver.c @@ -0,0 +1,154 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +#include "nx_stm32_phy_driver.h" +#include "nx_stm32_eth_config.h" + + +/* RTL8211 IO functions */ +static int32_t rtl8211_io_init(void); +static int32_t rtl8211_io_deinit (void); + +static int32_t rtl8211_io_write_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal); +static int32_t rtl8211_io_read_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal); + +static int32_t rtl8211_io_get_tick(void); + +/* RTL8211 IO context object */ +static rtl8211_IOCtx_t RTL8211_IOCtx = { rtl8211_io_init, + rtl8211_io_deinit, + rtl8211_io_write_reg, + rtl8211_io_read_reg, + rtl8211_io_get_tick + }; +/* RTL8211 main object */ +static rtl8211_Object_t RTL8211; + +/** + * @brief Initialize the PHY interface + * @param none + * @retval ETH_PHY_STATUS_OK on success, ETH_PHY_STATUS_ERROR otherwise + */ + +int32_t nx_eth_phy_init(void) +{ + int32_t ret = ETH_PHY_STATUS_ERROR; + /* Set PHY IO functions */ + + RTL8211_RegisterBusIO(&RTL8211, &RTL8211_IOCtx); + /* Initialize the RTL8211 ETH PHY */ + + if (RTL8211_Init(&RTL8211) == RTL8211_STATUS_OK) + { + ret = ETH_PHY_STATUS_OK; + } + + return ret; +} + +/** + * @brief set the Phy link state. + * @param LinkState + * @retval the link status. + */ + +int32_t nx_eth_phy_set_link_state(int32_t LinkState) +{ + return (RTL8211_SetLinkState(&RTL8211, LinkState)); +} + +/** + * @brief get the Phy link state. + * @param none + * @retval the link status. + */ + +int32_t nx_eth_phy_get_link_state(void) +{ + int32_t linkstate = RTL8211_GetLinkState(&RTL8211); + + return linkstate; +} + +/** + * @brief get the driver object handle + * @param none + * @retval pointer to the RTL8211 main object + */ + +nx_eth_phy_handle_t nx_eth_phy_get_handle(void) +{ + return (nx_eth_phy_handle_t)&RTL8211; +} + +/** + * @brief Initialize the PHY MDIO interface + * @param None + * @retval 0 if OK, -1 if ERROR + */ + +int32_t rtl8211_io_init(void) +{ + /* We assume that MDIO GPIO configuration is already done + in the ETH_MspInit() else it should be done here + */ + + /* Configure the MDIO Clock */ + HAL_ETH_SetMDIOClockRange(ð_handle); + + return ETH_PHY_STATUS_OK; +} + +/** + * @brief De-Initialize the MDIO interface + * @param None + * @retval 0 if OK, -1 if ERROR + */ +int32_t rtl8211_io_deinit (void) +{ + return ETH_PHY_STATUS_OK; +} + +/** + * @brief Read a PHY register through the MDIO interface. + * @param DevAddr: PHY port address + * @param RegAddr: PHY register address + * @param pRegVal: pointer to hold the register value + * @retval 0 if OK -1 if Error + */ +int32_t rtl8211_io_read_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal) +{ + if(HAL_ETH_ReadPHYRegister(ð_handle, DevAddr, RegAddr, pRegVal) != HAL_OK) + { + return ETH_PHY_STATUS_ERROR; + } + + return ETH_PHY_STATUS_OK; +} + +int32_t rtl8211_io_write_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal) +{ + if(HAL_ETH_WritePHYRegister(ð_handle, DevAddr, RegAddr, RegVal) != HAL_OK) + { + return ETH_PHY_STATUS_ERROR; + } + + return ETH_PHY_STATUS_OK; +} + +/** + * @brief Get the time in millisecons used for internal PHY driver process. + * @retval Time value + */ +int32_t rtl8211_io_get_tick(void) +{ + return HAL_GetTick(); +} diff --git a/common/stm32_drivers/template/ethernet/nx_stm32_eth_config.h b/common/stm32_drivers/template/ethernet/nx_stm32_eth_config.h new file mode 100644 index 00000000..7d6ea16a --- /dev/null +++ b/common/stm32_drivers/template/ethernet/nx_stm32_eth_config.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#ifndef NX_STM32_ETH_CONFIG_H +#define NX_STM32_ETH_CONFIG_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32NNxx_hal.h" +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ + +/* This define enables the call of nx_eth_init() from the interface layer.*/ +/* #define NX_DRIVER_ETH_HW_IP_INIT */ + +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ + +extern ETH_HandleTypeDef heth; + +#ifdef NX_DRIVER_ETH_HW_IP_INIT +extern void MX_ETH_Init(void); +#endif /* #define NX_DRIVER_ETH_HW_IP_INIT */ + +#define eth_handle heth + +#ifdef NX_DRIVER_ETH_HW_IP_INIT +#define nx_eth_init MX_ETH_Init +#endif /* #define NX_DRIVER_ETH_HW_IP_INIT */ + +/* Add Phy Ethernet specific defines */ + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NX_STM32_ETH_CONFIG_H */ + diff --git a/common/stm32_drivers/template/ethernet/nx_stm32_phy_driver.c b/common/stm32_drivers/template/ethernet/nx_stm32_phy_driver.c new file mode 100644 index 00000000..731eb0ed --- /dev/null +++ b/common/stm32_drivers/template/ethernet/nx_stm32_phy_driver.c @@ -0,0 +1,92 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ +/* Private includes ----------------------------------------------------------*/ +#include "nx_stm32_phy_driver.h" +#include "nx_stm32_eth_config.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +int32_t nx_eth_phy_init(void) +{ + +/* USER CODE BEGIN PHY_INIT_0 */ + +/* USER CODE END PHY_INIT_0 */ + + + int32_t ret = ETH_PHY_STATUS_OK; + +/* USER CODE BEGIN PHY_INIT_1 */ + +/* USER CODE END PHY_INIT_1 */ + return ret; +} + +int32_t nx_eth_phy_get_link_state(void) +{ + + /* USER CODE BEGIN LINK_STATE_0 */ + + /* USER CODE END LINK_STATE_0 */ + + int32_t linkstate = ETH_PHY_STATUS_LINK_ERROR; + + + /* USER CODE BEGIN LINK_STATE_1 */ + + /* USER CODE END LINK_STATE_1 */ + return linkstate; +} + +nx_eth_phy_handle_t nx_eth_phy_get_handle(void) +{ + + nx_eth_phy_handle_t handle = NULL; + /* USER CODE BEGIN GET_HANDLE */ + + /* USER CODE END GET_HANDLE */ + return handle; +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/common/stm32_drivers/template/nx_custom_driver.c b/common/stm32_drivers/template/nx_custom_driver.c new file mode 100644 index 00000000..5de7135f --- /dev/null +++ b/common/stm32_drivers/template/nx_custom_driver.c @@ -0,0 +1,157 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ +/* Private includes ----------------------------------------------------------*/ +#include "nx_stm32_custom_driver.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +VOID nx_stm32_custom_driver(NX_IP_DRIVER *driver_req_ptr) +{ + + /* Process according to the driver request type in the IP control + block. */ + switch (driver_req_ptr -> nx_ip_driver_command) + { + + case NX_LINK_INTERFACE_ATTACH: + /* USER CODE BEGIN NX_LINK_INTERFACE_ATTACH */ + + /* USER CODE END NX_LINK_INTERFACE_ATTACH */ + break; + + case NX_LINK_INITIALIZE: + /* USER CODE BEGIN NX_LINK_INITIALIZE */ + + /* USER CODE END NX_LINK_INITIALIZE */ + break; + + case NX_LINK_ENABLE: + /* USER CODE BEGIN NX_LINK_ENABLE */ + + /* USER CODE END NX_LINK_ENABLE */ + break; + + case NX_LINK_DISABLE: + /* USER CODE BEGIN NX_LINK_DISABLE */ + + /* USER CODE END NX_LINK_DISABLE */ + break; + + case NX_LINK_ARP_SEND: + /* USER CODE BEGIN NX_LINK_ARP_SEND */ + + /* USER CODE END NX_LINK_ARP_SEND */ + break; + + case NX_LINK_ARP_RESPONSE_SEND: + /* USER CODE BEGIN NX_LINK_ARP_RESPONSE_SEND */ + + /* USER CODE END NX_LINK_ARP_RESPONSE_SEND */ + break; + + case NX_LINK_PACKET_BROADCAST: + /* USER CODE BEGIN NX_LINK_PACKET_BROADCAST */ + + /* USER CODE END NX_LINK_PACKET_BROADCAST */ + break; + + case NX_LINK_RARP_SEND: + /* USER CODE BEGIN NX_LINK_RARP_SEND */ + + /* USER CODE END NX_LINK_RARP_SEND */ + break; + + case NX_LINK_PACKET_SEND: + /* USER CODE BEGIN NX_LINK_PACKET_SEND */ + + /* USER CODE END NX_LINK_PACKET_SEND */ + break; + + case NX_LINK_MULTICAST_JOIN: + /* USER CODE BEGIN NX_LINK_MULTICAST_JOIN */ + + /* USER CODE END NX_LINK_MULTICAST_JOIN */ + break; + + case NX_LINK_MULTICAST_LEAVE: + /* USER CODE BEGIN NX_LINK_MULTICAST_LEAVE */ + + /* USER CODE END NX_LINK_MULTICAST_LEAVE */ + break; + + case NX_LINK_GET_STATUS: + /* USER CODE BEGIN NX_LINK_GET_STATUS */ + + /* USER CODE END NX_LINK_GET_STATUS */ + break; + + case NX_LINK_DEFERRED_PROCESSING: + /* USER CODE BEGIN NX_LINK_DEFERRED_PROCESSING */ + + /* USER CODE END NX_LINK_DEFERRED_PROCESSING */ + break; + + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + case NX_INTERFACE_CAPABILITY_GET: + /* USER CODE BEGIN NX_INTERFACE_CAPABILITY_GET */ + + /* USER CODE END NX_INTERFACE_CAPABILITY_GET */ + break; + + case NX_INTERFACE_CAPABILITY_SET: + /* USER CODE BEGIN NX_INTERFACE_CAPABILITY_SET */ + + /* USER CODE END NX_INTERFACE_CAPABILITY_SET */ + break; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + default: + /* USER CODE BEGIN DEFAULT */ + + /* USER CODE END DEFAULT */ + break; + } +} + +/* USER CODE BEGIN 2 */ + +/* USER CODE END 2 */ diff --git a/common/stm32_drivers/template/nx_custom_driver.h b/common/stm32_drivers/template/nx_custom_driver.h new file mode 100644 index 00000000..a3c7fd90 --- /dev/null +++ b/common/stm32_drivers/template/nx_custom_driver.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#ifndef NX_STM32_CUSTOM_DRIVER_H +#define NX_STM32_CUSTOM_DRIVER_H + + +#ifdef __cplusplus + +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "nx_api.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +/* Define global driver entry function. */ + +VOID nx_stm32_custom_driver(NX_IP_DRIVER *driver_req_ptr); + + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +#ifdef __cplusplus + } +#endif +#endif /* NX_STM32_CUSTOM_DRIVER_H */ diff --git a/common/stm32_drivers/template/wifi/mxchip/mx_wifi_azure_rtos_conf.h b/common/stm32_drivers/template/wifi/mxchip/mx_wifi_azure_rtos_conf.h new file mode 100644 index 00000000..81ee43db --- /dev/null +++ b/common/stm32_drivers/template/wifi/mxchip/mx_wifi_azure_rtos_conf.h @@ -0,0 +1,120 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef MX_WIFI_AZURE_RTOS_CONF_H +#define MX_WIFI_AZURE_RTOS_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#if (MX_WIFI_USE_CMSIS_OS != 0) +#error The NetXDuo wifi driver does not support CMSIS OS +#endif + +#include +#include + +#include "tx_api.h" +#include "nx_api.h" + +UINT mx_wifi_alloc_init(); +void * mx_wifi_malloc(size_t size); +void mx_wifi_free(void * p); + +#define MX_WIFI_MALLOC(size) mx_wifi_malloc(size) +#define MX_WIFI_FREE(p) mx_wifi_free(p) + +#define NET_MALLOC(size) mx_wifi_malloc(size) +#define NET_FREE(p) mx_wifi_free(p) + + +typedef NX_PACKET mx_buf_t; + +NX_PACKET *mx_net_buffer_alloc(uint32_t n); +void mx_net_buffer_free(NX_PACKET *nx_packet); + +#define MX_NET_BUFFER_ALLOC mx_net_buffer_alloc +#define MX_NET_BUFFER_FREE mx_net_buffer_free +#define MX_NET_BUFFER_PAYLOAD(packet_ptr) packet_ptr->nx_packet_prepend_ptr +#define MX_NET_BUFFER_SET_PAYLOAD_SIZE(packet_ptr,n) \ + do { \ + packet_ptr->nx_packet_length = n; \ + packet_ptr->nx_packet_append_ptr = \ + packet_ptr->nx_packet_prepend_ptr + n; \ + } while (0) +#define MX_NET_BUFFER_GET_PAYLOAD_SIZE(packet_ptr) packet_ptr->nx_packet_length +#define MX_NET_BUFFER_HIDE_HEADER(packet_ptr,n) \ + do { \ + packet_ptr->nx_packet_prepend_ptr += n; \ + packet_ptr->nx_packet_length -=n ; \ + } while (0) + +#define DELAYms(n) \ + do { \ + if (n == 1) { \ + tx_thread_relinquish(); \ + } else { \ + tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND * n / 1000); \ + } \ + } while(0) + +#define MX_ASSERT(a) do {} while(!(a)) + +#define LOCK_DECLARE(A) TX_MUTEX A +#define LOCK_INIT(A) tx_mutex_create(&A, #A, TX_NO_INHERIT) +#define LOCK_DEINIT(A) tx_mutex_delete(&A) +#define LOCK(A) tx_mutex_get(&A, TX_WAIT_FOREVER) +#define UNLOCK(A) tx_mutex_put(&A) + +#define SEM_DECLARE(A) TX_SEMAPHORE A +#define SEM_INIT(A,COUNT) tx_semaphore_create(&A, #A, 0) +#define SEM_DEINIT(A) tx_semaphore_delete(&A) +#define SEM_SIGNAL(A) tx_semaphore_put(&A) +#define SEM_WAIT(A,TIMEOUT,IDLE_FUNC) tx_semaphore_get(&A, TIMEOUT) + +UINT mx_wifi_thread_init(TX_THREAD * thread_ptr, CHAR *name_ptr, VOID (*entry_function)(ULONG), ULONG entry_input, ULONG stack_size, UINT priority); +UINT mx_wifi_thread_deinit(TX_THREAD * thread_ptr); +void mx_wifi_thread_terminate(); + +#define THREAD_CONTEXT_TYPE ULONG + +#define OSPRIORITYNORMAL 5 +#define OSPRIORITYABOVENORMAL 4 +#define OSPRIORITYREALTIME 1 + +#define THREAD_DECLARE(A) TX_THREAD A +#define THREAD_INIT(A,THREAD_FUNC,THREAD_CONTEXT,STACKSIZE,PRIORITY) \ + mx_wifi_thread_init(&A, #A, (VOID (*)(ULONG)) THREAD_FUNC, (ULONG) THREAD_CONTEXT, STACKSIZE, PRIORITY) +#define THREAD_DEINIT(A) mx_wifi_thread_deinit(&A) +#define THREAD_TERMINATE() mx_wifi_thread_terminate() + +UINT mx_wifi_fifo_init(TX_QUEUE * queue_ptr, char * name_ptr, ULONG size); +UINT mx_wifi_fifo_deinit(TX_QUEUE * queue_ptr); +UINT mx_wifi_fifo_push(TX_QUEUE * queue_ptr, void * source_ptr, ULONG wait_option); +void * mx_wifi_fifo_pop(TX_QUEUE * queue_ptr, ULONG wait_option); + +#define FIFO_DECLARE(QUEUE) TX_QUEUE QUEUE +#define FIFO_INIT(QUEUE,QSIZE) mx_wifi_fifo_init(&QUEUE, #QUEUE, QSIZE) +#define FIFO_DEINIT(QUEUE) mx_wifi_fifo_deinit(&QUEUE) +#define FIFO_PUSH(QUEUE,VALUE,TIMEOUT,IDLE_FUNC) mx_wifi_fifo_push(&QUEUE,&VALUE,TIMEOUT) +#define FIFO_POP(QUEUE,TIMEOUT,IDLE_FUNC) mx_wifi_fifo_pop(&QUEUE,TIMEOUT) + +#define WAIT_FOREVER TX_WAIT_FOREVER +#define SEM_OK TX_SUCCESS +#define THREAD_OK TX_SUCCESS +#define FIFO_OK TX_SUCCESS + +#ifdef __cplusplus +} +#endif + +#endif /* MX_WIFI_AZURE_RTOS_CONF_H */ diff --git a/common/stm32_drivers/wifi/cypress/nx_driver_framework.c b/common/stm32_drivers/wifi/cypress/nx_driver_framework.c new file mode 100644 index 00000000..d12922c9 --- /dev/null +++ b/common/stm32_drivers/wifi/cypress/nx_driver_framework.c @@ -0,0 +1,1578 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** NetX driver framework */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#include + +/* Check that this file is included by the driver source and not compiled directly */ +#ifndef NX_DRIVER_SOURCE +#error This file is included by the driver source, not compiled directly. +#endif /* NX_DRIVER_SOURCE */ + +/* Include driver framework include file. */ +#include "nx_driver_framework.h" + +NX_DRIVER_INFORMATION nx_driver_information; + +static VOID nx_driver_framework_entry_default(NX_IP_DRIVER *driver_req_ptr); + +/* Define the routines for processing each driver entry request. */ +static VOID nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_enable(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_disable(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr); +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +static VOID nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr); +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ +#ifdef NX_DRIVER_ENABLE_DEFERRED +static VOID nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr); +#endif /* NX_DRIVER_ENABLE_DEFERRED */ +static VOID nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr); + +#if 0 /* Make the function available outside of this unit. */ +static VOID nx_driver_update_hardware_address(UCHAR hardware_address[6]); +#endif /*0*/ + +#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE +static VOID nx_driver_transmit_packet_enqueue(NX_PACKET *packet_ptr) +static NX_PACKET *nx_driver_transmit_packet_dequeue(VOID) +#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */ + + +/* Define the pointers for the hardware implementation of this driver. */ +static UINT(*nx_driver_hardware_initialize)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_enable)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_disable)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_packet_send)(NX_PACKET *packet_ptr) = NULL; +static UINT(*nx_driver_hardware_multicast_join)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_multicast_leave)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_get_status)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static VOID(*nx_driver_hardware_packet_transmitted)(VOID) = NULL; +static VOID(*nx_driver_hardware_packet_received)(VOID) = NULL; + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +static UINT(*nx_driver_hardware_capability_set)(NX_IP_DRIVER *driver_req_ptr) = NULL; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + + +#if !defined(REMOVE_DEBUG_FUNC) +static const char *nx_driver_operation_to_string(UINT operation); +#endif /* REMOVE_DEBUG_FUNC */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_framework_entry_default PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This is the default entry point processing for the NetX Driver. */ +/* This function should be called by a specific driver to handle */ +/* commands. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr The driver request from the */ +/* IP layer. */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_interface_attach Process attach request */ +/* nx_driver_initialize Process initialize request */ +/* nx_driver_enable Process link enable request */ +/* nx_driver_disable Process link disable request */ +/* nx_driver_packet_send Process send packet requests */ +/* nx_driver_multicast_join Process multicast join request*/ +/* nx_driver_multicast_leave Process multicast leave req */ +/* nx_driver_get_status Process get status request */ +/* nx_driver_deferred_processing Drive deferred processing */ +/* */ +/* CALLED BY */ +/* */ +/* IP layer */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_framework_entry_default(NX_IP_DRIVER *driver_req_ptr) +{ + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] > %s\n", HAL_GetTick(), + nx_driver_operation_to_string(driver_req_ptr -> nx_ip_driver_command)); + + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Process according to the driver request type in the IP control block. */ + switch (driver_req_ptr -> nx_ip_driver_command) + { + + case NX_LINK_INTERFACE_ATTACH: + { + /* Process link interface attach requests. */ + nx_driver_interface_attach(driver_req_ptr); + break; + } + + case NX_LINK_INITIALIZE: + { + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Initialization - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + NX_DEBUG_DRIVER_SOURCE_LOG(" IP Address = %08" PRIX32 "\n", + (uint32_t)driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_address); + + /* Process link initialize requests. */ + nx_driver_initialize(driver_req_ptr); + break; + } + + case NX_LINK_ENABLE: + { + /* Process link enable requests. */ + nx_driver_enable(driver_req_ptr); + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Link Enabled - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + break; + } + + case NX_LINK_DISABLE: + { + /* Process link disable requests. */ + nx_driver_disable(driver_req_ptr); + + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Link Disabled - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + break; + } + + case NX_LINK_ARP_SEND: + case NX_LINK_ARP_RESPONSE_SEND: + case NX_LINK_PACKET_BROADCAST: + case NX_LINK_RARP_SEND: + case NX_LINK_PACKET_SEND: + { + /* Process packet send requests. */ + nx_driver_packet_send(driver_req_ptr); + break; + } + + case NX_LINK_MULTICAST_JOIN: + { + /* Process multicast join requests. */ + nx_driver_multicast_join(driver_req_ptr); + break; + } + + case NX_LINK_MULTICAST_LEAVE: + { + /* Process multicast leave requests. */ + nx_driver_multicast_leave(driver_req_ptr); + break; + } + + case NX_LINK_GET_STATUS: + { + /* Process get status requests. */ + nx_driver_get_status(driver_req_ptr); + break; + } + +#ifdef NX_DRIVER_ENABLE_DEFERRED + case NX_LINK_DEFERRED_PROCESSING: + { + /* Process driver deferred requests. */ + + /* Process a device driver function on behave of the IP thread. */ + nx_driver_deferred_processing(driver_req_ptr); + break; + } +#endif /* NX_DRIVER_ENABLE_DEFERRED */ + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + case NX_INTERFACE_CAPABILITY_GET: + { + /* Process get capability requests. */ + nx_driver_capability_get(driver_req_ptr); + break; + } + + case NX_INTERFACE_CAPABILITY_SET: + { + /* Process set capability requests. */ + nx_driver_capability_set(driver_req_ptr); + break; + } +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + default: + + /* Invalid driver request. */ + + /* Return the unhandled command status. */ + driver_req_ptr -> nx_ip_driver_status = NX_UNHANDLED_COMMAND; + + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Received invalid request - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_interface_attach PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the interface attach request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr) +{ + /** + * Setup the driver's interface. + * This default implementation is for a simple one-interface driver. + * Additional logic is necessary for multiple port devices. + */ + nx_driver_information.nx_driver_information_interface = driver_req_ptr -> nx_ip_driver_interface; + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + driver_req_ptr -> nx_ip_driver_interface -> nx_interface_capability_flag = NX_DRIVER_CAPABILITY; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + /* Return successful status. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_initialize PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the initialize request. The processing */ +/* in this function is generic. All hardware specific logic goes in */ +/* nx_driver_hardware_initialize. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_initialize Process initialize request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr) +{ + NX_IP *ip_ptr; + NX_INTERFACE *interface_ptr; + UINT status; + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Setup interface pointer. */ + interface_ptr = driver_req_ptr -> nx_ip_driver_interface; + + /* Initialize the driver's information structure. */ + + /* Default IP pointer to NULL. */ + nx_driver_information.nx_driver_information_ip_ptr = NX_NULL; + + /* Setup the driver state to not initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_NOT_INITIALIZED; + + /* Setup the default packet pool for the driver's received packets. */ + nx_driver_information.nx_driver_information_packet_pool_ptr = ip_ptr -> nx_ip_default_packet_pool; + + /* Clear the deferred events for the driver. */ + nx_driver_information.nx_driver_information_deferred_events = 0; + +#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE + /* Clear the transmit queue count and head pointer. */ + nx_driver_information.nx_driver_transmit_packets_queued = 0; + nx_driver_information.nx_driver_transmit_queue_head = NX_NULL; + nx_driver_information.nx_driver_transmit_queue_tail = NX_NULL; +#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */ + + /* Call the hardware-specific WiFi module initialization. */ + if (!nx_driver_hardware_initialize) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_initialize(driver_req_ptr); + } + + /* Determine if the request was successful. */ + if (status == NX_SUCCESS) + { + /* Successful hardware initialization. */ + + /* Setup driver information to point to IP pointer. */ + nx_driver_information.nx_driver_information_ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Setup the link maximum transfer unit. */ + interface_ptr -> nx_interface_ip_mtu_size = NX_DRIVER_MTU - NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Indicate to the IP software that IP to physical mapping + is required. */ + interface_ptr -> nx_interface_address_mapping_needed = NX_TRUE; + + /* Move the driver's state to initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED; + + /* Indicate successful initialize. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + /* Initialization failed. Indicate that the request failed. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_enable PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the initialize request. The processing */ +/* in this function is generic. All hardware specific logic in */ +/* nx_driver_hardware_enable. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_enable Process enable request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_enable(NX_IP_DRIVER *driver_req_ptr) +{ + NX_IP *ip_ptr; + UINT status; + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* See if we can honor the NX_LINK_ENABLE request. */ + if (nx_driver_information.nx_driver_information_state < NX_DRIVER_STATE_INITIALIZED) + { + /* Mark the request as not successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + + /* Check if it is enabled by someone already */ + if (nx_driver_information.nx_driver_information_state >= NX_DRIVER_STATE_LINK_ENABLED) + { + /* Yes, the request has already been made. */ + driver_req_ptr -> nx_ip_driver_status = NX_ALREADY_ENABLED; + return; + } + + /* Call hardware specific enable. */ + if (!nx_driver_hardware_enable) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_enable(driver_req_ptr); + } + + /* Was the hardware enable successful? */ + if (status == NX_SUCCESS) + { + /* Update the driver state to link enabled. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_LINK_ENABLED; + + /* Mark request as successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Mark the IP instance as link up. */ + ip_ptr -> nx_ip_driver_link_up = NX_TRUE; + } + else + { + /* Enable failed. Indicate that the request failed. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_disable PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the disable request. The processing */ +/* in this function is generic. All hardware specific logic in */ +/* nx_driver_hardware_disable. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_disable Process disable request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_disable(NX_IP_DRIVER *driver_req_ptr) +{ + NX_IP *ip_ptr; + UINT status; + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Check if the link is enabled. */ + if (nx_driver_information.nx_driver_information_state != NX_DRIVER_STATE_LINK_ENABLED) + { + /* The link is not enabled, so just return an error. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + + /* Call hardware specific disable. */ + if (!nx_driver_hardware_disable) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_disable(driver_req_ptr); + } + + /* Was the hardware disable successful? */ + if (status == NX_SUCCESS) + { + /* Mark the IP instance as link down. */ + ip_ptr -> nx_ip_driver_link_up = NX_FALSE; + + /* Update the driver state back to initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED; + + /* Mark request as successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + /* Disable failed, return an error. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_packet_send PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the packet send request. The processing */ +/* in this function is generic. All hardware specific logic is in */ +/* nx_driver_hardware_packet_send. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_packet_send Process packet send request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr) +{ + NX_IP *ip_ptr; + NX_PACKET *packet_ptr; + ULONG *ethernet_frame_ptr; + UINT status; + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Check to make sure the link is up. */ + if (nx_driver_information.nx_driver_information_state != NX_DRIVER_STATE_LINK_ENABLED) + { + /* Indicate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(driver_req_ptr -> nx_ip_driver_packet); + return; + } + + /* Process driver send packet. */ + + /* Place the Ethernet frame at the front of the packet. */ + packet_ptr = driver_req_ptr -> nx_ip_driver_packet; + + + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] nx_driver_packet_send() with 0x%" PRIX32 " bytes\n", + HAL_GetTick(), (uint32_t)packet_ptr -> nx_packet_length); + + + /* Adjust the prepend pointer. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr - NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /** + * Setup the ethernet frame pointer to build the ethernet frame. + * Backup another 2 * bytes to get 32-bit word alignment. + */ + ethernet_frame_ptr = (ULONG *)(packet_ptr -> nx_packet_prepend_ptr - 2); + + /* Set up the hardware addresses in the Ethernet header. */ + *ethernet_frame_ptr = driver_req_ptr -> nx_ip_driver_physical_address_msw; + *(ethernet_frame_ptr + 1) = driver_req_ptr -> nx_ip_driver_physical_address_lsw; + + *(ethernet_frame_ptr + 2) = (ip_ptr -> nx_ip_arp_physical_address_msw << 16) | + (ip_ptr -> nx_ip_arp_physical_address_lsw >> 16); + *(ethernet_frame_ptr + 3) = (ip_ptr -> nx_ip_arp_physical_address_lsw << 16); + + /* Set up the frame type field in the Ethernet header. */ + if ((driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_SEND) || + (driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_RESPONSE_SEND)) + { + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_ARP; + } + else if (driver_req_ptr -> nx_ip_driver_command == NX_LINK_RARP_SEND) + { + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_RARP; + } +#ifdef FEATURE_NX_IPV6 + else if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6) + { + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_IPV6; + } +#endif /* FEATURE_NX_IPV6 */ + else + { + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_IP; + } + + /* Endian swapping if NX_LITTLE_ENDIAN is defined. */ + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 1)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 2)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 3)); + + /* Determine if the packet exceeds the driver's MTU. */ + if (packet_ptr -> nx_packet_length > NX_DRIVER_MTU) + { + /* This packet exceeds the size of the driver's MTU. Simply throw it away! */ + + /* Remove the Ethernet header. */ + NX_DRIVER_PHYSICAL_HEADER_REMOVE(packet_ptr); + + /* Indicate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(packet_ptr); + return; + } + + /* Transmit the packet through the WiFi controller low level access routine. */ + if (!nx_driver_hardware_packet_send) + { + status = NX_DRIVER_ERROR; + } + else + { + NX_DEBUG_DRIVER_SOURCE_LOG("\n* %" PRIX32 " %" PRIX32 " %" PRIX32 " %" PRIX32 " *\n", + (uint32_t)ethernet_frame_ptr[0], (uint32_t)ethernet_frame_ptr[1], + (uint32_t)ethernet_frame_ptr[2], (uint32_t)ethernet_frame_ptr[3]); + + + status = nx_driver_hardware_packet_send(packet_ptr); + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + /* Driver's hardware send packet routine failed to send the packet. */ + + /* Remove the Ethernet header. */ + NX_DRIVER_PHYSICAL_HEADER_REMOVE(packet_ptr); + + /* Indicate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(packet_ptr); + } + else + { + /* Set the status of the request. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_multicast_join PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the multicast join request. The processing */ +/* in this function is generic. All hardware specific logic is in */ +/* nx_driver_hardware_multicast_join. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_multicast_join Process multicast join request*/ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + + /* Call hardware specific multicast join function. */ + if (!nx_driver_hardware_multicast_join) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_multicast_join(driver_req_ptr); + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver multicast join returns: NX_DRIVER_ERROR\n"); + /* Call hardware specific multicast join function. */ + } + else + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_multicast_leave PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the multicast leave request. The code */ +/* in this function is generic. All hardware specific logic is in */ +/* nx_driver_hardware_multicast_leave. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_multicast_leave Process multicast leave req */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + + /* Call hardware specific multicast leave function. */ + if (!nx_driver_hardware_multicast_leave) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_multicast_leave(driver_req_ptr); + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver multicast leave returns: NX_DRIVER_ERROR\n"); + } + else + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_get_status PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the get status request. The processing */ +/* in this function is generic. All hardware specific logic is in */ +/* nx_driver_hardware_get_status. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_get_status Process get status request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr) +{ + /* Call hardware specific get status function. */ + if (!nx_driver_hardware_get_status) + { + driver_req_ptr -> nx_ip_driver_status = NX_UNHANDLED_COMMAND; + } + else + { + UINT status = nx_driver_hardware_get_status(driver_req_ptr); + + if (status == NX_SUCCESS) + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + } +} + + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_capability_get PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the get capability request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr) +{ + /* Return the capability of the WiFi controller. */ + *(driver_req_ptr -> nx_ip_driver_return_ptr) = NX_DRIVER_CAPABILITY; + + /* Return the success status. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_capability_set PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the set capability request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + + /* Call hardware specific get status function. */ + if (!nx_driver_hardware_capability_set) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_capability_set(driver_req_ptr); + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + else + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + +#ifdef NX_DRIVER_ENABLE_DEFERRED +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_deferred_processing PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the deferred ISR action within the context */ +/* of the IP thread. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_packet_transmitted Clean up after transmission */ +/* nx_driver_packet_received Process a received packet */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr) +{ + TX_INTERRUPT_SAVE_AREA + + ULONG deferred_events; + + /* Disable interrupts. */ + TX_DISABLE + + /* Pickup deferred events. */ + deferred_events = nx_driver_information.nx_driver_information_deferred_events; + nx_driver_information.nx_driver_information_deferred_events = 0; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for a transmit complete event. */ + if (deferred_events & NX_DRIVER_DEFERRED_PACKET_TRANSMITTED) + { + /* Process transmitted packet(s). */ + if (nx_driver_hardware_packet_transmitted) + { + nx_driver_hardware_packet_transmitted(); + } + } + + /* Check for received packet. */ + if (deferred_events & NX_DRIVER_DEFERRED_PACKET_RECEIVED) + { + /* Process received packet(s). */ + if (nx_driver_hardware_packet_received) + { + nx_driver_hardware_packet_received(); + } + } + + /* Mark request as successful. */ + driver_req_ptr->nx_ip_driver_status = NX_SUCCESS; +} +#endif /* NX_DRIVER_ENABLE_DEFERRED */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_transfer_to_netx PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing incoming packets. This routine would */ +/* be called from the driver-specific receive packet processing */ +/* function nx_driver_hardware_packet_received. */ +/* */ +/* INPUT */ +/* */ +/* ip_ptr Pointer to IP protocol block */ +/* packet_ptr Packet pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Error indication */ +/* */ +/* CALLS */ +/* */ +/* _nx_ip_packet_receive NetX IP packet receive */ +/* _nx_ip_packet_deferred_receive NetX IP packet receive */ +/* _nx_arp_packet_deferred_receive NetX ARP packet receive */ +/* _nx_rarp_packet_deferred_receive NetX RARP packet receive */ +/* _nx_packet_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* nx_driver_hardware_packet_received Driver packet receive function*/ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr) +{ + /* Pickup the packet header to determine where the packet needs to be sent. */ + const USHORT packet_type = (USHORT)((USHORT)(((USHORT)(*(packet_ptr -> nx_packet_prepend_ptr + 12))) << 8) | + (USHORT)(*(packet_ptr -> nx_packet_prepend_ptr + 13))); + + /* NX_DEBUG_DRIVER_SOURCE_LOG("\n%s() 0x%" PRIx32 "\n", __FUNCTION__, (uint32_t)packet_type); */ + + /* Set the interface for the incoming packet. */ + packet_ptr -> nx_packet_ip_interface = nx_driver_information.nx_driver_information_interface; + + /* Route the incoming packet according to its Ethernet type. */ + if ((packet_type == NX_DRIVER_ETHERNET_IP) || (packet_type == NX_DRIVER_ETHERNET_IPV6)) + { + /* Note: The length reported by some Ethernet hardware includes + bytes after the packet as well as the Ethernet header. In some + cases, the actual packet length after the Ethernet header should + be derived from the length in the IP header (lower 16 bits of + the first 32-bit word). */ + + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = + packet_ptr -> nx_packet_length - NX_DRIVER_PHYSICAL_FRAME_SIZE; + + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] < NX_DRIVER_ETHERNET_IP(V6) with (%p) %" PRIu32 " bytes\n", + HAL_GetTick(), (void *)packet_ptr, (uint32_t)packet_ptr -> nx_packet_length); + +#ifdef NX_DEBUG + { + const ULONG ip_tcp_headers_size = 40; + for (ULONG i = ip_tcp_headers_size ; i < (packet_ptr -> nx_packet_length - ip_tcp_headers_size); i++) + { + NX_DEBUG_DRIVER_SOURCE_LOG("%02X", packet_ptr -> nx_packet_prepend_ptr[i]); + } + } +#endif /* NX_DEBUG */ + + /* Route to the ip receive function. */ +#ifdef NX_DRIVER_ENABLE_DEFERRED + _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr); +#else + _nx_ip_packet_receive(ip_ptr, packet_ptr); +#endif /* NX_DRIVER_ENABLE_DEFERRED */ + } + else if (packet_type == NX_DRIVER_ETHERNET_ARP) + { + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = + packet_ptr -> nx_packet_length - NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Route to the ARP receive function. */ + _nx_arp_packet_deferred_receive(ip_ptr, packet_ptr); + } + else if (packet_type == NX_DRIVER_ETHERNET_RARP) + { + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = + packet_ptr -> nx_packet_length - NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Route to the RARP receive function. */ + _nx_rarp_packet_deferred_receive(ip_ptr, packet_ptr); + } + else + { + /* Invalid Ethernet header... release the packet. */ + nx_packet_release(packet_ptr); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_update_hardware_address PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function updates the hardware address kept by the driver. */ +/* The hardware address is used when constructing send packets and to */ +/* filter incoming packets. */ +/* */ +/* INPUT */ +/* */ +/* hardware_address The new hardware address */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* nx_driver_initialize Driver initialization function*/ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_update_hardware_address(UCHAR hardware_address[6]) +{ + NX_INTERFACE *interface_ptr; + + /* Setup interface pointer. */ + interface_ptr = nx_driver_information.nx_driver_information_interface; + + /** + * Setup the physical address of this IP instance. Increment the + * physical address lsw to simulate multiple nodes hanging on the + * Ethernet. + */ + interface_ptr -> nx_interface_physical_address_msw = + ((ULONG)(((ULONG)hardware_address[0]) << 8)) | + ((ULONG)hardware_address[1]); + interface_ptr -> nx_interface_physical_address_lsw = + ((ULONG)(((ULONG)hardware_address[2]) << 24)) | + ((ULONG)((ULONG)(hardware_address[3]) << 16)) | + ((ULONG)((ULONG)(hardware_address[4]) << 8)) | + ((ULONG)hardware_address[5]); +} + + +#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_transmit_packet_enqueue PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function queues a transmit packet when the hardware transmit */ +/* queue does not have the resources (buffer descriptors, etc.) to */ +/* send the packet. The queue is maintained as a singularly linked- */ +/* list with head and tail pointers. The maximum number of packets on */ +/* the transmit queue is regulated by the constant */ +/* NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH. When this number is exceeded, */ +/* the oldest packet is discarded after the new packet is queued. */ +/* */ +/* Note: that it is assumed further driver interrupts are locked out */ +/* during the call to this driver utility. */ +/* */ +/* INPUT */ +/* */ +/* packet_ptr Packet pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_packet_transmit_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* nx_driver_hardware_packet_send Driver packet send function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_transmit_packet_enqueue(NX_PACKET *packet_ptr) +{ + /* Determine if there is anything on the queue. */ + if (nx_driver_information.nx_driver_transmit_queue_tail) + { + /* Yes, something is on the transmit queue. Simply add the new packet to the tail. */ + nx_driver_information.nx_driver_transmit_queue_tail -> nx_packet_queue_next = packet_ptr; + + /* Update the tail pointer. */ + nx_driver_information.nx_driver_transmit_queue_tail = packet_ptr; + } + else + { + /* First packet on the transmit queue. */ + + /* Setup head pointers. */ + nx_driver_information.nx_driver_transmit_queue_head = packet_ptr; + nx_driver_information.nx_driver_transmit_queue_tail = packet_ptr; + + /* Set the packet's next pointer to NULL. */ + packet_ptr -> nx_packet_queue_next = NX_NULL; + } + + /* Increment the total packets queued. */ + nx_driver_information.nx_driver_transmit_packets_queued++; + + /* Determine if the total packet queued exceeds the driver's maximum transmit + queue depth. */ + if (nx_driver_information.nx_driver_transmit_packets_queued > NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH) + { + /* Yes, remove the head packet (oldest) packet in the transmit queue and release it. */ + packet_ptr = nx_driver_information.nx_driver_transmit_queue_head; + + /* Adjust the head pointer to the next packet. */ + nx_driver_information.nx_driver_transmit_queue_head = packet_ptr -> nx_packet_queue_next; + + /* Decrement the transmit packet queued count. */ + nx_driver_information.nx_driver_transmit_packets_queued--; + + /* Remove the Ethernet header. */ + NX_DRIVER_PHYSICAL_HEADER_REMOVE(packet_ptr); + + /* Release the packet. */ + nx_packet_transmit_release(packet_ptr); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_transmit_packet_dequeue PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function removes the oldest transmit packet when the hardware */ +/* transmit queue has new resources (usually after a transmit complete */ +/* interrupt) to send the packet. If there are no packets in the */ +/* transmit queue, a NULL is returned. */ +/* */ +/* Note: that it is assumed further driver interrupts are locked out */ +/* during the call to this driver utility. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* packet_ptr Packet pointer */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* nx_driver_hardware_packet_send Driver packet send function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static NX_PACKET *nx_driver_transmit_packet_dequeue(VOID) +{ + NX_PACKET *packet_ptr; + + /* Pickup the head pointer of the transmit packet queue. */ + packet_ptr = nx_driver_information.nx_driver_transmit_queue_head; + + /* Determine if there is anything on the queue. */ + if (packet_ptr) + { + /* Yes, something is on the transmit queue. Simply the packet from the head of the queue. */ + + /* Update the head pointer. */ + nx_driver_information.nx_driver_transmit_queue_head = packet_ptr -> nx_packet_queue_next; + + /* Clear the next pointer in the packet. */ + packet_ptr -> nx_packet_queue_next = NX_NULL; + + /* Decrement the transmit packet queued count. */ + nx_driver_information.nx_driver_transmit_packets_queued--; + } + + /* Return the packet pointer - NULL if there are no packets queued. */ + return (packet_ptr); +} +#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */ + +#if !defined(REMOVE_DEBUG_FUNC) +#define CASE(x) case x: return #x +#define DEFAULT default: return "UNKNOWN" +static const char *nx_driver_operation_to_string(UINT operation) +{ + switch (operation) + { + CASE(NX_LINK_PACKET_SEND); + CASE(NX_LINK_INITIALIZE); + CASE(NX_LINK_ENABLE); + CASE(NX_LINK_DISABLE); + CASE(NX_LINK_PACKET_BROADCAST); + CASE(NX_LINK_ARP_SEND); + CASE(NX_LINK_ARP_RESPONSE_SEND); + CASE(NX_LINK_RARP_SEND); + CASE(NX_LINK_MULTICAST_JOIN); + CASE(NX_LINK_MULTICAST_LEAVE); + CASE(NX_LINK_GET_STATUS); + CASE(NX_LINK_GET_SPEED); + CASE(NX_LINK_GET_DUPLEX_TYPE); + CASE(NX_LINK_GET_ERROR_COUNT); + CASE(NX_LINK_GET_RX_COUNT); + CASE(NX_LINK_GET_TX_COUNT); + CASE(NX_LINK_GET_ALLOC_ERRORS); + CASE(NX_LINK_UNINITIALIZE); + CASE(NX_LINK_DEFERRED_PROCESSING); + CASE(NX_LINK_INTERFACE_ATTACH); + CASE(NX_LINK_SET_PHYSICAL_ADDRESS); + CASE(NX_INTERFACE_CAPABILITY_GET); + CASE(NX_INTERFACE_CAPABILITY_SET); + CASE(NX_LINK_INTERFACE_DETACH); + CASE(NX_LINK_FACTORY_ADDRESS_GET); + CASE(NX_LINK_RX_ENABLE); + CASE(NX_LINK_RX_DISABLE); + CASE(NX_LINK_6LOWPAN_COMMAND); + CASE(NX_LINK_GET_INTERFACE_TYPE); + + DEFAULT; + } +} +#endif /* REMOVE_DEBUG_FUNC */ diff --git a/common/stm32_drivers/wifi/cypress/nx_driver_framework.h b/common/stm32_drivers/wifi/cypress/nx_driver_framework.h new file mode 100644 index 00000000..dd9f7978 --- /dev/null +++ b/common/stm32_drivers/wifi/cypress/nx_driver_framework.h @@ -0,0 +1,151 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** NetX driver framework */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef NX_DRIVER_FRAMEWORK_H +#define NX_DRIVER_FRAMEWORK_H + + +#ifdef __cplusplus +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { +#endif /* __cplusplus */ + + +/* Include ThreadX header file, if not already. */ + +#ifndef TX_API_H +#include "tx_api.h" +#endif /* TX_API_H */ + + +/* Include NetX header file, if not already. */ + +#ifndef NX_API_H +#include "nx_api.h" +#endif /* NX_API_H */ + +#include "whd_types.h" + +/* WHD_LINK_HEADER is : 30 bytes */ +/* #define WHD_ETHERNET_SIZE (14) */ +/* #define WHD_PHYSICAL_HEADER (WHD_LINK_HEADER + WHD_ETHERNET_SIZE) : 44 bytes */ +/* #define WHD_PAYLOAD_MTU (1500) */ +/* #define WHD_LINK_MTU (WHD_PAYLOAD_MTU + WHD_PHYSICAL_HEADER): 1544 bytes */ + +/* #define NX_PHYSICAL_HEADER (44) */ + + +#if defined(NX_PHYSICAL_HEADER) && (NX_PHYSICAL_HEADER != WHD_PHYSICAL_HEADER) +#error The symbol NX_PHYSICAL_HEADER should be set to WHD_PHYSICAL_HEADER +#endif /* NX_PHYSICAL_HEADER */ + +#define NX_DRIVER_MTU (WHD_PAYLOAD_MTU + WHD_ETHERNET_SIZE) +#define NX_DRIVER_PHYSICAL_FRAME_SIZE (WHD_ETHERNET_SIZE) +#define NX_DRIVER_PACKET_SIZE (WHD_LINK_MTU) + + +#define NX_DRIVER_PHYSICAL_HEADER_REMOVE(p) \ + do { \ + p -> nx_packet_prepend_ptr += NX_DRIVER_PHYSICAL_FRAME_SIZE; \ + p -> nx_packet_length -= NX_DRIVER_PHYSICAL_FRAME_SIZE; \ + } while (0) + +struct NX_DRIVER_INFORMATION_STRUCT; + + +/** + * Determine if the driver's source file is being compiled. + * The constants and typedefs are only valid within + * the driver's source file compilation. + */ + +#ifdef NX_DRIVER_SOURCE + + +/* Define generic constants and macros for all NetX drivers. */ + +#define NX_DRIVER_STATE_NOT_INITIALIZED 1 +#define NX_DRIVER_STATE_INITIALIZE_FAILED 2 +#define NX_DRIVER_STATE_INITIALIZED 3 +#define NX_DRIVER_STATE_LINK_ENABLED 4 + +#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE +#ifndef NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH +#define NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH 10 +#endif /* NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH */ +#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */ + +#define NX_DRIVER_DEFERRED_PACKET_RECEIVED 1 +#define NX_DRIVER_DEFERRED_DEVICE_RESET 2 +#define NX_DRIVER_DEFERRED_PACKET_TRANSMITTED 4 + +#define NX_DRIVER_ERROR 90 + +#ifndef NX_DRIVER_CAPABILITY +#define NX_DRIVER_CAPABILITY ( 0 ) +#endif /* NX_DRIVER_CAPABILITY */ + +/* Define generic constants and macros for all NetX Ethernet drivers. */ + +#define NX_DRIVER_ETHERNET_IP 0x0800 +#define NX_DRIVER_ETHERNET_IPV6 0x86dd +#define NX_DRIVER_ETHERNET_ARP 0x0806 +#define NX_DRIVER_ETHERNET_RARP 0x8035 + + +/** + * Define basic Ethernet driver information typedef. + * Note that this typedefs is designed to be used only + * in the driver's C file. + */ + +typedef struct NX_DRIVER_INFORMATION_STRUCT +{ + /* NetX IP instance that this driver is attached to. */ + NX_IP *nx_driver_information_ip_ptr; + + /* Driver's current state. */ + ULONG nx_driver_information_state ; + + /* Packet pool used for receiving packets. */ + NX_PACKET_POOL *nx_driver_information_packet_pool_ptr; + + /* Define the driver interface association. */ + NX_INTERFACE *nx_driver_information_interface; + + /* Define the deferred event field. This will contain bits representing events + deferred from the ISR for processing in the thread context. */ + ULONG nx_driver_information_deferred_events; + +} NX_DRIVER_INFORMATION; + +#endif /* NX_DRIVER_SOURCE */ + + +/* Define default driver entry function. */ + +VOID nx_driver_framework_default_entry(NX_IP_DRIVER *driver_req_ptr); + +#ifdef __cplusplus +/* Yes, C++ compiler is present. Use standard C. */ +} +#endif /* __cplusplus */ + +#endif /* NX_DRIVER_FRAMEWORK_H */ diff --git a/common/stm32_drivers/wifi/cypress/nx_stm32_cypress_whd_driver.c b/common/stm32_drivers/wifi/cypress/nx_stm32_cypress_whd_driver.c new file mode 100644 index 00000000..f34a421f --- /dev/null +++ b/common/stm32_drivers/wifi/cypress/nx_stm32_cypress_whd_driver.c @@ -0,0 +1,391 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* */ +/* NetX Component */ +/* */ +/* Cypress CHIP WiFi driver for the STM32 family of microprocessors */ +/* */ +/* */ +/**************************************************************************/ + +#include +#include +#include +#include + +#include "nx_api.h" +#include "whd.h" +#include "whd_debug.h" +#include "whd_types.h" +#include "whd_int.h" +#include "cy_wifi_conf.h" + +#include "whd_config.h" + +#ifndef NX_DRIVER_DEFERRED_PROCESSING +/* #error The symbol NX_DRIVER_DEFERRED_PROCESSING should be defined */ +#endif /* NX_DRIVER_DEFERRED_PROCESSING */ + + +#define NX_DRIVER_ENABLE_DEFERRED + +/* Indicate that driver source is being compiled. */ +#define NX_DRIVER_SOURCE + +#if !defined(NX_DEBUG_DRIVER_SOURCE_LOG) +#define NX_DEBUG_DRIVER_SOURCE_LOG(...) /* ; */ +#define REMOVE_DEBUG_FUNC +#endif /*NX_DEBUG_DRIVER_SOURCE_LOG*/ + +#include "nx_stm32_cypress_whd_driver.h" +#include "nx_driver_framework.c" + +whd_interface_t *Ifp; + +/* Private variables ---------------------------------------------------------*/ +static uint32_t CypressAliveInterfaceCount = 0; +static whd_driver_t WhdDriver; +static uint16_t EventIndex = 0xFF; + +/* The station mode is the default. */ +wifi_mode_t WifiMode = WIFI_MODE_STA; + +static const whd_event_num_t sta_link_change_events[] = +{ + WLC_E_SET_SSID, + WLC_E_LINK, + WLC_E_AUTH, + WLC_E_ASSOC, + WLC_E_DEAUTH_IND, + WLC_E_DISASSOC_IND, + WLC_E_DISASSOC, + WLC_E_REASSOC, + WLC_E_PSK_SUP, + WLC_E_ACTION_FRAME_COMPLETE, + WLC_E_NONE +}; + + +/* Declare the boot function implemented in whd_config.c */ +cy_rslt_t whd_boot(whd_driver_t *pwhd_driver); + +static UINT _nx_driver_cypress_whd_initialize(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_cypress_whd_enable(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_cypress_whd_disable(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_cypress_whd_packet_send(NX_PACKET *packet_ptr); +static UINT _nx_driver_cypress_whd_interface_status(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_cypress_whd_packet_received(VOID); + +static VOID *_nx_driver_cypress_whd_event_handler(whd_interface_t ifp, + const whd_event_header_t *event_header, + const uint8_t *event_data, void *handler_user_data); + + +#if !defined(REMOVE_DEBUG_FUNC) +static void HexDump(const void *pData, size_t Size); +#endif /* REMOVE_DEBUG_FUNC */ + +extern UINT cypress_whd_alloc_init(VOID); + +VOID nx_driver_cypress_whd_entry(NX_IP_DRIVER *driver_req_ptr) +{ + static bool started = false; + if (!started) + { + nx_driver_hardware_initialize = _nx_driver_cypress_whd_initialize; + nx_driver_hardware_enable = _nx_driver_cypress_whd_enable; + nx_driver_hardware_disable = _nx_driver_cypress_whd_disable; + nx_driver_hardware_packet_send = _nx_driver_cypress_whd_packet_send; + nx_driver_hardware_get_status = _nx_driver_cypress_whd_interface_status; + nx_driver_hardware_packet_received = _nx_driver_cypress_whd_packet_received; + + started = true; + } + + nx_driver_framework_entry_default(driver_req_ptr); +} + + +void cy_network_process_ethernet_data(whd_interface_t interface, whd_buffer_t buffer) +{ + NX_PACKET *packet_ptr = buffer; + + (void)interface; + + /* Avoid starving. */ + if (packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_available == 0) + { + nx_packet_release(packet_ptr); + return; + } + + /* Everything is OK, transfer the packet to NetX. */ + nx_driver_transfer_to_netx(nx_driver_information.nx_driver_information_ip_ptr, packet_ptr); +} + + +UINT _nx_driver_cypress_whd_initialize(NX_IP_DRIVER *driver_req_ptr) +{ + UINT ret = NX_SUCCESS; + whd_mac_t mac; + + (void)(driver_req_ptr); + + if (cypress_whd_alloc_init()) + { + return NX_DRIVER_ERROR; + } + + if (CypressAliveInterfaceCount == 0) + { + /* Boot cypress module and start whd driver for very first interface. */ + if (WHD_SUCCESS != whd_boot(&WhdDriver)) + { + WPRINT_WHD_ERROR(("Can't perform initialization of the WHD driver and module\n")); + ret = NX_DRIVER_ERROR; + } + + if (NX_SUCCESS == ret) + { + Ifp = WHD_MALLOC(sizeof(whd_interface_t)); + if (Ifp == NULL) + { + WPRINT_WHD_ERROR(("WHD_MALLOC() Failed in %s() at line %d \n", + __func__, __LINE__)); + } + + if (WHD_SUCCESS != whd_wifi_on(WhdDriver, Ifp)) + { + WPRINT_WHD_ERROR(("Failed when creating WIFI default interface\n")); + ret = NX_DRIVER_ERROR; + } + else + { + NX_DEBUG_DRIVER_SOURCE_LOG("WHD initialization interface done\n"); + CypressAliveInterfaceCount++; + ret = NX_SUCCESS; + } + } + } + else + { + whd_mac_t mac_addr = {{0xA0, 0xC9, 0xA0, 0X3D, 0x43, 0x41}}; + if (WHD_SUCCESS != whd_add_secondary_interface(WhdDriver, &mac_addr, Ifp)) + { + WPRINT_WHD_ERROR(("Failed when creating WIFI default interface\n")); + ret = NX_DRIVER_ERROR; + } + else + { + NX_DEBUG_DRIVER_SOURCE_LOG("WHD initialization interface done\n"); + CypressAliveInterfaceCount++; + ret = NX_SUCCESS; + } + } + + if (whd_wifi_get_mac_address(*Ifp, &mac) == WHD_SUCCESS) + { + nx_driver_update_hardware_address(mac.octet); + } + + return NX_SUCCESS; +} + + +static VOID *_nx_driver_cypress_whd_event_handler(whd_interface_t ifp, + const whd_event_header_t *event_header, + const uint8_t *event_data, void *handler_user_data) +{ + UNUSED_PARAMETER(event_data); + + if (event_header->bsscfgidx >= WHD_INTERFACE_MAX) + { + WPRINT_WHD_ERROR(("event_header: Bad interface\n")); + return NULL; + } + + if ((event_header->event_type == WLC_E_DEAUTH_IND) || + (event_header->event_type == WLC_E_DISASSOC_IND) || + ((event_header->event_type == WLC_E_PSK_SUP) && + (event_header->status == WLC_SUP_KEYED) && + (event_header->reason == WLC_E_SUP_DEAUTH)) || + ((event_header->event_type == WLC_E_LINK) && + (event_header->reason == WLC_E_REASON_LOW_RSSI))) + { + return handler_user_data; + } + + if (((event_header->event_type == WLC_E_PSK_SUP) && + (event_header->status == WLC_SUP_KEYED) && + (event_header->reason == WLC_E_SUP_OTHER)) || + (whd_wifi_is_ready_to_transceive(ifp) == WHD_SUCCESS)) + { + return handler_user_data; + } + + return handler_user_data; +} + + +UINT _nx_driver_cypress_whd_enable(NX_IP_DRIVER *driver_req_ptr) +{ + int32_t ret = 0; + whd_security_t privacy = WHD_SECURITY_WPA2_AES_PSK; + whd_ssid_t myssid = {0}; + const char security_key[] = WIFI_PASSWORD; + + (void)driver_req_ptr; + + strncpy((char *) myssid.value, WIFI_SSID, sizeof(myssid.value)); + myssid.length = (uint8_t)strlen((const char *)myssid.value); + + if (WifiMode == WIFI_MODE_STA) + { + whd_wifi_set_event_handler(*Ifp, (uint32_t const *) sta_link_change_events, + _nx_driver_cypress_whd_event_handler, NULL, &EventIndex); + + NX_DEBUG_DRIVER_SOURCE_LOG("Joining ... \"%s\"\n", myssid.value); + + ret = whd_wifi_join(*Ifp, (whd_ssid_t const *) &myssid, privacy, + (uint8_t const *) security_key, strlen(security_key)); + if (ret != 0) + { + WPRINT_WHD_ERROR(("Can't join \"%s\"\n", myssid.value)); + ret = NX_DRIVER_ERROR; + } + } + else + { + NX_DEBUG_DRIVER_SOURCE_LOG("Initialize the Access Point ... \"%s\"\n", myssid.value); + + ret = whd_wifi_init_ap(*Ifp, &myssid, WHD_SECURITY_OPEN, + (uint8_t const *) security_key, strlen(security_key), + (uint8_t)8u); + if (ret != 0) + { + WPRINT_WHD_ERROR(("Can't initialize as Access Point \"%s\"\n", myssid.value)); + ret = NX_DRIVER_ERROR; + } + else + { + ret = whd_wifi_start_ap((*Ifp)); + if (ret != 0) + { + WPRINT_WHD_ERROR(("Can't start the Access Point \"%s\"\n", myssid.value)); + ret = NX_DRIVER_ERROR; + } + } + } + return NX_SUCCESS; +} + + +UINT _nx_driver_cypress_whd_disable(NX_IP_DRIVER *driver_req_ptr) +{ + int32_t ret = 0; + + (void)driver_req_ptr; + + ret = whd_wifi_leave(*Ifp); + if (ret != 0) + { + WPRINT_WHD_ERROR(("Can't leave \"%s\"\n", WIFI_SSID)); + ret = NX_DRIVER_ERROR; + } + + if (WHD_SUCCESS != whd_wifi_off(*Ifp)) + { + WPRINT_WHD_ERROR(("Failed when deleting WIFI default interface\n")); + ret = NX_DRIVER_ERROR; + } + + return ret; +} + +UINT _nx_driver_cypress_whd_packet_send(NX_PACKET *packet_ptr) +{ + NX_DEBUG_DRIVER_SOURCE_LOG("\n\n>***\n"); + +#if !defined(REMOVE_DEBUG_FUNC) + HexDump(packet_ptr->nx_packet_prepend_ptr, packet_ptr->nx_packet_length); +#endif /* REMOVE_DEBUG_FUNC */ + + whd_network_send_ethernet_data(*Ifp, packet_ptr); + + NX_DEBUG_DRIVER_SOURCE_LOG("\n<***\n\n"); + + return NX_SUCCESS; +} + +static VOID _nx_driver_cypress_whd_packet_received(VOID) +{ + +} + +static UINT _nx_driver_cypress_whd_interface_status(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status = NX_PTR_ERROR; + + if (NULL != driver_req_ptr -> nx_ip_driver_return_ptr) + { + *driver_req_ptr -> nx_ip_driver_return_ptr = (CypressAliveInterfaceCount > 0) ? NX_TRUE : NX_FALSE; + status = NX_SUCCESS; + } + + return status; +} + + +#if !defined(REMOVE_DEBUG_FUNC) +static void HexDump(const void *pData, size_t Size) +{ + char ascii[17] = {0}; + + for (size_t i = 0; i < Size; ++i) + { + const uint8_t data_byte = ((uint8_t *)pData)[i]; + NX_DEBUG_DRIVER_SOURCE_LOG("%02" PRIx32 " ", (uint32_t)data_byte); + + if ((data_byte >= ' ') && (data_byte <= '~')) + { + ascii[i % 16] = (char)data_byte; + } + else + { + ascii[i % 16] = '.'; + } + + if (((i + 1) % 8 == 0) || ((i + 1) == Size)) + { + NX_DEBUG_DRIVER_SOURCE_LOG(" "); + if ((i + 1) % 16 == 0) + { + NX_DEBUG_DRIVER_SOURCE_LOG("| %s \n", ascii); + } + else if (i + 1 == Size) + { + ascii[(i + 1) % 16] = '\0'; + if ((i + 1) % 16 <= 8) + { + NX_DEBUG_DRIVER_SOURCE_LOG(" "); + } + for (size_t j = (i + 1) % 16; j < 16; ++j) + { + NX_DEBUG_DRIVER_SOURCE_LOG(" "); + } + NX_DEBUG_DRIVER_SOURCE_LOG("| %s \n", ascii); + } + } + } +} +#endif /* REMOVE_DEBUG_FUNC */ diff --git a/common/stm32_drivers/wifi/cypress/nx_stm32_cypress_whd_driver.h b/common/stm32_drivers/wifi/cypress/nx_stm32_cypress_whd_driver.h new file mode 100644 index 00000000..d0e4b94b --- /dev/null +++ b/common/stm32_drivers/wifi/cypress/nx_stm32_cypress_whd_driver.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* */ +/* NetX Component */ +/* */ +/* Cypress CHIP WiFi driver for the STM32 family of microprocessors */ +/* */ +/* */ +/**************************************************************************/ + +#ifndef NX_STM32_CYPRESS_WHD_DRIVER_H +#define NX_STM32_CYPRESS_WHD_DRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "whd.h" +#include "nx_api.h" + +/* Mode for the WiFi module, i.e. Station or Access Point. */ +typedef enum +{ + WIFI_MODE_STA, + WIFI_MODE_AP +} wifi_mode_t; + + +/* Public API */ +VOID nx_driver_cypress_whd_entry(NX_IP_DRIVER *driver_req_ptr); +void cy_network_process_ethernet_data(whd_interface_t interface, whd_buffer_t buffer); + +extern whd_interface_t *Ifp; +extern wifi_mode_t WifiMode; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* NX_STM32_CYPRESS_WHD_DRIVER_H */ diff --git a/common/stm32_drivers/wifi/es_wifi/nx_driver_ism43362.c b/common/stm32_drivers/wifi/es_wifi/nx_driver_ism43362.c new file mode 100644 index 00000000..17a00bb5 --- /dev/null +++ b/common/stm32_drivers/wifi/es_wifi/nx_driver_ism43362.c @@ -0,0 +1,2093 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* */ +/* NetX Component */ +/* */ +/* ES-WiFi driver for the STM32 family of microprocessors */ +/* */ +/* */ +/**************************************************************************/ + +#include +#include +#include + +#include "nx_api.h" +#include "es_wifi_conf.h" + + +#if !defined(NX_DEBUG_DRIVER_SOURCE_LOG) +#define NX_DEBUG_DRIVER_SOURCE_LOG(...) /* ; */ +#define REMOVE_DEBUG_FUNC +#endif /*NX_DEBUG_DRIVER_SOURCE_LOG*/ + +#include "nx_driver_ism43362.h" +#include "wifi.h" + +#ifndef NX_ENABLE_TCPIP_OFFLOAD +#error "NX_ENABLE_TCPIP_OFFLOAD must be defined to use this driver" +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + +#ifndef NX_DRIVER_IP_MTU +/* Due to some underlying constraints of the WiFi module driver, */ +/* only 1200 bytes will be sent at most at once. Report ES_WIFI_PAYLOAD_SIZE define value */ +/* So in case of TCP, a MTU of 1240 gives 1240-20-20=1200 bytes. */ +/* So in case of UDP, a MTU of 1228 gives 1228-20-8=1200 bytes. */ +#define NX_DRIVER_IP_MTU 1228 +#endif /* NX_DRIVER_IP_MTU */ + +#ifndef NX_DRIVER_RECEIVE_QUEUE_SIZE +#define NX_DRIVER_RECEIVE_QUEUE_SIZE 10 +#endif /* NX_DRIVER_RECEIVE_QUEUE_SIZE */ + +#ifndef NX_DRIVER_STACK_SIZE +#define NX_DRIVER_STACK_SIZE 1024 +#endif /* NX_DRIVER_STACK_SIZE */ + +/* Interval to receive packets when there is no packet. */ +#ifndef NX_DRIVER_THREAD_INTERVAL +#define NX_DRIVER_THREAD_INTERVAL NX_IP_PERIODIC_RATE / 20 /* 50 ms */ +#endif /* NX_DRIVER_THREAD_INTERVAL */ + +/* Define the maximum sockets at the same time. This is limited by hardware TCP/IP on STM32L4. */ +#define NX_DRIVER_SOCKETS_MAXIMUM 4 + +/* Define maximum server pending connections. */ +/* Even if the server is in multi-accept mode, restrict backlog to 1. */ +#ifndef NX_DRIVER_SERVER_LISTEN_COUNT +#define NX_DRIVER_SERVER_LISTEN_COUNT 1 +#endif /* NX_DRIVER_SERVER_LISTEN_COUNT */ + +/* Define the maximum wait timeout in ms for socket send. This is limited by hardware TCP/IP on STM32L4. */ +#define NX_DRIVER_SOCKET_SEND_TIMEOUT_MAXIMUM 3000 + +#define NX_DRIVER_SOCKET_RECEIVE_TIMEOUT 4 /* In number of RTOS ticks */ + +#define NX_DRIVER_SOCKET_SERVER_WAIT_TIMEOUT 1 /* In number of milliseconds */ + + + +#define NX_DRIVER_CAPABILITY (NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) + +/* Define basic network driver information typedef. */ + +typedef struct NX_DRIVER_INFORMATION_STRUCT +{ + /* NetX IP instance that this driver is attached to. */ + NX_IP *nx_driver_information_ip_ptr; + + /* Driver's current states. */ + ULONG nx_driver_information_state; + + /* Packet pool used for receiving packets. */ + NX_PACKET_POOL *nx_driver_information_packet_pool_ptr; + + /* Define the driver interface association. */ + NX_INTERFACE *nx_driver_information_interface; + +} NX_DRIVER_INFORMATION; + + +/* Define socket structure for hardware TCP/IP. */ + +typedef struct NX_DRIVER_SOCKET_STRUCT +{ + VOID *socket_ptr; + UINT protocol; + ULONG local_ip; + USHORT local_port; + ULONG remote_ip; + USHORT remote_port; + UCHAR tcp_connected; + UCHAR is_client; + USHORT reserved; + +} NX_DRIVER_SOCKET; + +/* Private variables ---------------------------------------------------------*/ +static NX_DRIVER_INFORMATION nx_driver_information; +static NX_DRIVER_SOCKET nx_driver_sockets[NX_DRIVER_SOCKETS_MAXIMUM]; +static TX_THREAD nx_driver_thread; +static CHAR NX_DRIVER_THREAD_NAME[] = "Nx Driver Thread"; + +static UCHAR nx_driver_thread_stack[NX_DRIVER_STACK_SIZE]; + +/* Define the routines for processing each driver entry request. The contents of these routines will change with + each driver. However, the main driver entry function will not change, except for the entry function name. */ + +static VOID nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_enable(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_disable(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr); +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +static VOID nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr); +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ +#ifdef NX_DRIVER_ENABLE_DEFERRED +static VOID nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr); +#endif /* NX_DRIVER_ENABLE_DEFERRED */ +static VOID nx_driver_thread_entry(ULONG thread_input); +static UINT nx_driver_tcpip_handler(struct NX_IP_STRUCT *ip_ptr, + struct NX_INTERFACE_STRUCT *interface_ptr, + VOID *socket_ptr, UINT operation, NX_PACKET *packet_ptr, + NXD_ADDRESS *local_ip, NXD_ADDRESS *remote_ip, + UINT local_port, UINT *remote_port, UINT wait_option); + + +/* Define the pointers for the hardware implementation of this driver. */ +static UINT(*nx_driver_hardware_initialize)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_enable)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_disable)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_multicast_join)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_multicast_leave)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_get_status)(NX_IP_DRIVER *driver_req_ptr) = NULL; +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +static UINT(*nx_driver_hardware_capability_set)(NX_IP_DRIVER *driver_req_ptr) = NULL; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + +/* Define the prototypes for the hardware implementation of this driver. */ +/* The contents of these routines are driver-specific. */ +static UINT _nx_driver_hardware_initialize(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_enable(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_disable(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_get_status(NX_IP_DRIVER *driver_req_ptr); +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +static UINT _nx_driver_hardware_capability_set(NX_IP_DRIVER *driver_req_ptr); +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + +#if !defined(REMOVE_DEBUG_FUNC) +static const char *nx_driver_offload_operation_to_string(UINT operation); +static const char *nx_driver_operation_to_string(UINT operation); +#endif /* REMOVE_DEBUG_FUNC */ + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_ism43362_entry PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This is the entry point of the NetX Driver. This driver */ +/* function is responsible for initializing the network controller, */ +/* enabling or disabling the controller as need, preparing */ +/* a packet for transmission, and getting status information. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr The driver request from the */ +/* IP layer. */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_interface_attach Process attach request */ +/* _nx_driver_initialize Process initialize request */ +/* _nx_driver_enable Process link enable request */ +/* _nx_driver_disable Process link disable request */ +/* _nx_driver_multicast_join Process multicast join request*/ +/* _nx_driver_multicast_leave Process multicast leave req */ +/* _nx_driver_get_status Process get status request */ +/* _nx_driver_deferred_processing Drive deferred processing */ +/* _nx_driver_capability_get Get interface capability */ +/* _nx_driver_capability_set Set interface capability */ +/* */ +/* CALLED BY */ +/* */ +/* IP layer */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +VOID nx_driver_ism43362_entry(NX_IP_DRIVER *driver_req_ptr) +{ + static bool started = false; + if (!started) + { + nx_driver_hardware_initialize = _nx_driver_hardware_initialize; + nx_driver_hardware_enable = _nx_driver_hardware_enable; + nx_driver_hardware_disable = _nx_driver_hardware_disable; + nx_driver_hardware_get_status = _nx_driver_hardware_get_status; +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + nx_driver_hardware_capability_set = _nx_driver_hardware_capability_set; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + started = true; + } + + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] > %s\n", HAL_GetTick(), + nx_driver_operation_to_string(driver_req_ptr -> nx_ip_driver_command)); + + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Process according to the driver request type in the IP control block. */ + switch (driver_req_ptr -> nx_ip_driver_command) + { + + case NX_LINK_INTERFACE_ATTACH: + { + /* Process link interface attach requests. */ + nx_driver_interface_attach(driver_req_ptr); + break; + } + + case NX_LINK_INITIALIZE: + { + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Initialization - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + NX_DEBUG_DRIVER_SOURCE_LOG(" IP Address = %08" PRIX32 "\n", + (uint32_t)driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_address); + + /* Process link initialize requests. */ + nx_driver_initialize(driver_req_ptr); + break; + } + + case NX_LINK_ENABLE: + { + /* Process link enable requests. */ + nx_driver_enable(driver_req_ptr); + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Link Enabled - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + break; + } + + case NX_LINK_DISABLE: + { + /* Process link disable requests. */ + nx_driver_disable(driver_req_ptr); + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Link Disabled - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + break; + } + + case NX_LINK_ARP_SEND: + case NX_LINK_ARP_RESPONSE_SEND: + case NX_LINK_PACKET_BROADCAST: + case NX_LINK_RARP_SEND: + case NX_LINK_PACKET_SEND: + { + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + nx_packet_transmit_release(driver_req_ptr -> nx_ip_driver_packet); + break; + } + + case NX_LINK_MULTICAST_JOIN: + { + /* Process multicast join requests. */ + nx_driver_multicast_join(driver_req_ptr); + break; + } + + case NX_LINK_MULTICAST_LEAVE: + { + /* Process multicast leave requests. */ + nx_driver_multicast_leave(driver_req_ptr); + break; + } + + case NX_LINK_GET_STATUS: + { + /* Process get status requests. */ + nx_driver_get_status(driver_req_ptr); + break; + } + +#ifdef NX_DRIVER_ENABLE_DEFERRED + case NX_LINK_DEFERRED_PROCESSING: + { + /* Process driver deferred requests. */ + + /* Process a device driver function on behave of the IP thread. */ + nx_driver_deferred_processing(driver_req_ptr); + break; + } +#endif /* NX_DRIVER_ENABLE_DEFERRED */ + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + case NX_INTERFACE_CAPABILITY_GET: + { + /* Process get capability requests. */ + nx_driver_capability_get(driver_req_ptr); + break; + } + + case NX_INTERFACE_CAPABILITY_SET: + { + /* Process set capability requests. */ + nx_driver_capability_set(driver_req_ptr); + break; + } +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + default: + + /* Invalid driver request. */ + + /* Return the unhandled command status. */ + driver_req_ptr -> nx_ip_driver_status = NX_UNHANDLED_COMMAND; + + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Received invalid request - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_interface_attach PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the interface attach request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr) +{ +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + driver_req_ptr -> nx_ip_driver_interface -> nx_interface_capability_flag = NX_DRIVER_CAPABILITY; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + /* Return successful status. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_initialize PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the initialize request. The processing */ +/* in this function is generic. All hardware specific logic goes in */ +/* nx_driver_hardware_initialize. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_initialize Process initialize request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr) +{ + NX_IP *ip_ptr; + NX_INTERFACE *interface_ptr; + UINT status; + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Setup interface pointer. */ + interface_ptr = driver_req_ptr -> nx_ip_driver_interface; + + /* Initialize the driver's information structure. */ + + /* Default IP pointer to NULL. */ + nx_driver_information.nx_driver_information_ip_ptr = NX_NULL; + + /* Setup the driver state to not initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_NOT_INITIALIZED; + + /* Setup the default packet pool for the driver's received packets. */ + nx_driver_information.nx_driver_information_packet_pool_ptr = ip_ptr -> nx_ip_default_packet_pool; + + /* Call the hardware-specific WiFi module initialization. */ + if (!nx_driver_hardware_initialize) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_initialize(driver_req_ptr); + } + + /* Determine if the request was successful. */ + if (status == NX_SUCCESS) + { + /* Successful hardware initialization. */ + + /* Setup driver information to point to IP pointer. */ + nx_driver_information.nx_driver_information_ip_ptr = ip_ptr; + nx_driver_information.nx_driver_information_interface = interface_ptr; + + /* Setup the link maximum transfer unit. */ + interface_ptr -> nx_interface_ip_mtu_size = NX_DRIVER_IP_MTU; + + /* Setup the physical address of this IP instance. */ + interface_ptr -> nx_interface_physical_address_msw = 0; + interface_ptr -> nx_interface_physical_address_lsw = 0; + + /* Indicate to the IP software that IP to physical mapping + is required. */ + interface_ptr -> nx_interface_address_mapping_needed = NX_FALSE; + + /* Move the driver's state to initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED; + + /* Indicate successful initialize. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + /* Initialization failed. Indicate that the request failed. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_enable PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the initialize request. The processing */ +/* in this function is generic. All hardware specific logic in */ +/* nx_driver_hardware_enable. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_enable Process enable request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_enable(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + + /* See if we can honor the NX_LINK_ENABLE request. */ + if (nx_driver_information.nx_driver_information_state < NX_DRIVER_STATE_INITIALIZED) + { + /* Mark the request as not successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + + /* Check if it is enabled by someone already */ + if (nx_driver_information.nx_driver_information_state >= NX_DRIVER_STATE_LINK_ENABLED) + { + /* Yes, the request has already been made. */ + driver_req_ptr -> nx_ip_driver_status = NX_ALREADY_ENABLED; + return; + } + + /* Call hardware specific enable. */ + if (!nx_driver_hardware_enable) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_enable(driver_req_ptr); + } + + /* Was the hardware enable successful? */ + if (status == NX_SUCCESS) + { + /* Update the driver state to link enabled. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_LINK_ENABLED; + + /* Mark request as successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Mark the IP instance as link up. */ + driver_req_ptr -> nx_ip_driver_interface -> nx_interface_link_up = NX_TRUE; + + /* Set TCP/IP callback function. */ + driver_req_ptr -> nx_ip_driver_interface -> nx_interface_tcpip_offload_handler = nx_driver_tcpip_handler; + } + else + { + /* Enable failed. Indicate that the request failed. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_disable PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the disable request. The processing */ +/* in this function is generic. All hardware specific logic in */ +/* nx_driver_hardware_disable. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_disable Process disable request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_disable(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + + /* Check if the link is enabled. */ + if (nx_driver_information.nx_driver_information_state != NX_DRIVER_STATE_LINK_ENABLED) + { + /* The link is not enabled, so just return an error. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + + /* Call hardware specific disable. */ + status = nx_driver_hardware_disable(driver_req_ptr); + + /* Was the hardware disable successful? */ + if (status == NX_SUCCESS) + { + /* Mark the IP instance as link down. */ + driver_req_ptr -> nx_ip_driver_interface -> nx_interface_link_up = NX_FALSE; + + /* Update the driver state back to initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED; + + /* Mark request as successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Clear the TCP/IP callback function. */ + driver_req_ptr -> nx_ip_driver_interface -> nx_interface_tcpip_offload_handler = NX_NULL; + } + else + { + /* Disable failed, return an error. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_multicast_join PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the multicast join request. The processing */ +/* in this function is generic. All hardware specific logic is in */ +/* nx_driver_hardware_multicast_join. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_multicast_join Process multicast join request*/ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + + /* Call hardware specific multicast join function. */ + if (!nx_driver_hardware_multicast_join) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_multicast_join(driver_req_ptr); + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver multicast join returns: NX_DRIVER_ERROR\n"); + /* Call hardware specific multicast join function. */ + } + else + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_multicast_leave PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the multicast leave request. The code */ +/* in this function is generic. All hardware specific logic is in */ +/* nx_driver_hardware_multicast_leave. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_multicast_leave Process multicast leave req */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + + /* Call hardware specific multicast leave function. */ + if (!nx_driver_hardware_multicast_leave) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_multicast_leave(driver_req_ptr); + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver multicast leave returns: NX_DRIVER_ERROR\n"); + } + else + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_get_status PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the get status request. The processing */ +/* in this function is generic. All hardware specific logic is in */ +/* nx_driver_hardware_get_status. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_get_status Process get status request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr) +{ + /* Call hardware specific get status function. */ + if (!nx_driver_hardware_get_status) + { + driver_req_ptr -> nx_ip_driver_status = NX_UNHANDLED_COMMAND; + } + else + { + UINT status = nx_driver_hardware_get_status(driver_req_ptr); + + if (status == NX_SUCCESS) + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + } +} + + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_capability_get PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the get capability request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr) +{ + /* Return the capability of the WiFi controller. */ + *(driver_req_ptr -> nx_ip_driver_return_ptr) = NX_DRIVER_CAPABILITY; + + /* Return the success status. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_capability_set PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the set capability request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + + /* Call hardware specific get status function. */ + if (!nx_driver_hardware_capability_set) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_capability_set(driver_req_ptr); + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + else + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + +#ifdef NX_DRIVER_ENABLE_DEFERRED +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_deferred_processing PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the deferred ISR action within the context */ +/* of the IP thread. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr) +{ + +} +#endif /* NX_DRIVER_ENABLE_DEFERRED */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_thread_entry PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the driver thread entry. In this thread, it */ +/* performs checking for incoming TCP and UDP packets. On new packet, */ +/* it will be passed to NetX. */ +/* */ +/* INPUT */ +/* */ +/* thread_input Thread input */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Obtain protection mutex */ +/* tx_mutex_put Release protection mutex */ +/* tx_thread_sleep Sleep driver thread */ +/* nx_packet_allocate Allocate a packet for incoming*/ +/* TCP and UDP data */ +/* _nx_tcp_socket_driver_packet_receive Receive TCP packet */ +/* _nx_tcp_socket_driver_establish Establish TCP connection */ +/* _nx_udp_socket_driver_packet_receive Receive UDP packet */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_thread_entry(ULONG thread_input) +{ + UINT packet_type; + UINT status; + uint16_t data_length; + NX_IP *const ip_ptr = nx_driver_information.nx_driver_information_ip_ptr; + NX_INTERFACE *const interface_ptr = nx_driver_information.nx_driver_information_interface; + NX_PACKET_POOL *const pool_ptr = nx_driver_information.nx_driver_information_packet_pool_ptr; + + NX_PARAMETER_NOT_USED(thread_input); + + for (;;) + { + /* Obtain the IP internal mutex before processing the IP event. */ + tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); + + /* Loop through TCP socket. */ + for (UINT i = 0; i < NX_DRIVER_SOCKETS_MAXIMUM; i++) + { + if (nx_driver_sockets[i].socket_ptr == NX_NULL) + { + /* Skip sockets not used. */ + continue; + } + + if ((nx_driver_sockets[i].local_port == 0) && (nx_driver_sockets[i].remote_port == 0)) + { + /* Skip sockets not listening. */ + continue; + } + + /* Set packet type. */ + if (nx_driver_sockets[i].protocol == NX_PROTOCOL_TCP) + { + packet_type = NX_TCP_PACKET; + if ((nx_driver_sockets[i].tcp_connected == NX_FALSE) && (nx_driver_sockets[i].is_client == NX_FALSE)) + { + /* TCP server. Try accept. */ + if (_nx_tcp_socket_driver_establish((NX_TCP_SOCKET *)nx_driver_sockets[i].socket_ptr, interface_ptr, 0)) + { + /* NX_DEBUG_DRIVER_SOURCE_LOG("\n%s: Sleeping (%04" PRIu32 ")\n", NX_DRIVER_THREAD_NAME, (uint32_t)__LINE__); */ + + /* NetX TCP socket is not ready to accept. Just sleep to avoid starving. */ + tx_thread_sleep(NX_DRIVER_THREAD_INTERVAL / 2); + continue; + } + } + } + else + { + packet_type = NX_UDP_PACKET; + } + + /* Loop to receive all data on current socket. */ + for (;;) + { + NX_PACKET *packet_ptr = NX_NULL; + + if (nx_packet_allocate(pool_ptr, &packet_ptr, packet_type, NX_NO_WAIT)) + { + NX_DEBUG_DRIVER_SOURCE_LOG("\n\"%s\": TCP (%" PRIu32 ") No packet (%04" PRIu32 ")\n", + NX_DRIVER_THREAD_NAME, (uint32_t)i, (uint32_t)__LINE__); + /* Packet not available. */ + break; + } + + /* Get available size of packet. */ + data_length = (uint16_t)((ptrdiff_t)((ptrdiff_t)packet_ptr -> nx_packet_data_end - \ + (ptrdiff_t)packet_ptr -> nx_packet_prepend_ptr)); + + /* Limit the data length to ES_WIFI_PAYLOAD_SIZE due to underlayer limitation. */ + if (data_length > ES_WIFI_PAYLOAD_SIZE) + { + data_length = ES_WIFI_PAYLOAD_SIZE; + } + + /* Receive data without suspending. */ + status = WIFI_ReceiveData(i, (uint8_t *)(packet_ptr -> nx_packet_prepend_ptr), + data_length, &data_length, NX_DRIVER_SOCKET_RECEIVE_TIMEOUT /*NX_NO_WAIT*/); + + if (status != WIFI_STATUS_OK) + { + /* Connection error. Notify upper layer with Null packet. */ + if (nx_driver_sockets[i].protocol == NX_PROTOCOL_TCP) + { + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] \"%s\" TCP (%" PRIu32 ") (:%" PRIu32 ") received data with: %04" PRIu32 "\n", + HAL_GetTick(), NX_DRIVER_THREAD_NAME, + (uint32_t)i, (uint32_t)nx_driver_sockets[i].local_port, (uint32_t)status); + + if (nx_driver_sockets[i].is_client == NX_FALSE) + { + _nx_tcp_socket_driver_packet_receive((NX_TCP_SOCKET *)nx_driver_sockets[i].socket_ptr, NX_NULL); + + /* The remote side client has disconnected. */ + nx_driver_sockets[i].tcp_connected = NX_FALSE; + } + else + { + /* In case there is no more data on the server side, */ + /* even if an error is returned by the underlying driver, */ + /* simply break the receive loop with an empty packet. */ + data_length = 0; + } + + } + else + { + _nx_udp_socket_driver_packet_receive((NX_UDP_SOCKET *)nx_driver_sockets[i].socket_ptr, NX_NULL, + NX_NULL, NX_NULL, 0); + } + nx_packet_release(packet_ptr); + break; + } + + if (data_length == 0) + { + /* No incoming data. */ + nx_packet_release(packet_ptr); + break; + } + + /* Set packet length. */ + packet_ptr -> nx_packet_length = (ULONG)data_length; + packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + data_length; + packet_ptr -> nx_packet_ip_interface = interface_ptr; + + /* Pass it to NetXDuo. */ + if (nx_driver_sockets[i].protocol == NX_PROTOCOL_TCP) + { + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] \"%s\" TCP (%" PRIu32 ") (:%" PRIu32 ") received data with %04" PRIu32 " bytes\n", + HAL_GetTick(), NX_DRIVER_THREAD_NAME, + (uint32_t)i, (uint32_t)nx_driver_sockets[i].local_port, + (uint32_t)data_length); + + _nx_tcp_socket_driver_packet_receive((NX_TCP_SOCKET *)nx_driver_sockets[i].socket_ptr, packet_ptr); + } + else + { + NXD_ADDRESS local_ip; + NXD_ADDRESS remote_ip; + /* Convert IP version. */ + remote_ip.nxd_ip_version = NX_IP_VERSION_V4; + remote_ip.nxd_ip_address.v4 = nx_driver_sockets[i].remote_ip; + local_ip.nxd_ip_version = NX_IP_VERSION_V4; + local_ip.nxd_ip_address.v4 = nx_driver_sockets[i].local_ip; + + _nx_udp_socket_driver_packet_receive((NX_UDP_SOCKET *)nx_driver_sockets[i].socket_ptr, + packet_ptr, &local_ip, &remote_ip, + nx_driver_sockets[i].remote_port); + } + } + } + + /* Release the IP internal mutex before processing the IP event. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + /* Sleep some ticks to next loop. */ + tx_thread_sleep(NX_DRIVER_THREAD_INTERVAL); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_tcpip_handler PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the TCP/IP request. */ +/* */ +/* INPUT */ +/* */ +/* ip_ptr Pointer to IP */ +/* interface_ptr Pointer to interface */ +/* socket_ptr Pointer to TCP or UDP socket */ +/* operation Operation of TCP/IP request */ +/* packet_ptr Pointer to packet */ +/* local_ip Pointer to local IP address */ +/* remote_ip Pointer to remote IP address */ +/* local_port Local socket port */ +/* remote_port Remote socket port */ +/* wait_option Wait option in ticks */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_packet_transmit_release Release transmission packet */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static UINT nx_driver_tcpip_handler(struct NX_IP_STRUCT *ip_ptr, + struct NX_INTERFACE_STRUCT *interface_ptr, + VOID *socket_ptr, UINT operation, NX_PACKET *packet_ptr, + NXD_ADDRESS *local_ip, NXD_ADDRESS *remote_ip, + UINT local_port, UINT *remote_port, UINT wait_option) +{ + UINT status = NX_NOT_SUCCESSFUL; + UINT i; + + (void)(ip_ptr); + (void)(interface_ptr); + + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] > %s\n", HAL_GetTick(), nx_driver_offload_operation_to_string(operation)); + + if (operation == NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_LISTEN) + { + /* For TCP server socket, find duplicate listen request first. + Only one socket can listen to each TCP port. */ + for (i = 0; i < NX_DRIVER_SOCKETS_MAXIMUM; i++) + { + if ((nx_driver_sockets[i].local_port == local_port) && (nx_driver_sockets[i].protocol == NX_PROTOCOL_TCP)) + { + if (nx_driver_sockets[i].tcp_connected == NX_TRUE) + { + NX_DEBUG_DRIVER_SOURCE_LOG("\n< NX_NOT_SUPPORTED (%" PRIu32 "):\n\n", (uint32_t)i); + + /* Previous connection not closed. Multiple connection is not supported. */ + return (NX_NOT_SUPPORTED); + } + + /* Find a duplicate listen. Just overwrite it. */ + ((NX_TCP_SOCKET *)socket_ptr) -> nx_tcp_socket_tcpip_offload_context = (VOID *)i; + nx_driver_sockets[i].socket_ptr = socket_ptr; + + return (NX_SUCCESS); + } + } + } + + if ((operation == NX_TCPIP_OFFLOAD_TCP_CLIENT_SOCKET_CONNECT) || + (operation == NX_TCPIP_OFFLOAD_UDP_SOCKET_BIND) || + (operation == NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_LISTEN)) + { + /* Find a socket that is not used. */ + for (i = 0; i < NX_DRIVER_SOCKETS_MAXIMUM; i++) + { + if (nx_driver_sockets[i].socket_ptr == NX_NULL) + { + /* Find an empty entry. */ + nx_driver_sockets[i].socket_ptr = socket_ptr; + + NX_DEBUG_DRIVER_SOURCE_LOG("\n Driver socket -> (%" PRIu32 "):\n\n", (uint32_t)i); + break; + } + } + + if (i == NX_DRIVER_SOCKETS_MAXIMUM) + { + /* No more entries. */ + return (NX_NO_MORE_ENTRIES); + } + } + + switch (operation) + { + case NX_TCPIP_OFFLOAD_TCP_CLIENT_SOCKET_CONNECT: + { + UCHAR remote_ip_bytes[4]; + + /* Store the index of driver socket. */ + ((NX_TCP_SOCKET *)socket_ptr) -> nx_tcp_socket_tcpip_offload_context = (VOID *)i; + + /* Convert remote IP to byte array. */ + remote_ip_bytes[0] = (UCHAR)((remote_ip -> nxd_ip_address.v4 >> 24) & 0xFF); + remote_ip_bytes[1] = (remote_ip -> nxd_ip_address.v4 >> 16) & 0xFF; + remote_ip_bytes[2] = (remote_ip -> nxd_ip_address.v4 >> 8) & 0xFF; + remote_ip_bytes[3] = (remote_ip -> nxd_ip_address.v4) & 0xFF; + + /* Connect. */ + status = WIFI_OpenClientConnection(i, WIFI_TCP_PROTOCOL, "", + remote_ip_bytes, (uint16_t)(*remote_port), (uint16_t)(local_port)); + + if (status) + { + return (NX_NOT_SUCCESSFUL); + } + + NX_DEBUG_DRIVER_SOURCE_LOG("\n### TCP client socket %" PRIu32 " connect to: %u.%u.%u.%u:%u\n", + (uint32_t)i, + remote_ip_bytes[0], remote_ip_bytes[1], remote_ip_bytes[2], remote_ip_bytes[3], + *remote_port); + + /* Store address and port. */ + nx_driver_sockets[i].remote_ip = remote_ip -> nxd_ip_address.v4; + nx_driver_sockets[i].local_port = (USHORT)local_port; + nx_driver_sockets[i].remote_port = (USHORT)(*remote_port); + nx_driver_sockets[i].protocol = NX_PROTOCOL_TCP; + nx_driver_sockets[i].is_client = NX_TRUE; + } + break; + + case NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_LISTEN: + { + /* Store the index of driver socket. */ + ((NX_TCP_SOCKET *)socket_ptr) -> nx_tcp_socket_tcpip_offload_context = (VOID *)i; + + /* Start TCP server. */ + status = WIFI_StartServer(i, WIFI_TCP_PROTOCOL, NX_DRIVER_SERVER_LISTEN_COUNT, "", (uint16_t)local_port); + if (status) + { + NX_DEBUG_DRIVER_SOURCE_LOG("\n< NX_NOT_SUCCESSFUL (%" PRIu32 ")\n", (uint32_t)i); + + return (NX_NOT_SUCCESSFUL); + } + + NX_DEBUG_DRIVER_SOURCE_LOG("\n### TCP server socket %" PRIu32 " listen to port: %u\n", (uint32_t)i, local_port); + + /* Store address and port. */ + nx_driver_sockets[i].local_port = (USHORT)local_port; + nx_driver_sockets[i].remote_port = 0; + nx_driver_sockets[i].protocol = NX_PROTOCOL_TCP; + nx_driver_sockets[i].tcp_connected = NX_FALSE; + nx_driver_sockets[i].is_client = NX_FALSE; + } + break; + + case NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_ACCEPT: + { + UCHAR remote_ip_bytes[4]; + i = (UINT)(((NX_TCP_SOCKET *)socket_ptr) -> nx_tcp_socket_tcpip_offload_context); + /* Accept connection. */ + status = WIFI_WaitServerConnection(i, NX_DRIVER_SOCKET_SERVER_WAIT_TIMEOUT, + remote_ip_bytes, sizeof(remote_ip_bytes), &nx_driver_sockets[i].remote_port); + + if (status) + { + /* NX_DEBUG_DRIVER_SOURCE_LOG("\nNX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_ACCEPT: NX_NOT_SUCCESSFUL\n"); */ + + return (NX_NOT_SUCCESSFUL); + } + + NX_DEBUG_DRIVER_SOURCE_LOG("\n### TCP server socket (%" PRIu32 ") (:%" PRIu32 ") accept from: %u.%u.%u.%u:%u\n", + (uint32_t)i, (uint32_t)nx_driver_sockets[i].local_port, + remote_ip_bytes[0], remote_ip_bytes[1], remote_ip_bytes[2], remote_ip_bytes[3], + nx_driver_sockets[i].remote_port); + + /* Store address and port. */ + remote_ip -> nxd_ip_version = NX_IP_VERSION_V4; + remote_ip -> nxd_ip_address.v4 = IP_ADDRESS(remote_ip_bytes[0], + remote_ip_bytes[1], + remote_ip_bytes[2], + remote_ip_bytes[3]); + nx_driver_sockets[i].remote_ip = remote_ip -> nxd_ip_address.v4; + *remote_port = (UINT)nx_driver_sockets[i].remote_port; + nx_driver_sockets[i].tcp_connected = NX_TRUE; + } + break; + + case NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_UNLISTEN: + { + uint8_t listenee_count = 0; + for (i = 0; i < NX_DRIVER_SOCKETS_MAXIMUM; i++) + { + if (nx_driver_sockets[i].local_port != 0) + { + listenee_count++; + } + if ((nx_driver_sockets[i].local_port == local_port) && (nx_driver_sockets[i].protocol == NX_PROTOCOL_TCP)) + { + NX_DEBUG_DRIVER_SOURCE_LOG("\n### TCP server socket (%" PRIu32 ") unlisten port: %u (%" PRIu32 ")\n", + (uint32_t)i, local_port, (uint32_t)listenee_count); + + nx_driver_sockets[i].socket_ptr = NX_NULL; + nx_driver_sockets[i].protocol = 0; + nx_driver_sockets[i].local_ip = 0; + nx_driver_sockets[i].local_port = 0; + nx_driver_sockets[i].remote_ip = 0; + nx_driver_sockets[i].remote_port = 0; + nx_driver_sockets[i].tcp_connected = NX_FALSE; + nx_driver_sockets[i].is_client = NX_FALSE; + + if (1 < listenee_count) + { + WIFI_CloseServerConnection(i); + } + else + { + /* Not port at all to listen to. */ + WIFI_StopServer(i); + } + + return (NX_SUCCESS); + } + } + } + break; + + case NX_TCPIP_OFFLOAD_TCP_SOCKET_DISCONNECT: + { + i = (UINT)(((NX_TCP_SOCKET *)socket_ptr) -> nx_tcp_socket_tcpip_offload_context); + if (nx_driver_sockets[i].remote_port) + { + if (nx_driver_sockets[i].is_client) + { + NX_DEBUG_DRIVER_SOURCE_LOG("\n### TCP client socket %" PRIu32 " disconnect\n", (uint32_t)i); + + /* Disconnect. */ + status = WIFI_CloseClientConnection(i); + } + else + { + NX_DEBUG_DRIVER_SOURCE_LOG("\n### TCP server socket %" PRIu32 " (:%" PRIu32 ") disconnect\n", + (uint32_t)i, (uint32_t)nx_driver_sockets[i].local_port); + + /* Close server connection. */ + status = WIFI_CloseServerConnection(i); + nx_driver_sockets[i].tcp_connected = NX_FALSE; + + /* No need to free this entry as TCP server still needs to listening to port. */ + break; + } + } + + /* Reset socket to free this entry. */ + nx_driver_sockets[i].socket_ptr = NX_NULL; + } + break; + + case NX_TCPIP_OFFLOAD_UDP_SOCKET_BIND: + { + /* Note, send data from one port to multiple remotes are not supported. */ + /* Store the index of driver socket. */ + ((NX_UDP_SOCKET *)socket_ptr) -> nx_udp_socket_tcpip_offload_context = (VOID *)i; + + /* Reset the remote port to indicate the socket is not connected yet. */ + nx_driver_sockets[i].remote_port = 0; + + NX_DEBUG_DRIVER_SOURCE_LOG("\n### UDP socket %" PRIu32 " bind to port: %u\n", (uint32_t)i, local_port); + + status = NX_SUCCESS; + } + break; + + case NX_TCPIP_OFFLOAD_UDP_SOCKET_UNBIND: + { + i = (UINT)(((NX_UDP_SOCKET *)socket_ptr) -> nx_udp_socket_tcpip_offload_context); + if (nx_driver_sockets[i].remote_port) + { + /* Disconnect. */ + status = WIFI_CloseClientConnection(i); + + NX_DEBUG_DRIVER_SOURCE_LOG("\n### UDP socket %" PRIu32 " unbind port: %u\n", (uint32_t)i, local_port); + } + + /* Reset socket to free this entry. */ + nx_driver_sockets[i].socket_ptr = NX_NULL; + } + break; + + case NX_TCPIP_OFFLOAD_UDP_SOCKET_SEND: + { + i = (UINT)(((NX_UDP_SOCKET *)socket_ptr) -> nx_udp_socket_tcpip_offload_context); + if (nx_driver_sockets[i].remote_port == 0) + { + UCHAR remote_ip_bytes[4]; + + /* Do connection once. */ + /* Convert remote IP to byte array. */ + remote_ip_bytes[0] = (UCHAR)((remote_ip -> nxd_ip_address.v4 >> 24) & 0xFF); + remote_ip_bytes[1] = (remote_ip -> nxd_ip_address.v4 >> 16) & 0xFF; + remote_ip_bytes[2] = (remote_ip -> nxd_ip_address.v4 >> 8) & 0xFF; + remote_ip_bytes[3] = (remote_ip -> nxd_ip_address.v4) & 0xFF; + + /* Connect. */ + status = WIFI_OpenClientConnection(i, WIFI_UDP_PROTOCOL, "", + remote_ip_bytes, (uint16_t)(*remote_port), (uint16_t)local_port); + if (status) + { + return (NX_NOT_SUCCESSFUL); + } + + NX_DEBUG_DRIVER_SOURCE_LOG("\n### UDP socket %" PRIu32 " connect to: %u.%u.%u.%u:%u\n", + (uint32_t)i, + remote_ip_bytes[0], remote_ip_bytes[1], remote_ip_bytes[2], remote_ip_bytes[3], + *remote_port); + + /* Store address and port. */ + nx_driver_sockets[i].protocol = NX_PROTOCOL_UDP; + nx_driver_sockets[i].local_ip = local_ip -> nxd_ip_address.v4; + nx_driver_sockets[i].local_port = (USHORT)local_port; + nx_driver_sockets[i].remote_ip = remote_ip -> nxd_ip_address.v4; + nx_driver_sockets[i].remote_port = (USHORT)(*remote_port); + nx_driver_sockets[i].is_client = NX_TRUE; + } + + if ((packet_ptr -> nx_packet_length > ES_WIFI_PAYLOAD_SIZE) +#ifndef NX_DISABLE_PACKET_CHAIN + || (packet_ptr -> nx_packet_next) +#endif /* NX_DISABLE_PACKET_CHAIN */ + ) + { + /* Limitation in this driver. UDP packet must be in one packet. */ + return (NX_NOT_SUCCESSFUL); + } + + /* Convert wait option from ticks to ms. */ + if (wait_option > (NX_DRIVER_SOCKET_SEND_TIMEOUT_MAXIMUM / 1000 * NX_IP_PERIODIC_RATE)) + { + wait_option = NX_DRIVER_SOCKET_SEND_TIMEOUT_MAXIMUM; + } + else + { + wait_option = wait_option / NX_IP_PERIODIC_RATE * 1000; + } + + /* Send data. */ + { + uint16_t sent_size = 0; + status = WIFI_SendData(i, + packet_ptr -> nx_packet_prepend_ptr, + (uint16_t)(packet_ptr -> nx_packet_length), &sent_size, + (uint32_t)wait_option); + + /* Check status. */ + if ((status != WIFI_STATUS_OK) || (sent_size != packet_ptr -> nx_packet_length)) + { + return (NX_NOT_SUCCESSFUL); + } + + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] ### UDP socket %" PRIu32 " sent data with: %04" PRIu32 " bytes\n", + HAL_GetTick(), (uint32_t)i, (uint32_t)sent_size); + } + /* Release the packet. */ + nx_packet_transmit_release(packet_ptr); + } + break; + + case NX_TCPIP_OFFLOAD_TCP_SOCKET_SEND: + { + NX_PACKET *current_packet; + ULONG offset; + + i = (UINT)(((NX_TCP_SOCKET *)socket_ptr) -> nx_tcp_socket_tcpip_offload_context); + /* Initialize the current packet to the input packet pointer. */ + current_packet = packet_ptr; + offset = 0; + + /* Convert wait option from ticks to ms. */ + if (wait_option > (NX_DRIVER_SOCKET_SEND_TIMEOUT_MAXIMUM / 1000 * NX_IP_PERIODIC_RATE)) + { + wait_option = NX_DRIVER_SOCKET_SEND_TIMEOUT_MAXIMUM; + } + else + { + wait_option = wait_option / NX_IP_PERIODIC_RATE * 1000; + } + + /* Loop to send the packet. */ + while (current_packet) + { + ULONG packet_size; + uint16_t sent_size = 0; + + /* Calculate current packet size. */ + packet_size = (ULONG)(current_packet -> nx_packet_append_ptr - current_packet -> nx_packet_prepend_ptr); + packet_size -= offset; + + /* Limit the data size to ES_WIFI_PAYLOAD_SIZE due to underlayer limitation. */ + if (packet_size > ES_WIFI_PAYLOAD_SIZE) + { + packet_size = ES_WIFI_PAYLOAD_SIZE; + } + + /* Send data. */ + status = WIFI_SendData(i, + current_packet -> nx_packet_prepend_ptr + offset, + (uint16_t)packet_size, &sent_size, + wait_option); + + /* Check status. */ + if ((status != WIFI_STATUS_OK) || (sent_size != packet_size)) + { + NX_DEBUG_DRIVER_SOURCE_LOG("\nNX_TCPIP_OFFLOAD_TCP_SOCKET_SEND (%" PRIu32 "): NX_NOT_SUCCESSFUL\n", (uint32_t)i); + + return (NX_NOT_SUCCESSFUL); + } + + NX_DEBUG_DRIVER_SOURCE_LOG("\n [%06" PRIu32 "] NX_TCPIP_OFFLOAD_TCP_SOCKET_SEND (%" PRIu32 "): TCP sent data with: %04" PRIu32 " bytes\n", + HAL_GetTick(), (uint32_t)i, (uint32_t)sent_size); + + /* Calculate current packet size. */ + packet_size = (ULONG)(current_packet -> nx_packet_append_ptr - current_packet -> nx_packet_prepend_ptr); + + if ((sent_size + offset) < packet_size) + { + /* Partial data sent. Increase the offset. */ + offset += sent_size; + } + else + { + /* Data in current packet are all sent. */ + offset = 0; + +#ifndef NX_DISABLE_PACKET_CHAIN + /* We have crossed the packet boundary. Move to the next packet structure. */ + current_packet = current_packet -> nx_packet_next; +#else + /* End of the loop. */ + current_packet = NX_NULL; +#endif /* NX_DISABLE_PACKET_CHAIN */ + } + } + + /* Release the packet. */ + nx_packet_transmit_release(packet_ptr); + } + break; + + default: + break; + } + + return (status); +} + + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific internal driver functions. */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_initialize PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific initialization. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_info_get Get thread information */ +/* tx_thread_create Create driver thread */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_initialize Driver initialize processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_initialize(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + UINT priority = 0; + + (void)(driver_req_ptr); + + /* Get priority of IP thread. */ + tx_thread_info_get(tx_thread_identify(), NX_NULL, NX_NULL, NX_NULL, &priority, + NX_NULL, NX_NULL, NX_NULL, NX_NULL); + + /* Create the driver thread. */ + /* The priority of network thread is lower than IP thread. */ + status = tx_thread_create(&nx_driver_thread, NX_DRIVER_THREAD_NAME, nx_driver_thread_entry, 0, + nx_driver_thread_stack, NX_DRIVER_STACK_SIZE, + priority + 1, priority + 1, + TX_NO_TIME_SLICE, TX_DONT_START); + + /* Return success! */ + return (status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_enable PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific link enable requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_reset Reset driver thread */ +/* tx_thread_resume Resume driver thread */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_enable Driver link enable processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_enable(NX_IP_DRIVER *driver_req_ptr) +{ + (void)(driver_req_ptr); + + tx_thread_reset(&nx_driver_thread); + tx_thread_resume(&nx_driver_thread); + + /* Return success! */ + return (NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_disable PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific link disable requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_suspend Suspend driver thread */ +/* tx_thread_terminate Terminate driver thread */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_disable Driver link disable processing*/ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_disable(NX_IP_DRIVER *driver_req_ptr) +{ + UINT i; + + (void)(driver_req_ptr); + + /* Reset all sockets. */ + for (i = 0; i < NX_DRIVER_SOCKETS_MAXIMUM; i++) + { + if (nx_driver_sockets[i].socket_ptr) + { + /* Disconnect. */ + WIFI_CloseClientConnection(i); + nx_driver_sockets[i].socket_ptr = NX_NULL; + nx_driver_sockets[i].protocol = 0; + nx_driver_sockets[i].local_port = 0; + nx_driver_sockets[i].local_ip = 0; + nx_driver_sockets[i].remote_ip = 0; + nx_driver_sockets[i].remote_port = 0; + nx_driver_sockets[i].tcp_connected = NX_FALSE; + nx_driver_sockets[i].is_client = NX_FALSE; + } + } + + tx_thread_suspend(&nx_driver_thread); + tx_thread_terminate(&nx_driver_thread); + + /* Return success! */ + return (NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_get_status PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific get status requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR]*/ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_get_status Driver get status processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_get_status(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status = NX_PTR_ERROR; + + if (NULL != driver_req_ptr -> nx_ip_driver_return_ptr) + { + ULONG return_value = NX_FALSE; + if (nx_driver_information.nx_driver_information_state >= NX_DRIVER_STATE_LINK_ENABLED) + { + return_value = NX_TRUE; + } + + *driver_req_ptr -> nx_ip_driver_return_ptr = return_value; + status = NX_SUCCESS; + } + + return status; +} + + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_capability_set PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific capability set requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_capability_set Capability set processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Yuxin Zhou Initial Version 6.x */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_capability_set(NX_IP_DRIVER *driver_req_ptr) +{ + (void)(driver_req_ptr); + + return NX_SUCCESS; +} +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + +#if !defined(REMOVE_DEBUG_FUNC) +#define CASE(x) case x: return #x +#define DEFAULT default: return "UNKNOWN" +static const char *nx_driver_offload_operation_to_string(UINT operation) +{ + switch (operation) + { + CASE(NX_TCPIP_OFFLOAD_TCP_CLIENT_SOCKET_CONNECT); + CASE(NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_LISTEN); + CASE(NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_ACCEPT); + CASE(NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_UNLISTEN); + CASE(NX_TCPIP_OFFLOAD_TCP_SOCKET_DISCONNECT); + CASE(NX_TCPIP_OFFLOAD_TCP_SOCKET_SEND); + CASE(NX_TCPIP_OFFLOAD_UDP_SOCKET_BIND); + CASE(NX_TCPIP_OFFLOAD_UDP_SOCKET_UNBIND); + CASE(NX_TCPIP_OFFLOAD_UDP_SOCKET_SEND); + DEFAULT; + } +} + + +#define CASE(x) case x: return #x +#define DEFAULT default: return "UNKNOWN" +static const char *nx_driver_operation_to_string(UINT operation) +{ + switch (operation) + { + CASE(NX_LINK_PACKET_SEND); + CASE(NX_LINK_INITIALIZE); + CASE(NX_LINK_ENABLE); + CASE(NX_LINK_DISABLE); + CASE(NX_LINK_PACKET_BROADCAST); + CASE(NX_LINK_ARP_SEND); + CASE(NX_LINK_ARP_RESPONSE_SEND); + CASE(NX_LINK_RARP_SEND); + CASE(NX_LINK_MULTICAST_JOIN); + CASE(NX_LINK_MULTICAST_LEAVE); + CASE(NX_LINK_GET_STATUS); + CASE(NX_LINK_GET_SPEED); + CASE(NX_LINK_GET_DUPLEX_TYPE); + CASE(NX_LINK_GET_ERROR_COUNT); + CASE(NX_LINK_GET_RX_COUNT); + CASE(NX_LINK_GET_TX_COUNT); + CASE(NX_LINK_GET_ALLOC_ERRORS); + CASE(NX_LINK_UNINITIALIZE); + CASE(NX_LINK_DEFERRED_PROCESSING); + CASE(NX_LINK_INTERFACE_ATTACH); + CASE(NX_LINK_SET_PHYSICAL_ADDRESS); + CASE(NX_INTERFACE_CAPABILITY_GET); + CASE(NX_INTERFACE_CAPABILITY_SET); + CASE(NX_LINK_INTERFACE_DETACH); + CASE(NX_LINK_FACTORY_ADDRESS_GET); + CASE(NX_LINK_RX_ENABLE); + CASE(NX_LINK_RX_DISABLE); + CASE(NX_LINK_6LOWPAN_COMMAND); + CASE(NX_LINK_GET_INTERFACE_TYPE); + + DEFAULT; + } +} +#endif /* REMOVE_DEBUG_FUNC */ + diff --git a/common/stm32_drivers/wifi/es_wifi/nx_driver_ism43362.h b/common/stm32_drivers/wifi/es_wifi/nx_driver_ism43362.h new file mode 100644 index 00000000..12ad846b --- /dev/null +++ b/common/stm32_drivers/wifi/es_wifi/nx_driver_ism43362.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +/**************************************************************************/ +/* */ +/** */ +/** NetX Component */ +/** */ +/** ES-WiFi driver for the STM32 family of microprocessors */ +/** */ +/* */ +/**************************************************************************/ + +#ifndef NX_DRIVER_ISM43362_H +#define NX_DRIVER_ISM43362_H + + +#ifdef __cplusplus +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { +#endif /* __cplusplus */ + +/* Include ThreadX header file, if not already. */ + +#ifndef TX_API_H +#include "tx_api.h" +#endif /* TX_API_H */ + + +/* Include NetX header file, if not already. */ + +#ifndef NX_API_H +#include "nx_api.h" +#endif /* NX_API_H */ + +#define NX_DRIVER_STATE_NOT_INITIALIZED 1 +#define NX_DRIVER_STATE_INITIALIZE_FAILED 2 +#define NX_DRIVER_STATE_INITIALIZED 3 +#define NX_DRIVER_STATE_LINK_ENABLED 4 + +#define NX_DRIVER_ERROR 90 + +/* Define global driver entry function. */ +VOID nx_driver_ism43362_entry(NX_IP_DRIVER *driver_req_ptr); + +#ifdef __cplusplus +/* Yes, C++ compiler is present. Use standard C. */ +} +#endif /* __cplusplus */ + +#endif /* NX_DRIVER_ISM43362_H */ diff --git a/common/stm32_drivers/wifi/mxchip/mx_wifi_azure_rtos.c b/common/stm32_drivers/wifi/mxchip/mx_wifi_azure_rtos.c new file mode 100644 index 00000000..296e486a --- /dev/null +++ b/common/stm32_drivers/wifi/mxchip/mx_wifi_azure_rtos.c @@ -0,0 +1,255 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#include "mx_wifi.h" +#define NX_DRIVER_SOURCE +#include "nx_driver_emw3080.h" +#include "nx_user.h" +#include + +#if !defined(NX_DEBUG_DRIVER_SOURCE_LOG) +#define NX_DEBUG_DRIVER_SOURCE_LOG(...) /* ; */ +#endif /*NX_DEBUG_DRIVER_SOURCE_LOG*/ + +extern TX_THREAD *_tx_thread_current_ptr; + +extern NX_DRIVER_INFORMATION nx_driver_information; + + +#define MX_WIFI_BYTE_POOL_SIZE (1024 * 4) /* less than 3k is actually used */ + +static ULONG mx_wifi_byte_pool_buffer[MX_WIFI_BYTE_POOL_SIZE / sizeof(ULONG)]; + +static TX_BYTE_POOL mx_wifi_byte_pool; +static CHAR mx_wifi_byte_pool_name[] = "MX WiFi byte pool"; + +UINT mx_wifi_alloc_init(void) +{ + if (tx_byte_pool_create(&mx_wifi_byte_pool, + mx_wifi_byte_pool_name, + mx_wifi_byte_pool_buffer, + MX_WIFI_BYTE_POOL_SIZE)) + { + return NX_DRIVER_ERROR; + } + + return NX_SUCCESS; +} + + +void *mx_wifi_malloc(size_t size) +{ + UINT status; + void *p = NULL; + + status = tx_byte_allocate(&mx_wifi_byte_pool, + &p, + size, + TX_NO_WAIT); + if (status != TX_SUCCESS) + { + return NULL; + } + + MX_ASSERT(p); + + NX_DEBUG_DRIVER_SOURCE_LOG("\n mx_wifi_malloc(): %p (%" PRIu32 ")\n", p, (uint32_t)size); + + return p; +} + + +void mx_wifi_free(void *p) +{ + UINT status; + + MX_ASSERT(p); + + status = tx_byte_release(p); + MX_ASSERT(status == NX_SUCCESS); + + NX_DEBUG_DRIVER_SOURCE_LOG("\n mx_wifi_free() : %p\n", p); +} + + +NX_PACKET *mx_net_buffer_alloc(uint32_t n) +{ + UINT status; + NX_PACKET *packet_ptr; + + if (!nx_driver_information.nx_driver_information_packet_pool_ptr) + { + return NULL; + } + + if (n > nx_driver_information.nx_driver_information_packet_pool_ptr->nx_packet_pool_payload_size) + { + return NULL; + } + + status = nx_packet_allocate(nx_driver_information.nx_driver_information_packet_pool_ptr, + &packet_ptr, + NX_RECEIVE_PACKET, + NX_NO_WAIT); + if (status != NX_SUCCESS) + { + MX_STAT_LOG(); + return NULL; + } + + MX_ASSERT(packet_ptr); + + MX_STAT(alloc); + +#if defined(NX_DEBUG) && defined(NX_ENABLE_PACKET_DEBUG_INFO) + { + const struct NX_PACKET_POOL_STRUCT *const pool_owner = packet_ptr->nx_packet_pool_owner; + + NX_DEBUG_DRIVER_SOURCE_LOG("\n mx_net_buffer_alloc(): allocated %p -> %" PRIu32 ", allocated by \"%s\"\n", + (void *)packet_ptr, (uint32_t)pool_owner->nx_packet_pool_available, packet_ptr->nx_packet_debug_thread); + } +#endif /* NX_DEBUG && NX_ENABLE_PACKET_DEBUG_INFO*/ + + packet_ptr->nx_packet_next = NULL; + packet_ptr->nx_packet_prepend_ptr += 2; + packet_ptr->nx_packet_append_ptr = packet_ptr->nx_packet_prepend_ptr + n; + packet_ptr->nx_packet_length = n; + MX_ASSERT(packet_ptr->nx_packet_append_ptr <= packet_ptr->nx_packet_data_end); + + return packet_ptr; +} + + +void mx_net_buffer_free(NX_PACKET *packet_ptr) +{ + UINT status; + + MX_ASSERT(packet_ptr); + MX_STAT(free); + +#if defined(NX_DEBUG) && defined(NX_ENABLE_PACKET_DEBUG_INFO) + { + const struct NX_PACKET_POOL_STRUCT *const pool_owner = packet_ptr->nx_packet_pool_owner; + + NX_DEBUG_DRIVER_SOURCE_LOG("\n mx_net_buffer_free() : releasing %p, allocated by \"%s\"\n", (void *)packet_ptr, packet_ptr->nx_packet_debug_thread); + + for (UCHAR *p = packet_ptr->nx_packet_data_start; p < packet_ptr->nx_packet_data_end; p++) + { + *p = (UCHAR)'D'; + } +#endif /* NX_DEBUG && NX_ENABLE_PACKET_DEBUG_INFO*/ + + status = nx_packet_release(packet_ptr); + +#if defined(NX_DEBUG) && defined(NX_ENABLE_PACKET_DEBUG_INFO) + NX_DEBUG_DRIVER_SOURCE_LOG("\n mx_net_buffer_free() : -> %" PRIu32 "\n", + (uint32_t)pool_owner->nx_packet_pool_available); + } +#endif /* NX_DEBUG && NX_ENABLE_PACKET_DEBUG_INFO*/ + + MX_ASSERT(status == NX_SUCCESS); +} + + +UINT mx_wifi_thread_init(TX_THREAD *thread_ptr, CHAR *name_ptr, + VOID (*entry_function)(ULONG), ULONG entry_input, + ULONG stack_size, UINT priority) +{ + /* Do not worry about alignment, it is handled by tx_thread_create */ + void *stack = mx_wifi_malloc(stack_size); + MX_ASSERT(stack); + if (!stack) + { + return TX_NO_MEMORY; + } + + return tx_thread_create( + thread_ptr, + name_ptr, + entry_function, entry_input, + stack, stack_size, + priority, priority, + TX_NO_TIME_SLICE, + TX_AUTO_START); +} + + +UINT mx_wifi_thread_deinit(TX_THREAD *thread_ptr) +{ + MX_ASSERT(thread_ptr); + MX_ASSERT(thread_ptr->tx_thread_stack_start); + + mx_wifi_free(thread_ptr->tx_thread_stack_start); + + return tx_thread_delete(thread_ptr); +} + + +void mx_wifi_thread_terminate(void) +{ + tx_thread_terminate(_tx_thread_current_ptr); +} + + +UINT mx_wifi_fifo_init(TX_QUEUE *queue_ptr, CHAR *name_ptr, ULONG size) +{ + void *queue_start = mx_wifi_malloc(size * TX_1_ULONG * sizeof(ULONG)); + MX_ASSERT(queue_start); + if (!queue_start) + { + return TX_NO_MEMORY; + } + + return tx_queue_create( + queue_ptr, + name_ptr, + TX_1_ULONG, + queue_start, + size * sizeof(ULONG)); +} + + +UINT mx_wifi_fifo_deinit(TX_QUEUE *queue_ptr) +{ + MX_ASSERT(queue_ptr); + MX_ASSERT(queue_ptr->tx_queue_start); + + mx_wifi_free(queue_ptr->tx_queue_start); + + return tx_queue_delete(queue_ptr); +} + + +UINT mx_wifi_fifo_push(TX_QUEUE *queue_ptr, void *source_ptr, ULONG wait_option) +{ + MX_ASSERT(queue_ptr); + + NX_DEBUG_DRIVER_SOURCE_LOG("\n mx_wifi_fifo_push(): pushing %p\n", source_ptr); + + return tx_queue_send(queue_ptr, source_ptr, wait_option); +} + + +void *mx_wifi_fifo_pop(TX_QUEUE *queue_ptr, ULONG wait_option) +{ + void *destination_ptr; + + MX_ASSERT(queue_ptr); + + UINT status = tx_queue_receive(queue_ptr, &destination_ptr, wait_option); + if (status != TX_SUCCESS) + { + return NULL; + } + + NX_DEBUG_DRIVER_SOURCE_LOG("\n mx_wifi_fifo_pop() : popping %p\n", destination_ptr); + + return destination_ptr; +} diff --git a/common/stm32_drivers/wifi/mxchip/nx_driver_emw3080.c b/common/stm32_drivers/wifi/mxchip/nx_driver_emw3080.c new file mode 100644 index 00000000..26fc744e --- /dev/null +++ b/common/stm32_drivers/wifi/mxchip/nx_driver_emw3080.c @@ -0,0 +1,401 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#include +#include +#include +#include +#include + +#include "nx_api.h" +#include "mx_wifi.h" +#include "core/mx_address.h" +#include "mx_wifi_conf.h" + + +#ifndef NX_DRIVER_DEFERRED_PROCESSING +#error The symbol NX_DRIVER_DEFERRED_PROCESSING should be defined +#endif /* NX_DRIVER_DEFERRED_PROCESSING */ + +#if !defined(WIFI_SSID) +#error The symbol WIFI_SSID should be defined +#endif /* WIFI_SSID */ + +#if !defined(WIFI_PASSWORD) +#error The symbol WIFI_PASSWORD should be defined +#endif /* WIFI_PASSWORD */ + +#define NX_DRIVER_ENABLE_DEFERRED + +/* Indicate that driver source is being compiled. */ +#define NX_DRIVER_SOURCE + +#if !defined(NX_DEBUG_DRIVER_SOURCE_LOG) +#define NX_DEBUG_DRIVER_SOURCE_LOG(...) /* ; */ +#define REMOVE_DEBUG_FUNC +#endif /*NX_DEBUG_DRIVER_SOURCE_LOG*/ + +#include "nx_driver_emw3080.h" +#include "nx_driver_framework.c" +#include "io_pattern/mx_wifi_io.h" + +/* The station mode is the default. */ +uint8_t WifiMode = MC_STATION; + +static void _nx_netlink_input_callback(mx_buf_t *pbuf, void *user_args); +static void _nx_mx_wifi_status_changed(uint8_t cate, uint8_t status, void *arg); + +static UINT _nx_driver_emw3080_initialize(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_emw3080_enable(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_emw3080_disable(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_emw3080_packet_send(NX_PACKET *packet_ptr); +static UINT _nx_driver_emw3080_interface_status(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_emw3080_packet_received(VOID); + +#if !defined(REMOVE_DEBUG_FUNC) +static const char *nx_driver_mx_wifi_status_to_string(uint8_t status); +#endif /* REMOVE_DEBUG_FUNC */ + +static volatile bool nx_driver_interface_up = false; +static volatile bool nx_driver_ip_acquired = false; + + +void nx_driver_emw3080_entry(NX_IP_DRIVER *driver_req_ptr) +{ + static bool started = false; + + if (!started) + { + nx_driver_hardware_initialize = _nx_driver_emw3080_initialize; + nx_driver_hardware_enable = _nx_driver_emw3080_enable; + nx_driver_hardware_disable = _nx_driver_emw3080_disable; + nx_driver_hardware_packet_send = _nx_driver_emw3080_packet_send; + nx_driver_hardware_get_status = _nx_driver_emw3080_interface_status; + nx_driver_hardware_packet_received = _nx_driver_emw3080_packet_received; + + started = true; + } + + nx_driver_framework_entry_default(driver_req_ptr); +} + + +void nx_driver_emw3080_interrupt(void) +{ + ULONG deffered_events; + + if ((!nx_driver_interface_up) || (!nx_driver_ip_acquired)) + { + return; /* not yet running */ + } + + deffered_events = nx_driver_information.nx_driver_information_deferred_events; + + nx_driver_information.nx_driver_information_deferred_events |= NX_DRIVER_DEFERRED_PACKET_RECEIVED; + + if (!deffered_events) + { + /* Call NetX deferred driver processing. */ + _nx_ip_driver_deferred_processing(nx_driver_information.nx_driver_information_ip_ptr); + } +} + + +static UINT _nx_driver_emw3080_initialize(NX_IP_DRIVER *driver_req_ptr) +{ + (void)(driver_req_ptr); + + if (mx_wifi_alloc_init()) + { + return NX_DRIVER_ERROR; + } + + if (mxwifi_probe(NULL)) + { + return NX_DRIVER_ERROR; + } + + if (MX_WIFI_HardResetModule(wifi_obj_get())) + { + return NX_DRIVER_ERROR; + } + + if (MX_WIFI_Init(wifi_obj_get())) + { + return NX_DRIVER_ERROR; + } + /* Register MAC address that corresponds to STA mode by default. */ + nx_driver_update_hardware_address(wifi_obj_get()->SysInfo.MAC); + + if (MX_WIFI_RegisterStatusCallback_if(wifi_obj_get(), + _nx_mx_wifi_status_changed, + NULL /* void * arg */, + (mwifi_if_t)WifiMode)) + { + return NX_DRIVER_ERROR; + } + + return NX_SUCCESS; +} + + +UINT _nx_driver_emw3080_enable(NX_IP_DRIVER *driver_req_ptr) +{ + (void)(driver_req_ptr); + + if (WifiMode == MC_STATION) + { + NX_DEBUG_DRIVER_SOURCE_LOG("Joining ... \"%s\"\n", WIFI_SSID); + + if (MX_WIFI_STATUS_OK != MX_WIFI_Connect(wifi_obj_get(), WIFI_SSID, WIFI_PASSWORD, MX_WIFI_SEC_AUTO)) + { + return NX_DRIVER_ERROR; + } + } + else + { + MX_WIFI_APSettings_t ApSettings = {{0},{0},0,{{0},{0},{0},{0}}}; + + strncpy(ApSettings.SSID, WIFI_SSID, sizeof(ApSettings.SSID)); + strncpy(ApSettings.pswd, WIFI_PASSWORD, sizeof(ApSettings.pswd)); + ApSettings.channel = 8; + + { + const mx_ip_addr_t ip_addr = { htonl(IP_ADDRESS(0, 0, 0, 0)) }; + strncpy(ApSettings.ip.localip, mx_ntoa(&ip_addr), sizeof(ApSettings.ip.localip) - 1); + ApSettings.ip.localip[sizeof(ApSettings.ip.localip) - 1] = '\0'; + } + { + const mx_ip_addr_t network_mask = { htonl(IP_ADDRESS(0, 0, 0, 0)) }; + strncpy(ApSettings.ip.netmask, mx_ntoa(&network_mask), sizeof(ApSettings.ip.netmask) - 1); + ApSettings.ip.netmask[sizeof(ApSettings.ip.netmask) - 1] = '\0'; + } + { + const mx_ip_addr_t dns_server_addr = { htonl(IP_ADDRESS(0, 0, 0, 0)) }; + strncpy(ApSettings.ip.dnserver, mx_ntoa(&dns_server_addr), sizeof(ApSettings.ip.dnserver) - 1); + ApSettings.ip.dnserver[sizeof(ApSettings.ip.dnserver) - 1] = '\0'; + } + { + const mx_ip_addr_t gateway_addr = { htonl(IP_ADDRESS(0, 0, 0, 0)) }; + strncpy(ApSettings.ip.gateway, mx_ntoa(&gateway_addr), sizeof(ApSettings.ip.gateway) - 1); + ApSettings.ip.gateway[sizeof(ApSettings.ip.gateway) - 1] = '\0'; + } + + NX_DEBUG_DRIVER_SOURCE_LOG("Init Access Point ... \"%s\" with %s\n", ApSettings.SSID, ApSettings.ip.localip); + + if (MX_WIFI_STATUS_OK != MX_WIFI_StartAP(wifi_obj_get(), &ApSettings)) + { + return NX_DRIVER_ERROR; + } + else + { + uint8_t ap_mac[MX_WIFI_MAC_SIZE] = {0}; + + (void)MX_WIFI_GetsoftapMACAddress(wifi_obj_get(), ap_mac); + + /* Register MAC address that corresponds to AP mode. */ + nx_driver_update_hardware_address(ap_mac); + } + } + + while (!nx_driver_interface_up) + { + MX_WIFI_IO_YIELD(wifi_obj_get(), 10 /* timeout */); + } + + if (MX_WIFI_STATUS_OK != MX_WIFI_Network_bypass_mode_set(wifi_obj_get(), + 1 /* enable */, + _nx_netlink_input_callback, + NULL /* user arg */)) + { + return NX_DRIVER_ERROR; + } + + return NX_SUCCESS; +} + + +UINT _nx_driver_emw3080_disable(NX_IP_DRIVER *driver_req_ptr) +{ + (void)(driver_req_ptr); + + MX_WIFI_Network_bypass_mode_set(wifi_obj_get(), 0 /* disable */, NULL, NULL); + + if (MX_WIFI_Disconnect(wifi_obj_get())) + { + return NX_DRIVER_ERROR; + } + + if (MX_WIFI_DeInit(wifi_obj_get())) + { + return NX_DRIVER_ERROR; + } + + return NX_SUCCESS; +} + + +UINT _nx_driver_emw3080_packet_send(NX_PACKET *packet_ptr) +{ + static int errors = 0; + + /* Verify that the length matches the size between the pointers. */ + if (((ptrdiff_t)packet_ptr->nx_packet_length) != (packet_ptr->nx_packet_append_ptr - packet_ptr->nx_packet_prepend_ptr)) + { + return NX_DRIVER_ERROR; + } + + if (packet_ptr->nx_packet_next) + { + NX_DRIVER_PHYSICAL_HEADER_REMOVE(packet_ptr); + nx_packet_transmit_release(packet_ptr); + + MX_STAT(free); + + return NX_DRIVER_ERROR; + } + +#if defined(NX_DEBUG) + if ((packet_ptr->nx_packet_prepend_ptr - packet_ptr->nx_packet_data_start) < 28) + { + NX_DEBUG_DRIVER_SOURCE_LOG("Incorrect NX packet, need at least 28 byte in front of payload, got %d\n", + packet_ptr->nx_packet_prepend_ptr - packet_ptr->nx_packet_data_start); + } +#endif /* NX_DEBUG */ + + { + int32_t interface = (WifiMode == MC_STATION) ? STATION_IDX : SOFTAP_IDX; + + if (MX_WIFI_Network_bypass_netlink_output(wifi_obj_get(), + packet_ptr->nx_packet_prepend_ptr, (int32_t)packet_ptr->nx_packet_length, + interface)) + { + errors++; + } + } + + NX_DRIVER_PHYSICAL_HEADER_REMOVE(packet_ptr); + nx_packet_transmit_release(packet_ptr); + + MX_STAT(free); + + return NX_SUCCESS; +} + + +static void _nx_netlink_input_callback(mx_buf_t *buffer, void *user_args) +{ + NX_PACKET *packet_ptr = buffer; + + (void)(user_args); + + /* Avoid starving. */ + if (packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_available == 0) + { + nx_packet_release(packet_ptr); + + MX_STAT(free); + + return; + } + + /* Everything is OK, transfer the packet to NetX. */ + nx_driver_transfer_to_netx(nx_driver_information.nx_driver_information_ip_ptr, packet_ptr); +} + + +static VOID _nx_driver_emw3080_packet_received(VOID) +{ + MX_WIFI_IO_YIELD(wifi_obj_get(), 100 /* timeout */); +} + + +static UINT _nx_driver_emw3080_interface_status(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status = NX_PTR_ERROR; + + if (NULL != driver_req_ptr -> nx_ip_driver_return_ptr) + { + *driver_req_ptr -> nx_ip_driver_return_ptr = nx_driver_interface_up ? NX_TRUE : NX_FALSE; + status = NX_SUCCESS; + } + + return status; +} + + +static void _nx_mx_wifi_status_changed(uint8_t cate, uint8_t status, void *arg) +{ + (void)(arg); + + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] > %s\n", + HAL_GetTick(), nx_driver_mx_wifi_status_to_string(status)); + + if ((uint8_t)MC_STATION == cate) + { + switch (status) + { + case MWIFI_EVENT_STA_DOWN: + nx_driver_interface_up = false; + break; + + case MWIFI_EVENT_STA_UP: + nx_driver_interface_up = true; + break; + + case MWIFI_EVENT_STA_GOT_IP: + nx_driver_ip_acquired = true; + break; + + default: + break; + } + } + else if ((uint8_t)MC_SOFTAP == cate) + { + switch (status) + { + case MWIFI_EVENT_AP_DOWN: + nx_driver_interface_up = false; + break; + + case MWIFI_EVENT_AP_UP: + nx_driver_interface_up = true; + break; + + default: + break; + } + } + else + { + /* nothing */ + } +} + + +#if !defined(REMOVE_DEBUG_FUNC) +#define CASE(x) case x: return #x +#define DEFAULT default: return "UNKNOWN" +static const char *nx_driver_mx_wifi_status_to_string(uint8_t status) +{ + switch (status) + { + CASE(MWIFI_EVENT_NONE); + CASE(MWIFI_EVENT_STA_DOWN); + CASE(MWIFI_EVENT_STA_UP); + CASE(MWIFI_EVENT_STA_GOT_IP); + CASE(MWIFI_EVENT_AP_DOWN); + CASE(MWIFI_EVENT_AP_UP); + DEFAULT; + } +} +#endif /* REMOVE_DEBUG_FUNC */ + diff --git a/common/stm32_drivers/wifi/mxchip/nx_driver_emw3080.h b/common/stm32_drivers/wifi/mxchip/nx_driver_emw3080.h new file mode 100644 index 00000000..1e6dcaa8 --- /dev/null +++ b/common/stm32_drivers/wifi/mxchip/nx_driver_emw3080.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* */ +/* NetX Component */ +/* */ +/* MX CHIP EMW3080 WiFi driver for the STM32 family of microprocessors */ +/* */ +/* */ +/**************************************************************************/ + +#ifndef NX_DRIVER_EMW3080_H +#define NX_DRIVER_EMW3080_H + + +#ifdef __cplusplus +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { +#endif /* __cplusplus */ + +/* Indicate that driver source is being compiled. */ +#define NX_DRIVER_SOURCE + +/* Include driver framework include file. */ +#include "nx_driver_framework.h" + +/* Public API */ +/* Define global driver entry function. */ +void nx_driver_emw3080_entry(NX_IP_DRIVER *driver_req_ptr); +void nx_driver_emw3080_interrupt(void); + +extern uint8_t WifiMode; + +#ifdef __cplusplus +/* Yes, C++ compiler is present. Use standard C. */ +} +#endif /* __cplusplus */ + +#endif /* NX_DRIVER_EMW3080_H */ diff --git a/common/stm32_drivers/wifi/mxchip/nx_driver_framework.c b/common/stm32_drivers/wifi/mxchip/nx_driver_framework.c new file mode 100644 index 00000000..be0858dc --- /dev/null +++ b/common/stm32_drivers/wifi/mxchip/nx_driver_framework.c @@ -0,0 +1,1587 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** NetX driver framework */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#include + +/* Check that this file is included by the driver source and not compiled directly */ +#ifndef NX_DRIVER_SOURCE +#error This file is included by the driver source, not compiled directly. +#endif /* NX_DRIVER_SOURCE */ + +/* Include driver framework include file. */ +#include "nx_driver_framework.h" + +NX_DRIVER_INFORMATION nx_driver_information; + +static VOID nx_driver_framework_entry_default(NX_IP_DRIVER *driver_req_ptr); + +/* Define the routines for processing each driver entry request. */ +static VOID nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_enable(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_disable(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr); +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +static VOID nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr); +static VOID nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr); +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ +#ifdef NX_DRIVER_ENABLE_DEFERRED +static VOID nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr); +#endif /* NX_DRIVER_ENABLE_DEFERRED */ +static VOID nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr); +static VOID nx_driver_update_hardware_address(UCHAR hardware_address[6]); +#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE +static VOID nx_driver_transmit_packet_enqueue(NX_PACKET *packet_ptr) +static NX_PACKET *nx_driver_transmit_packet_dequeue(VOID) +#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */ + + +/* Define the pointers for the hardware implementation of this driver. */ +static UINT(*nx_driver_hardware_initialize)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_enable)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_disable)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_packet_send)(NX_PACKET *packet_ptr) = NULL; +static UINT(*nx_driver_hardware_multicast_join)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_multicast_leave)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static UINT(*nx_driver_hardware_get_status)(NX_IP_DRIVER *driver_req_ptr) = NULL; +static VOID(*nx_driver_hardware_packet_transmitted)(VOID) = NULL; +static VOID(*nx_driver_hardware_packet_received)(VOID) = NULL; + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +static UINT(*nx_driver_hardware_capability_set)(NX_IP_DRIVER *driver_req_ptr) = NULL; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + + +#if !defined(REMOVE_DEBUG_FUNC) +static const char *nx_driver_operation_to_string(UINT operation); +#endif /* REMOVE_DEBUG_FUNC */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_framework_entry_default PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This is the default entry point processing for the NetX Driver. */ +/* This function should be called by a specific driver to handle */ +/* commands. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr The driver request from the */ +/* IP layer. */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_interface_attach Process attach request */ +/* nx_driver_initialize Process initialize request */ +/* nx_driver_enable Process link enable request */ +/* nx_driver_disable Process link disable request */ +/* nx_driver_packet_send Process send packet requests */ +/* nx_driver_multicast_join Process multicast join request*/ +/* nx_driver_multicast_leave Process multicast leave req */ +/* nx_driver_get_status Process get status request */ +/* nx_driver_deferred_processing Drive deferred processing */ +/* */ +/* CALLED BY */ +/* */ +/* IP layer */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_framework_entry_default(NX_IP_DRIVER *driver_req_ptr) +{ + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] > %s\n", HAL_GetTick(), + nx_driver_operation_to_string(driver_req_ptr -> nx_ip_driver_command)); + + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Process according to the driver request type in the IP control block. */ + switch (driver_req_ptr -> nx_ip_driver_command) + { + + case NX_LINK_INTERFACE_ATTACH: + { + /* Process link interface attach requests. */ + nx_driver_interface_attach(driver_req_ptr); + break; + } + + case NX_LINK_INITIALIZE: + { + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Initialization - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + NX_DEBUG_DRIVER_SOURCE_LOG(" IP Address = %08" PRIX32 "\n", + (uint32_t)driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_address); + + /* Process link initialize requests. */ + nx_driver_initialize(driver_req_ptr); + break; + } + + case NX_LINK_ENABLE: + { + /* Process link enable requests. */ + nx_driver_enable(driver_req_ptr); + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Link Enabled - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + break; + } + + case NX_LINK_DISABLE: + { + /* Process link disable requests. */ + nx_driver_disable(driver_req_ptr); + + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Link Disabled - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + break; + } + + case NX_LINK_ARP_SEND: + case NX_LINK_ARP_RESPONSE_SEND: + case NX_LINK_PACKET_BROADCAST: + case NX_LINK_RARP_SEND: + case NX_LINK_PACKET_SEND: + { + /* Process packet send requests. */ + nx_driver_packet_send(driver_req_ptr); + break; + } + + case NX_LINK_MULTICAST_JOIN: + { + /* Process multicast join requests. */ + nx_driver_multicast_join(driver_req_ptr); + break; + } + + case NX_LINK_MULTICAST_LEAVE: + { + /* Process multicast leave requests. */ + nx_driver_multicast_leave(driver_req_ptr); + break; + } + + case NX_LINK_GET_STATUS: + { + /* Process get status requests. */ + nx_driver_get_status(driver_req_ptr); + break; + } + +#ifdef NX_DRIVER_ENABLE_DEFERRED + case NX_LINK_DEFERRED_PROCESSING: + { + /* Process driver deferred requests. */ + + /* Process a device driver function on behave of the IP thread. */ + nx_driver_deferred_processing(driver_req_ptr); + break; + } +#endif /* NX_DRIVER_ENABLE_DEFERRED */ + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + case NX_INTERFACE_CAPABILITY_GET: + { + /* Process get capability requests. */ + nx_driver_capability_get(driver_req_ptr); + break; + } + + case NX_INTERFACE_CAPABILITY_SET: + { + /* Process set capability requests. */ + nx_driver_capability_set(driver_req_ptr); + break; + } +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + default: + + /* Invalid driver request. */ + + /* Return the unhandled command status. */ + driver_req_ptr -> nx_ip_driver_status = NX_UNHANDLED_COMMAND; + + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver Received invalid request - \"%s\"\n", + driver_req_ptr -> nx_ip_driver_ptr -> nx_ip_name); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_interface_attach PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the interface attach request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr) +{ + /** + * Setup the driver's interface. + * This default implementation is for a simple one-interface driver. + * Additional logic is necessary for multiple port devices. + */ + nx_driver_information.nx_driver_information_interface = driver_req_ptr -> nx_ip_driver_interface; + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + driver_req_ptr -> nx_ip_driver_interface -> nx_interface_capability_flag = NX_DRIVER_CAPABILITY; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + /* Return successful status. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_initialize PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the initialize request. The processing */ +/* in this function is generic. All hardware specific logic goes in */ +/* nx_driver_hardware_initialize. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_initialize Process initialize request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr) +{ + NX_IP *ip_ptr; + NX_INTERFACE *interface_ptr; + UINT status; + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Setup interface pointer. */ + interface_ptr = driver_req_ptr -> nx_ip_driver_interface; + + /* Initialize the driver's information structure. */ + + /* Default IP pointer to NULL. */ + nx_driver_information.nx_driver_information_ip_ptr = NX_NULL; + + /* Setup the driver state to not initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_NOT_INITIALIZED; + + /* Setup the default packet pool for the driver's received packets. */ + nx_driver_information.nx_driver_information_packet_pool_ptr = ip_ptr -> nx_ip_default_packet_pool; + + /* Clear the deferred events for the driver. */ + nx_driver_information.nx_driver_information_deferred_events = 0; + +#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE + /* Clear the transmit queue count and head pointer. */ + nx_driver_information.nx_driver_transmit_packets_queued = 0; + nx_driver_information.nx_driver_transmit_queue_head = NX_NULL; + nx_driver_information.nx_driver_transmit_queue_tail = NX_NULL; +#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */ + + /* Call the hardware-specific WiFi module initialization. */ + if (!nx_driver_hardware_initialize) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_initialize(driver_req_ptr); + } + + /* Determine if the request was successful. */ + if (status == NX_SUCCESS) + { + /* Successful hardware initialization. */ + + /* Setup driver information to point to IP pointer. */ + nx_driver_information.nx_driver_information_ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Setup the link maximum transfer unit. */ + interface_ptr -> nx_interface_ip_mtu_size = NX_DRIVER_MTU - NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Indicate to the IP software that IP to physical mapping + is required. */ + interface_ptr -> nx_interface_address_mapping_needed = NX_TRUE; + + /* Move the driver's state to initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED; + + /* Indicate successful initialize. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + /* Initialization failed. Indicate that the request failed. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_enable PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the initialize request. The processing */ +/* in this function is generic. All hardware specific logic in */ +/* nx_driver_hardware_enable. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_enable Process enable request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_enable(NX_IP_DRIVER *driver_req_ptr) +{ + NX_IP *ip_ptr; + UINT status; + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* See if we can honor the NX_LINK_ENABLE request. */ + if (nx_driver_information.nx_driver_information_state < NX_DRIVER_STATE_INITIALIZED) + { + /* Mark the request as not successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + + /* Check if it is enabled by someone already */ + if (nx_driver_information.nx_driver_information_state >= NX_DRIVER_STATE_LINK_ENABLED) + { + /* Yes, the request has already been made. */ + driver_req_ptr -> nx_ip_driver_status = NX_ALREADY_ENABLED; + return; + } + + /* Call hardware specific enable. */ + if (!nx_driver_hardware_enable) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_enable(driver_req_ptr); + } + + /* Was the hardware enable successful? */ + if (status == NX_SUCCESS) + { + /* Update the driver state to link enabled. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_LINK_ENABLED; + + /* Mark request as successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Mark the IP instance as link up. */ + ip_ptr -> nx_ip_driver_link_up = NX_TRUE; + } + else + { + /* Enable failed. Indicate that the request failed. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_disable PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the disable request. The processing */ +/* in this function is generic. All hardware specific logic in */ +/* nx_driver_hardware_disable. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_disable Process disable request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_disable(NX_IP_DRIVER *driver_req_ptr) +{ + NX_IP *ip_ptr; + UINT status; + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Check if the link is enabled. */ + if (nx_driver_information.nx_driver_information_state != NX_DRIVER_STATE_LINK_ENABLED) + { + /* The link is not enabled, so just return an error. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + + /* Call hardware specific disable. */ + if (!nx_driver_hardware_disable) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_disable(driver_req_ptr); + } + + /* Was the hardware disable successful? */ + if (status == NX_SUCCESS) + { + /* Mark the IP instance as link down. */ + ip_ptr -> nx_ip_driver_link_up = NX_FALSE; + + /* Update the driver state back to initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED; + + /* Mark request as successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + /* Disable failed, return an error. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_packet_send PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the packet send request. The processing */ +/* in this function is generic. All hardware specific logic is in */ +/* nx_driver_hardware_packet_send. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_packet_send Process packet send request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr) +{ + NX_IP *ip_ptr; + NX_PACKET *packet_ptr; + ULONG *ethernet_frame_ptr; + UINT status; + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Check to make sure the link is up. */ + if (nx_driver_information.nx_driver_information_state != NX_DRIVER_STATE_LINK_ENABLED) + { + /* Indicate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(driver_req_ptr -> nx_ip_driver_packet); + + MX_STAT(free); + + return; + } + + /* Process driver send packet. */ + + /* Place the Ethernet frame at the front of the packet. */ + packet_ptr = driver_req_ptr -> nx_ip_driver_packet; + + + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] nx_driver_packet_send() with 0x%" PRIX32 " bytes\n", + HAL_GetTick(), (uint32_t)packet_ptr -> nx_packet_length); + + + /* Adjust the prepend pointer. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr - NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /** + * Setup the ethernet frame pointer to build the ethernet frame. + * Backup another 2 * bytes to get 32-bit word alignment. + */ + ethernet_frame_ptr = (ULONG *)(packet_ptr -> nx_packet_prepend_ptr - 2); + + /* Set up the hardware addresses in the Ethernet header. */ + *ethernet_frame_ptr = driver_req_ptr -> nx_ip_driver_physical_address_msw; + *(ethernet_frame_ptr + 1) = driver_req_ptr -> nx_ip_driver_physical_address_lsw; + + *(ethernet_frame_ptr + 2) = (ip_ptr -> nx_ip_arp_physical_address_msw << 16) | + (ip_ptr -> nx_ip_arp_physical_address_lsw >> 16); + *(ethernet_frame_ptr + 3) = (ip_ptr -> nx_ip_arp_physical_address_lsw << 16); + + /* Set up the frame type field in the Ethernet header. */ + if ((driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_SEND) || + (driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_RESPONSE_SEND)) + { + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_ARP; + } + else if (driver_req_ptr -> nx_ip_driver_command == NX_LINK_RARP_SEND) + { + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_RARP; + } +#ifdef FEATURE_NX_IPV6 + else if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6) + { + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_IPV6; + } +#endif /* FEATURE_NX_IPV6 */ + else + { + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_IP; + } + + /* Endian swapping if NX_LITTLE_ENDIAN is defined. */ + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 1)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 2)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 3)); + + /* Determine if the packet exceeds the driver's MTU. */ + if (packet_ptr -> nx_packet_length > NX_DRIVER_MTU) + { + /* This packet exceeds the size of the driver's MTU. Simply throw it away! */ + + /* Remove the Ethernet header. */ + NX_DRIVER_PHYSICAL_HEADER_REMOVE(packet_ptr); + + /* Indicate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(packet_ptr); + + MX_STAT(free); + + return; + } + + /* Transmit the packet through the WiFi controller low level access routine. */ + if (!nx_driver_hardware_packet_send) + { + status = NX_DRIVER_ERROR; + } + else + { + NX_DEBUG_DRIVER_SOURCE_LOG("\n* %" PRIX32 " %" PRIX32 " %" PRIX32 " %" PRIX32 " *\n", + (uint32_t)ethernet_frame_ptr[0], (uint32_t)ethernet_frame_ptr[1], + (uint32_t)ethernet_frame_ptr[2], (uint32_t)ethernet_frame_ptr[3]); + + + status = nx_driver_hardware_packet_send(packet_ptr); + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + /* Driver's hardware send packet routine failed to send the packet. */ + + /* Remove the Ethernet header. */ + NX_DRIVER_PHYSICAL_HEADER_REMOVE(packet_ptr); + + /* Indicate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(packet_ptr); + + MX_STAT(free); + } + else + { + /* Set the status of the request. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_multicast_join PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the multicast join request. The processing */ +/* in this function is generic. All hardware specific logic is in */ +/* nx_driver_hardware_multicast_join. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_multicast_join Process multicast join request*/ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + + /* Call hardware specific multicast join function. */ + if (!nx_driver_hardware_multicast_join) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_multicast_join(driver_req_ptr); + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver multicast join returns: NX_DRIVER_ERROR\n"); + /* Call hardware specific multicast join function. */ + } + else + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_multicast_leave PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the multicast leave request. The code */ +/* in this function is generic. All hardware specific logic is in */ +/* nx_driver_hardware_multicast_leave. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_multicast_leave Process multicast leave req */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + + /* Call hardware specific multicast leave function. */ + if (!nx_driver_hardware_multicast_leave) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_multicast_leave(driver_req_ptr); + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + NX_DEBUG_DRIVER_SOURCE_LOG("\nNetX WiFi Driver multicast leave returns: NX_DRIVER_ERROR\n"); + } + else + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_get_status PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the get status request. The processing */ +/* in this function is generic. All hardware specific logic is in */ +/* nx_driver_hardware_get_status. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_hardware_get_status Process get status request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr) +{ + /* Call hardware specific get status function. */ + if (!nx_driver_hardware_get_status) + { + driver_req_ptr -> nx_ip_driver_status = NX_UNHANDLED_COMMAND; + } + else + { + UINT status = nx_driver_hardware_get_status(driver_req_ptr); + + if (status == NX_SUCCESS) + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + } +} + + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_capability_get PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the get capability request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr) +{ + /* Return the capability of the WiFi controller. */ + *(driver_req_ptr -> nx_ip_driver_return_ptr) = NX_DRIVER_CAPABILITY; + + /* Return the success status. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_capability_set PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the set capability request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr) +{ + UINT status; + + /* Call hardware specific get status function. */ + if (!nx_driver_hardware_capability_set) + { + status = NX_SUCCESS; + } + else + { + status = nx_driver_hardware_capability_set(driver_req_ptr); + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + else + { + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + +#ifdef NX_DRIVER_ENABLE_DEFERRED +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_deferred_processing PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the deferred ISR action within the context */ +/* of the IP thread. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_driver_packet_transmitted Clean up after transmission */ +/* nx_driver_packet_received Process a received packet */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr) +{ + TX_INTERRUPT_SAVE_AREA + + ULONG deferred_events; + + /* Disable interrupts. */ + TX_DISABLE + + /* Pickup deferred events. */ + deferred_events = nx_driver_information.nx_driver_information_deferred_events; + nx_driver_information.nx_driver_information_deferred_events = 0; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for a transmit complete event. */ + if (deferred_events & NX_DRIVER_DEFERRED_PACKET_TRANSMITTED) + { + /* Process transmitted packet(s). */ + if (nx_driver_hardware_packet_transmitted) + { + nx_driver_hardware_packet_transmitted(); + } + } + + /* Check for received packet. */ + if (deferred_events & NX_DRIVER_DEFERRED_PACKET_RECEIVED) + { + /* Process received packet(s). */ + if (nx_driver_hardware_packet_received) + { + nx_driver_hardware_packet_received(); + } + } + + /* Mark request as successful. */ + driver_req_ptr->nx_ip_driver_status = NX_SUCCESS; +} +#endif /* NX_DRIVER_ENABLE_DEFERRED */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_transfer_to_netx PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing incoming packets. This routine would */ +/* be called from the driver-specific receive packet processing */ +/* function nx_driver_hardware_packet_received. */ +/* */ +/* INPUT */ +/* */ +/* ip_ptr Pointer to IP protocol block */ +/* packet_ptr Packet pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Error indication */ +/* */ +/* CALLS */ +/* */ +/* _nx_ip_packet_receive NetX IP packet receive */ +/* _nx_ip_packet_deferred_receive NetX IP packet receive */ +/* _nx_arp_packet_deferred_receive NetX ARP packet receive */ +/* _nx_rarp_packet_deferred_receive NetX RARP packet receive */ +/* _nx_packet_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* nx_driver_hardware_packet_received Driver packet receive function*/ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr) +{ + /* Pickup the packet header to determine where the packet needs to be sent. */ + const USHORT packet_type = (USHORT)((USHORT)(((USHORT)(*(packet_ptr -> nx_packet_prepend_ptr + 12))) << 8) | + (USHORT)(*(packet_ptr -> nx_packet_prepend_ptr + 13))); + + /* NX_DEBUG_DRIVER_SOURCE_LOG("\n%s() 0x%" PRIx32 "\n", __FUNCTION__, (uint32_t)packet_type); */ + + /* Set the interface for the incoming packet. */ + packet_ptr -> nx_packet_ip_interface = nx_driver_information.nx_driver_information_interface; + + /* Route the incoming packet according to its Ethernet type. */ + if ((packet_type == NX_DRIVER_ETHERNET_IP) || (packet_type == NX_DRIVER_ETHERNET_IPV6)) + { + /* Note: The length reported by some Ethernet hardware includes + bytes after the packet as well as the Ethernet header. In some + cases, the actual packet length after the Ethernet header should + be derived from the length in the IP header (lower 16 bits of + the first 32-bit word). */ + + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = + packet_ptr -> nx_packet_length - NX_DRIVER_PHYSICAL_FRAME_SIZE; + + NX_DEBUG_DRIVER_SOURCE_LOG("\n[%06" PRIu32 "] < NX_DRIVER_ETHERNET_IP(V6) with (%p) %" PRIu32 " bytes\n", + HAL_GetTick(), (void *)packet_ptr, (uint32_t)packet_ptr -> nx_packet_length); + +#ifdef NX_DEBUG + { + const ULONG ip_tcp_headers_size = 40; + for (ULONG i = ip_tcp_headers_size ; i < (packet_ptr -> nx_packet_length - ip_tcp_headers_size); i++) + { + NX_DEBUG_DRIVER_SOURCE_LOG("%02X", packet_ptr -> nx_packet_prepend_ptr[i]); + } + } +#endif /* NX_DEBUG */ + + /* Route to the ip receive function. */ +#ifdef NX_DRIVER_ENABLE_DEFERRED + _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr); +#else + _nx_ip_packet_receive(ip_ptr, packet_ptr); +#endif /* NX_DRIVER_ENABLE_DEFERRED */ + } + else if (packet_type == NX_DRIVER_ETHERNET_ARP) + { + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = + packet_ptr -> nx_packet_length - NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Route to the ARP receive function. */ + _nx_arp_packet_deferred_receive(ip_ptr, packet_ptr); + } + else if (packet_type == NX_DRIVER_ETHERNET_RARP) + { + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = + packet_ptr -> nx_packet_length - NX_DRIVER_PHYSICAL_FRAME_SIZE; + + /* Route to the RARP receive function. */ + _nx_rarp_packet_deferred_receive(ip_ptr, packet_ptr); + } + else + { + /* Invalid Ethernet header... release the packet. */ + nx_packet_release(packet_ptr); + } + + /* Consider that in the nominal case, the packets are correctly processed and released. */ + MX_STAT(free); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_update_hardware_address PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function updates the hardware address kept by the driver. */ +/* The hardware address is used when constructing send packets and to */ +/* filter incoming packets. */ +/* */ +/* INPUT */ +/* */ +/* hardware_address The new hardware address */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* nx_driver_initialize Driver initialization function*/ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_update_hardware_address(UCHAR hardware_address[6]) +{ + NX_INTERFACE *interface_ptr; + + /* Setup interface pointer. */ + interface_ptr = nx_driver_information.nx_driver_information_interface; + + /** + * Setup the physical address of this IP instance. Increment the + * physical address lsw to simulate multiple nodes hanging on the + * Ethernet. + */ + interface_ptr -> nx_interface_physical_address_msw = + ((ULONG)(((ULONG)hardware_address[0]) << 8)) | + ((ULONG)hardware_address[1]); + interface_ptr -> nx_interface_physical_address_lsw = + ((ULONG)(((ULONG)hardware_address[2]) << 24)) | + ((ULONG)((ULONG)(hardware_address[3]) << 16)) | + ((ULONG)((ULONG)(hardware_address[4]) << 8)) | + ((ULONG)hardware_address[5]); +} + + +#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_transmit_packet_enqueue PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function queues a transmit packet when the hardware transmit */ +/* queue does not have the resources (buffer descriptors, etc.) to */ +/* send the packet. The queue is maintained as a singularly linked- */ +/* list with head and tail pointers. The maximum number of packets on */ +/* the transmit queue is regulated by the constant */ +/* NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH. When this number is exceeded, */ +/* the oldest packet is discarded after the new packet is queued. */ +/* */ +/* Note: that it is assumed further driver interrupts are locked out */ +/* during the call to this driver utility. */ +/* */ +/* INPUT */ +/* */ +/* packet_ptr Packet pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_packet_transmit_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* nx_driver_hardware_packet_send Driver packet send function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static VOID nx_driver_transmit_packet_enqueue(NX_PACKET *packet_ptr) +{ + /* Determine if there is anything on the queue. */ + if (nx_driver_information.nx_driver_transmit_queue_tail) + { + /* Yes, something is on the transmit queue. Simply add the new packet to the tail. */ + nx_driver_information.nx_driver_transmit_queue_tail -> nx_packet_queue_next = packet_ptr; + + /* Update the tail pointer. */ + nx_driver_information.nx_driver_transmit_queue_tail = packet_ptr; + } + else + { + /* First packet on the transmit queue. */ + + /* Setup head pointers. */ + nx_driver_information.nx_driver_transmit_queue_head = packet_ptr; + nx_driver_information.nx_driver_transmit_queue_tail = packet_ptr; + + /* Set the packet's next pointer to NULL. */ + packet_ptr -> nx_packet_queue_next = NX_NULL; + } + + /* Increment the total packets queued. */ + nx_driver_information.nx_driver_transmit_packets_queued++; + + /* Determine if the total packet queued exceeds the driver's maximum transmit + queue depth. */ + if (nx_driver_information.nx_driver_transmit_packets_queued > NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH) + { + /* Yes, remove the head packet (oldest) packet in the transmit queue and release it. */ + packet_ptr = nx_driver_information.nx_driver_transmit_queue_head; + + /* Adjust the head pointer to the next packet. */ + nx_driver_information.nx_driver_transmit_queue_head = packet_ptr -> nx_packet_queue_next; + + /* Decrement the transmit packet queued count. */ + nx_driver_information.nx_driver_transmit_packets_queued--; + + /* Remove the Ethernet header. */ + NX_DRIVER_PHYSICAL_HEADER_REMOVE(packet_ptr); + + /* Release the packet. */ + nx_packet_transmit_release(packet_ptr); + + MX_STAT(free); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_transmit_packet_dequeue PORTABLE C */ +/* 6.x */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function removes the oldest transmit packet when the hardware */ +/* transmit queue has new resources (usually after a transmit complete */ +/* interrupt) to send the packet. If there are no packets in the */ +/* transmit queue, a NULL is returned. */ +/* */ +/* Note: that it is assumed further driver interrupts are locked out */ +/* during the call to this driver utility. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* packet_ptr Packet pointer */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* nx_driver_hardware_packet_send Driver packet send function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Andres Mlinar Initial Version 6.x */ +/* */ +/**************************************************************************/ +static NX_PACKET *nx_driver_transmit_packet_dequeue(VOID) +{ + NX_PACKET *packet_ptr; + + /* Pickup the head pointer of the transmit packet queue. */ + packet_ptr = nx_driver_information.nx_driver_transmit_queue_head; + + /* Determine if there is anything on the queue. */ + if (packet_ptr) + { + /* Yes, something is on the transmit queue. Simply the packet from the head of the queue. */ + + /* Update the head pointer. */ + nx_driver_information.nx_driver_transmit_queue_head = packet_ptr -> nx_packet_queue_next; + + /* Clear the next pointer in the packet. */ + packet_ptr -> nx_packet_queue_next = NX_NULL; + + /* Decrement the transmit packet queued count. */ + nx_driver_information.nx_driver_transmit_packets_queued--; + } + + /* Return the packet pointer - NULL if there are no packets queued. */ + return (packet_ptr); +} +#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */ + +#if !defined(REMOVE_DEBUG_FUNC) +#define CASE(x) case x: return #x +#define DEFAULT default: return "UNKNOWN" +static const char *nx_driver_operation_to_string(UINT operation) +{ + switch (operation) + { + CASE(NX_LINK_PACKET_SEND); + CASE(NX_LINK_INITIALIZE); + CASE(NX_LINK_ENABLE); + CASE(NX_LINK_DISABLE); + CASE(NX_LINK_PACKET_BROADCAST); + CASE(NX_LINK_ARP_SEND); + CASE(NX_LINK_ARP_RESPONSE_SEND); + CASE(NX_LINK_RARP_SEND); + CASE(NX_LINK_MULTICAST_JOIN); + CASE(NX_LINK_MULTICAST_LEAVE); + CASE(NX_LINK_GET_STATUS); + CASE(NX_LINK_GET_SPEED); + CASE(NX_LINK_GET_DUPLEX_TYPE); + CASE(NX_LINK_GET_ERROR_COUNT); + CASE(NX_LINK_GET_RX_COUNT); + CASE(NX_LINK_GET_TX_COUNT); + CASE(NX_LINK_GET_ALLOC_ERRORS); + CASE(NX_LINK_UNINITIALIZE); + CASE(NX_LINK_DEFERRED_PROCESSING); + CASE(NX_LINK_INTERFACE_ATTACH); + CASE(NX_LINK_SET_PHYSICAL_ADDRESS); + CASE(NX_INTERFACE_CAPABILITY_GET); + CASE(NX_INTERFACE_CAPABILITY_SET); + CASE(NX_LINK_INTERFACE_DETACH); + CASE(NX_LINK_FACTORY_ADDRESS_GET); + CASE(NX_LINK_RX_ENABLE); + CASE(NX_LINK_RX_DISABLE); + CASE(NX_LINK_6LOWPAN_COMMAND); + CASE(NX_LINK_GET_INTERFACE_TYPE); + + DEFAULT; + } +} +#endif /* REMOVE_DEBUG_FUNC */ diff --git a/common/stm32_drivers/wifi/mxchip/nx_driver_framework.h b/common/stm32_drivers/wifi/mxchip/nx_driver_framework.h new file mode 100644 index 00000000..8018cbfd --- /dev/null +++ b/common/stm32_drivers/wifi/mxchip/nx_driver_framework.h @@ -0,0 +1,138 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** NetX driver framework */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef NX_DRIVER_FRAMEWORK_H +#define NX_DRIVER_FRAMEWORK_H + + +#ifdef __cplusplus +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { +#endif /* __cplusplus */ + + +/* Include ThreadX header file, if not already. */ + +#ifndef TX_API_H +#include "tx_api.h" +#endif /* TX_API_H */ + + +/* Include NetX header file, if not already. */ + +#ifndef NX_API_H +#include "nx_api.h" +#endif /* NX_API_H */ + + +#define NX_DRIVER_MTU (1514) +#define NX_DRIVER_PHYSICAL_FRAME_SIZE (14) + +/* MIPC_HEADER_SIZE(6) + sizeof(wifi_bypass_in_rparams_t)(22) */ + +#define NX_DRIVER_PACKET_SIZE (NX_DRIVER_MTU + 28 + 2) + +#define NX_DRIVER_PHYSICAL_HEADER_REMOVE(p) \ + do { \ + p -> nx_packet_prepend_ptr += NX_DRIVER_PHYSICAL_FRAME_SIZE; \ + p -> nx_packet_length -= NX_DRIVER_PHYSICAL_FRAME_SIZE; \ + } while (0) + +struct NX_DRIVER_INFORMATION_STRUCT; + + +/** + * Determine if the driver's source file is being compiled. + * The constants and typedefs are only valid within + * the driver's source file compilation. + */ + +#ifdef NX_DRIVER_SOURCE + + +/* Define generic constants and macros for all NetX drivers. */ + +#define NX_DRIVER_STATE_NOT_INITIALIZED 1 +#define NX_DRIVER_STATE_INITIALIZE_FAILED 2 +#define NX_DRIVER_STATE_INITIALIZED 3 +#define NX_DRIVER_STATE_LINK_ENABLED 4 + +#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE +#ifndef NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH +#define NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH 10 +#endif /* NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH */ +#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */ + +#define NX_DRIVER_DEFERRED_PACKET_RECEIVED 1 +#define NX_DRIVER_DEFERRED_DEVICE_RESET 2 +#define NX_DRIVER_DEFERRED_PACKET_TRANSMITTED 4 + +#define NX_DRIVER_ERROR 90 + +#ifndef NX_DRIVER_CAPABILITY +#define NX_DRIVER_CAPABILITY ( 0 ) +#endif /* NX_DRIVER_CAPABILITY */ + +/* Define generic constants and macros for all NetX Ethernet drivers. */ + +#define NX_DRIVER_ETHERNET_IP 0x0800 +#define NX_DRIVER_ETHERNET_IPV6 0x86dd +#define NX_DRIVER_ETHERNET_ARP 0x0806 +#define NX_DRIVER_ETHERNET_RARP 0x8035 + + +/** + * Define basic Ethernet driver information typedef. + * Note that this typedefs is designed to be used only + * in the driver's C file. + */ + +typedef struct NX_DRIVER_INFORMATION_STRUCT +{ + /* NetX IP instance that this driver is attached to. */ + NX_IP *nx_driver_information_ip_ptr; + + /* Driver's current state. */ + ULONG nx_driver_information_state ; + + /* Packet pool used for receiving packets. */ + NX_PACKET_POOL *nx_driver_information_packet_pool_ptr; + + /* Define the driver interface association. */ + NX_INTERFACE *nx_driver_information_interface; + + /* Define the deferred event field. This will contain bits representing events + deferred from the ISR for processing in the thread context. */ + ULONG nx_driver_information_deferred_events; + +} NX_DRIVER_INFORMATION; + +#endif /* NX_DRIVER_SOURCE */ + + +/* Define default driver entry function. */ +VOID nx_driver_framework_default_entry(NX_IP_DRIVER *driver_req_ptr); + +#ifdef __cplusplus +/* Yes, C++ compiler is present. Use standard C. */ +} +#endif /* __cplusplus */ + +#endif /* NX_DRIVER_FRAMEWORK_H */