INT rt28xx_ioctl(
	IN	PNET_DEV	net_dev, 
	IN	OUT	struct ifreq	*rq, 
	IN	INT					cmd)
{
	RTMP_ADAPTER	*pAd = NULL;
	INT				ret = 0;

	GET_PAD_FROM_NET_DEV(pAd, net_dev);	

	if (pAd == NULL)
	{
		/* if 1st open fail, pAd will be free;
		   So the net_dev->priv will be NULL in 2rd open */
		return -ENETDOWN;
	}

#ifdef CONFIG_AP_SUPPORT
	IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
	{
		ret = rt28xx_ap_ioctl(net_dev, rq, cmd);
	}
#endif // CONFIG_AP_SUPPORT //

#ifdef CONFIG_STA_SUPPORT
	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
	{
		ret = rt28xx_sta_ioctl(net_dev, rq, cmd);
	}
#endif // CONFIG_STA_SUPPORT //

	return ret;
}
static void update_mat_table(void)
{
	struct eth_drv_sc *sc = NULL;
	cyg_netdevtab_entry_t *t;

	for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++){
		sc = (struct eth_drv_sc *)t->device_instance;
		if (strcmp(sc->dev_name, TRAFFICD_IF_AP) == 0){
			break;
		}
	}

	if(sc){
		struct iwreq iwr;
		int status;
		memset(&iwr, 0, sizeof(iwr));
		iwr.u.data.pointer = (caddr_t) mat_callback;
		iwr.u.data.flags = RTPRIV_IOCTL_MAT_CALLBACK;
		iwr.u.data.flags |= OID_GET_SET_TOGGLE;
		iwr.u.data.length = sizeof(caddr_t);
		status = rt28xx_ap_ioctl(sc, RTPRIV_IOCTL_MAT_CALLBACK, (caddr_t)&iwr);
		dlog("set mat_callback [%d]\n", status);
	}


#if 0
	char line[200], ip[100], hw[100];
	int num;
	struct hw_node *hw_node;
	struct ip_node *ip_node;
	FILE *fp;


	/* Open the PROCps kernel table. */
	if ((fp = fopen(PROC_MAT_TABLE_FILE, "r")) == NULL) {
		D(SYSTEM, "fopen %s error\n", PROC_MAT_TABLE_FILE);
		return;
	}

	for (; fgets(line, sizeof(line), fp);) {
		num = sscanf(line, "%100s %100s\n",
				ip, hw);
		if (num < 2)
			break;
		upper_nstring(hw, HWAMAXLEN);

		hw_node = trafficd_hw_get(hw, true);
		ip_node = trafficd_ip_get(ip, true);
		if(hw_node && ip_node &&
				ip_node->hw != hw_node){
			ip_node->hw = hw_node;
			list_del(&ip_node->list);
			list_add(&ip_node->list, &hw_node->ip_list);
		}
	}
	fclose(fp);
#endif
}
int RT_ioctl(
		int 			sid, 
		int 			param, 
		char  			*data, 
		int 			data_len, 
		char 			*prefix_name, 
		unsigned char 	apidx, 
		int 			flags)
{
    char			name[12];
    int				ret = 1;
    struct iwreq	wrq;

#ifdef __ECOS
	cyg_netdevtab_entry_t *t;
	struct eth_drv_sc *sc;
	int found = 0;
#endif

	memset(name,'\0',12);
    	sprintf(name, "ra%d", apidx);
    	name[3] = '\0';
    	wrq.u.data.flags = flags;
	wrq.u.data.length = data_len;
    	wrq.u.data.pointer = (caddr_t) data;
#ifdef __ECOS
	for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) 
	{
		sc = (struct eth_drv_sc *)t->device_instance;
		if (strcmp(sc->dev_name, name) == 0) {
			found =1;
			break;
	        }
	}

	if ( found == 1 )
	{
		if ((ret=rt28xx_ap_ioctl(sc, param, (caddr_t)&wrq)) < 0)
		{
			diag_printf("RTPRIV_IOCTL_SET has error.\n");
		}
	}
	else
	{
		diag_printf("Can't find ra0.\n");
		ret=1;
	}
		
