/**
* 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);
                }
            }
Example #2
0
/**
 * @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;
}