/** * Node Commands * * This function is part of the callback system for the Ethernet transport * and will be executed when a valid node commands is recevied. * * @param Command Header - WARPNet Command Header * Command Arguments - WARPNet Command Arguments * Response Header - WARPNet Response Header * Response Arguments - WARPNet Response Arguments * Packet Source - Ethernet Packet Source * Ethernet Device Number - Indicates which Ethernet device packet came from * * @return None. * * @note See on-line documentation for more information about the ethernet * packet structure for WARPNet: www.warpproject.org * ******************************************************************************/ int node_processCmd(const wn_cmdHdr* cmdHdr,const void* cmdArgs, wn_respHdr* respHdr,void* respArgs, void* pktSrc, unsigned int eth_dev_num){ //IMPORTANT ENDIAN NOTES: // -cmdHdr is safe to access directly (pre-swapped if needed) // -cmdArgs is *not* pre-swapped, since the framework doesn't know what it is // -respHdr will be swapped by the framework; user code should fill it normally // -respArgs will *not* be swapped by the framework, since only user code knows what it is // Any data added to respArgs by the code below must be endian-safe (swapped on AXI hardware) int status = 0; const u32 * cmdArgs32 = cmdArgs; u32 * respArgs32 = respArgs; unsigned int respIndex = 0; unsigned int respSent = NO_RESP_SENT; unsigned int max_words = 320; // Max number of u32 words that can be sent in the packet (~1400 bytes) // If we need more, then we will need to rework this to send multiple response packets unsigned int temp, i; // Variables for functions u32 id; u32 flags; u32 start_address; u32 curr_address; u32 next_address; u32 size; u32 evt_log_size; u32 transfer_size; u32 bytes_per_pkt; u32 num_bytes; u32 num_pkts; u32 interval; unsigned int cmdID; cmdID = WN_CMD_TO_CMDID(cmdHdr->cmd); respHdr->cmd = cmdHdr->cmd; respHdr->length = 0; respHdr->numArgs = 0; #ifdef _DEBUG_ xil_printf("In node_processCmd(): ID = %d \n", cmdID); #endif switch(cmdID){ //--------------------------------------------------------------------- case WARPNET_TYPE: // Return the WARPNet Type respArgs32[respIndex++] = Xil_Htonl( node_info.type ); respHdr->length += (respIndex * sizeof(respArgs32)); respHdr->numArgs = respIndex; break; //--------------------------------------------------------------------- case NODE_INFO: // Return the info about the WLAN_EXP_NODE // Send node parameters temp = node_get_parameters( &respArgs32[respIndex], max_words, TRANSMIT_OVER_NETWORK); respIndex += temp; max_words -= temp; if ( max_words <= 0 ) { xil_printf("No more space left in NODE_INFO packet \n"); }; // Send transport parameters temp = transport_get_parameters( eth_dev_num, &respArgs32[respIndex], max_words, TRANSMIT_OVER_NETWORK); respIndex += temp; max_words -= temp; if ( max_words <= 0 ) { xil_printf("No more space left in NODE_INFO packet \n"); }; #ifdef _DEBUG_ xil_printf("NODE INFO: \n"); for ( i = 0; i < respIndex; i++ ) { xil_printf(" [%2d] = 0x%8x \n", i, respArgs32[i]); } xil_printf("END NODE INFO \n"); #endif // -------------------------------- // Future parameters go here // -------------------------------- // Finalize response respHdr->length += (respIndex * sizeof(respArgs32)); respHdr->numArgs = respIndex; break; //--------------------------------------------------------------------- case NODE_IDENTIFY: // Return Null Response // The WLAN_EXP_NODE currently does not have access to LEDs xil_printf(" Node: %d IP Address: %d.%d.%d.%d \n", node_info.node, node_info.ip_addr[0], node_info.ip_addr[1],node_info.ip_addr[2],node_info.ip_addr[3]); // -------------------------------- // TODO: Add in visual identifiers for the node // -------------------------------- break; //--------------------------------------------------------------------- case NODE_CONFIG_SETUP: // NODE_CONFIG_SETUP Packet Format: // - Note: All u32 parameters in cmdArgs32 are byte swapped so use Xil_Ntohl() // // - cmdArgs32[0] - Serial Number // - cmdArgs32[1] - Node ID // - cmdArgs32[2] - IP Address // - cmdArgs32[3] - Unicast Port // - cmdArgs32[4] - Broadcast Port // if ( node_info.node == 0xFFFF ) { // Only update the parameters if the serial numbers match if ( node_info.serial_number == Xil_Ntohl(cmdArgs32[0]) ) { xil_printf(" Reconfiguring ETH %c \n", wn_conv_eth_dev_num(eth_dev_num) ); node_info.node = Xil_Ntohl(cmdArgs32[1]) & 0xFFFF; xil_printf(" New Node ID : %d \n", node_info.node); // Grab New IP Address node_info.ip_addr[0] = (Xil_Ntohl(cmdArgs32[2]) >> 24) & 0xFF; node_info.ip_addr[1] = (Xil_Ntohl(cmdArgs32[2]) >> 16) & 0xFF; node_info.ip_addr[2] = (Xil_Ntohl(cmdArgs32[2]) >> 8) & 0xFF; node_info.ip_addr[3] = (Xil_Ntohl(cmdArgs32[2]) ) & 0xFF; // Grab new ports node_info.unicast_port = Xil_Ntohl(cmdArgs32[3]); node_info.broadcast_port = Xil_Ntohl(cmdArgs32[4]); xil_printf(" New IP Address : %d.%d.%d.%d \n", node_info.ip_addr[0], node_info.ip_addr[1],node_info.ip_addr[2],node_info.ip_addr[3]); xil_printf(" New Unicast Port : %d \n", node_info.unicast_port); xil_printf(" New Broadcast Port: %d \n", node_info.broadcast_port); transport_set_hw_info( eth_dev_num, node_info.ip_addr, node_info.hw_addr); status = transport_config_sockets(eth_dev_num, node_info.unicast_port, node_info.broadcast_port); if(status != 0) { xil_printf("Error binding transport...\n"); } } else { xil_printf("NODE_IP_SETUP Packet with Serial Number %d ignored. My serial number is %d \n", Xil_Ntohl(cmdArgs32[0]), node_info.serial_number); } }
/** * @brief Transport subsystem initialization * * Initializes the transport subsystem * * @param eth_dev_num - Ethernet device number * @param node_info - Pointer to the Node info structure (wlan_exp_node_info) * @param ip_addr - Pointer to IP address for transport * @param hw_addr - Pointer to HW address (MAC address) for transport * @param unicast_port - Unicast port for transport * @param broadcast_port - Broadcast port for transport * * @return int - Status of the command: * XST_SUCCESS - Command completed successfully * XST_FAILURE - There was an error in the command ******************************************************************************/ int transport_init(u32 eth_dev_num, void * node_info, u8 * ip_addr, u8 * hw_addr, u16 unicast_port, u16 broadcast_port) { int status = XST_SUCCESS; // Print initialization message wlan_exp_printf(WLAN_EXP_PRINT_NONE, NULL, "Configuring transport ...\n"); // Initialize the User callback for processing a packet process_hton_msg_callback = wlan_exp_null_callback; // Check that we are initializing a valid Ethernet device for the transport if (transport_check_device(eth_dev_num) != XST_SUCCESS) { return XST_FAILURE; } // Initialize the WARP IP/UDP transport warp_ip_udp_init(); // Print MAC address and IP address wlan_exp_printf(WLAN_EXP_PRINT_NONE, NULL, " ETH %c MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", warp_conv_eth_dev_num(eth_dev_num), hw_addr[0], hw_addr[1], hw_addr[2], hw_addr[3], hw_addr[4], hw_addr[5]); wlan_exp_printf(WLAN_EXP_PRINT_NONE, NULL, " ETH %c IP Address: %d.%d.%d.%d\n", warp_conv_eth_dev_num(eth_dev_num), ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); // Initialize the Ethernet device (use verbose mode) status = eth_init(eth_dev_num, hw_addr, ip_addr, WLAN_EXP_TRUE); if (status != XST_SUCCESS) { wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Ethernet %c initialization error\n", warp_conv_eth_dev_num(eth_dev_num)); } // Set interrupt callbacks // NOTE: The WLAN project uses interrupts so we should make sure to disable // interrupts when sending Ethernet packets. This step must be done after // the call to eth_init(). eth_set_interrupt_enable_callback((void *)wlan_mac_high_interrupt_restore_state); eth_set_interrupt_disable_callback((void *)wlan_mac_high_interrupt_stop); // Initialize the transport_eth_dev_info structure for the Ethernet device transport_eth_dev_info_init(eth_dev_num, (wlan_exp_node_info *)node_info, ip_addr, hw_addr, unicast_port, broadcast_port); // Set the Ethernet link speed if (WLAN_EXP_NEGOTIATE_ETH_LINK_SPEED) { // Enable auto-negotiation in the Ethernet PHY transport_set_eth_phy_auto_negotiation(eth_dev_num, WLAN_EXP_ENABLE); // Update the link speed transport_update_link_speed(eth_dev_num, ETH_WAIT_FOR_AUTO_NEGOTIATION); } else { // Disable auto-negotiation in the Ethernet PHY transport_set_eth_phy_auto_negotiation(eth_dev_num, WLAN_EXP_DISABLE); // Update the link speed transport_update_link_speed(eth_dev_num, ETH_DO_NOT_WAIT_FOR_AUTO_NEGOTIATION); } // Start Ethernet device status = eth_start_device(eth_dev_num); if (status != XST_SUCCESS) { wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Cannot start Ethernet %c\n", warp_conv_eth_dev_num(eth_dev_num)); } // Configure the Sockets for each Ethernet Interface status = transport_config_sockets(eth_dev_num, unicast_port, broadcast_port, 1); if (status != XST_SUCCESS) { wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Cannot configure sockets for Ethernet %c\n", warp_conv_eth_dev_num(eth_dev_num)); } // Initialize the tag parameters transport_init_parameters(eth_dev_num, (u32 *) &(eth_devices[eth_dev_num].info)); return status; }