#endif//__ECOS
#ifdef LINUX
    ret = ioctl(sid, param, &wrq);	
 #endif
    return ret;
}
int system_init()
{
	struct eth_drv_sc *sc = NULL;
	cyg_netdevtab_entry_t *t;

	if(!sys->cfg.is_router && sys->tbus_ctx){
		sd = calloc(1, sizeof(* sd));
		if (!sd){
			elog("calloc failed\n");
			return -1;
		}

		arp = calloc(1, sizeof(struct arp_table) +
				ARP_DEFAULT_SIZE * sizeof(struct _arp_entry));
		if(!arp){
			elog("calloc failed\n");
			return -1;
		}
		arp->size = ARP_DEFAULT_SIZE;

		dlog("set timeout_init\n");
		sd->timeout_init.cb = init_loop_cb;
		dlog("set timeout_mat\n");
		sd->timeout_mat.cb = mat_loop_cb;
		if(sys->init_mode){
			uloop_timeout_set(&sd->timeout_init, TRAFFICD_INIT_LOOP_TIME);
		}else{
			uloop_timeout_set(&sd->timeout_mat, TRAFFICD_WIFIAP_LOOP_TIME);
		}
	}

	for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++){
		sc = (struct eth_drv_sc *)t->device_instance;
		if (strcmp(sc->dev_name, TRAFFICD_IF_AP) == 0){
			break;
		}
	}

	if(sc){
		struct iwreq iwr;
		int status;
		memset(&iwr, 0, sizeof(iwr));
		iwr.u.data.pointer = (caddr_t) iw_callback;
		iwr.u.data.flags = RTPRIV_IOCTL_IW_CALLBACK;
		iwr.u.data.flags |= OID_GET_SET_TOGGLE;
		iwr.u.data.length = sizeof(caddr_t);
		status = rt28xx_ap_ioctl(sc, RTPRIV_IOCTL_IW_CALLBACK, (caddr_t)&iwr);
		dlog("!!Set callback for 2.4G device[%d]\n", status);
	}

	return 0;
}
static void refresh_arp_table(void)
{
#ifdef __ECOS
	int idx = 0;
	struct iwreq iwr;
	RT_802_11_MAC_TABLE MacTab;
	struct eth_drv_sc       *sc;
	cyg_netdevtab_entry_t   *t;
	int found = 0;
	char hw[HWAMAXLEN];

	memset(&iwr, 0, sizeof(iwr));
	memset(&MacTab, 0, sizeof(RT_802_11_MAC_TABLE));
	iwr.u.data.pointer = (caddr_t) &MacTab;
    for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {
        sc = (struct eth_drv_sc *)t->device_instance;
        if (strcmp(sc->dev_name, TRAFFICD_IF_AP) == 0) {
            found = 1;
            break;
        }
    }

    if (found == 1) {
        if(rt28xx_ap_ioctl(sc, RTPRIV_IOCTL_GET_MAC_TABLE,
					(caddr_t)&iwr) < 0) {
            elog("RTPRIV_IOCTL_GET_MAC_TABLE sock fail!!\n");
			arp->size = 0;
            return;
        }
    } else {
		arp->size = 0;
        return;
    }

	reset_arp_table();
	for (idx = 0; idx < MacTab.Num; idx++){
		if(MacTab.Entry[idx].TxRate.field.MODE >= 2){
			snprintf((char *)hw, HWAMAXLEN, "%02X:%02X:%02X:%02X:%02X:%02X",
				MacTab.Entry[idx].Addr[0], MacTab.Entry[idx].Addr[1],
				MacTab.Entry[idx].Addr[2], MacTab.Entry[idx].Addr[3],
				MacTab.Entry[idx].Addr[4], MacTab.Entry[idx].Addr[5]);
			push_arp(hw, 0);
		}
	}
#endif
}
void system_show_assoclist(void)
{
	int idx = 0;
	struct iwreq iwr;
	RT_802_11_MAC_TABLE MacTab;
	struct eth_drv_sc       *sc;
	cyg_netdevtab_entry_t   *t;
	int found = 0;

	memset(&iwr, 0, sizeof(iwr));
	memset(&MacTab, 0, sizeof(RT_802_11_MAC_TABLE));
	iwr.u.data.pointer = (caddr_t) &MacTab;
    for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {
        sc = (struct eth_drv_sc *)t->device_instance;
        if (strcmp(sc->dev_name, TRAFFICD_IF_AP) == 0) {
            found = 1;
            break;
        }
    }

    if (found == 1) {
        if(rt28xx_ap_ioctl(sc, RTPRIV_IOCTL_GET_MAC_TABLE, (caddr_t)&iwr) < 0) {
            dlog("RTPRIV_IOCTL_GET_MAC_TABLE sock fail!!\n");
            return;
        }
    } else {
        return;
    }

	for (idx = 0; idx < MacTab.Num; idx++){
		if(MacTab.Entry[idx].TxRate.field.MODE >= 2){
			D(SYSTEM, "%02X:%02X:%02X:%02X:%02X:%02X",
				MacTab.Entry[idx].Addr[0], MacTab.Entry[idx].Addr[1],
				MacTab.Entry[idx].Addr[2], MacTab.Entry[idx].Addr[3],
				MacTab.Entry[idx].Addr[4], MacTab.Entry[idx].Addr[5]);
		}
	}
}
//static char TempString[8192];
int CmdIwpriv(int argc, char *argv[])
{
	int cmd;
	cyg_netdevtab_entry_t *t;
	struct eth_drv_sc *sc;
	struct iwreq param;
	int found = 0;

	if ( argc < 2 )
                goto error_exit;

        if ((strcmp(argv[0], "ra0") != 0 )
                && (strcmp(argv[0], "ra1") != 0 )
                && (strcmp(argv[0], "ra2") != 0 )
                && (strcmp(argv[0], "ra3") != 0 )
                && (strcmp(argv[0], "ra4") != 0 )
                && (strcmp(argv[0], "ra5") != 0 )
                && (strcmp(argv[0], "ra6") != 0 )
                && (strcmp(argv[0], "ra7") != 0 )
                && (strcmp(argv[0], "wds0") != 0 )
                && (strcmp(argv[0], "apcli0") != 0 )
                && (strcmp(argv[0], "mesh0") != 0 )
        )
                goto error_exit;

        memset(&param, 0, sizeof(struct iwreq));

	if ( strcmp(argv[1], "set") == 0 )
	{
		cmd = RTPRIV_IOCTL_SET;
	} 
	else if ( strcmp(argv[1], "show") == 0 )
	{
		cmd = RTPRIV_IOCTL_SHOW;
	} 
	else if ( strcmp(argv[1], "e2p") == 0 )
	{
		cmd = RTPRIV_IOCTL_E2P;
	} 
	else if ( strcmp(argv[1], "bbp") == 0 )
	{
		cmd = RTPRIV_IOCTL_BBP;
                param.u.data.flags |= (RTPRIV_IOCTL_FLAG_NOSPACE | RTPRIV_IOCTL_FLAG_NODUMPMSG);
	} 
	else if ( strcmp(argv[1], "mac") == 0 )
	{
		cmd = RTPRIV_IOCTL_MAC;
                param.u.data.flags |= (RTPRIV_IOCTL_FLAG_NOSPACE | RTPRIV_IOCTL_FLAG_NODUMPMSG);
	} 
	else if ( strcmp(argv[1], "rf") == 0 )
	{
		cmd = RTPRIV_IOCTL_RF;
                param.u.data.flags |= (RTPRIV_IOCTL_FLAG_NOSPACE | RTPRIV_IOCTL_FLAG_NODUMPMSG);
	} 
	else if (( strcmp(argv[1], "GetSiteSurvey") == 0 ) ||( strcmp(argv[1], "get_site_survey") == 0 ))
	{
		cmd = RTPRIV_IOCTL_GSITESURVEY;
                param.u.data.flags |= (RTPRIV_IOCTL_FLAG_NOSPACE | RTPRIV_IOCTL_FLAG_NODUMPMSG);
	}                 
	else if ( strcmp(argv[1], "stat") == 0 )
	{
		cmd = RTPRIV_IOCTL_STATISTICS;
                param.u.data.flags |= (RTPRIV_IOCTL_FLAG_NOSPACE | RTPRIV_IOCTL_FLAG_NODUMPMSG);
	}
	else 
	{
                goto error_exit;
	}

	for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) 
	{
		sc = (struct eth_drv_sc *)t->device_instance;
		if (strcmp(sc->dev_name, argv[0]) == 0) {
			found =1;
			break;
	        }
	}

	if ( found == 1 )
	{
		char *TempString=NULL;
		int original_length = 0;
		
		TempString =malloc(7168);//7*1024
		if(TempString==NULL){diag_printf("Not enough memory for CmdIwpriv!\n");return FALSE;}	    
		 TempString[0] = '\0';

		if ( argc > 2 )
		{              
			sprintf(&TempString[0], "%s", argv[2]);
			original_length = strlen(argv[2]);
		}
		
		param.u.data.pointer = &TempString[0];                
		param.u.data.length = strlen(TempString);
		//diag_printf("cmd:%s [%d][%d]",TempString,param.u.data.length,original_length);
		rt28xx_ap_ioctl(sc, cmd, (caddr_t)&param);
		
		if (param.u.data.length != original_length)
		{
			TempString[param.u.data.length] = '\0';
			diag_printf("%s", TempString);
		}
		
		free(TempString);
    		return TRUE;			
	}	
    
error_exit:
	diag_printf("usage: iwpriv <interface> set|show|e2p|bbp|mac|rf <command>\n");
	diag_printf("usage: iwpriv <interface> stat|GetSiteSurvey\n");
	return FALSE;    
}