// This function will be called when query /proc struct iw_statistics *rt28xx_get_wireless_stats( IN struct net_device *net_dev) { PRTMP_ADAPTER pAd = NULL; #ifdef CONFIG_AP_SUPPORT PMAC_TABLE_ENTRY pMacEntry = NULL; #endif // CONFIG_AP_SUPPORT // GET_PAD_FROM_NET_DEV(pAd, net_dev); #ifdef CONFIG_AP_SUPPORT if (pAd->OpMode == OPMODE_AP) { #ifdef APCLI_SUPPORT if (RT_DEV_PRIV_FLAGS_GET(net_dev) == INT_APCLI) { INT ApCliIdx = ApCliIfLookUp(pAd, (PUCHAR)net_dev->dev_addr); if ((ApCliIdx >= 0) && VALID_WCID(pAd->ApCfg.ApCliTab[ApCliIdx].MacTabWCID)) pMacEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[ApCliIdx].MacTabWCID]; } else #endif // APCLI_SUPPORT // { /* only AP client support wireless stats function. return NULL pointer for all other cases. */ pMacEntry = &pAd->MacTab.Content[0]; } } #endif // CONFIG_AP_SUPPORT // DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_get_wireless_stats --->\n")); //check if the interface is down if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) return NULL; pAd->iw_stats.status = 0; // Status - device dependent for now // link quality #ifdef CONFIG_AP_SUPPORT if (pAd->OpMode == OPMODE_AP) { if (pMacEntry != NULL) pAd->iw_stats.qual.qual = ((pMacEntry->ChannelQuality * 12)/10 + 10); } #endif // CONFIG_AP_SUPPORT // if(pAd->iw_stats.qual.qual > 100) pAd->iw_stats.qual.qual = 100; #ifdef CONFIG_AP_SUPPORT if (pAd->OpMode == OPMODE_AP) { if (pMacEntry != NULL) pAd->iw_stats.qual.level = RTMPMaxRssi(pAd, pMacEntry->RssiSample.AvgRssi0, pMacEntry->RssiSample.AvgRssi1, pMacEntry->RssiSample.AvgRssi2); } #endif // CONFIG_AP_SUPPORT // #ifdef CONFIG_AP_SUPPORT pAd->iw_stats.qual.noise = RTMPMaxRssi(pAd, pAd->ApCfg.RssiSample.AvgRssi0, pAd->ApCfg.RssiSample.AvgRssi1, pAd->ApCfg.RssiSample.AvgRssi2) - RTMPMinSnr(pAd, pAd->ApCfg.RssiSample.AvgSnr0, pAd->ApCfg.RssiSample.AvgSnr1); #endif // CONFIG_AP_SUPPORT // pAd->iw_stats.qual.updated = 1; // Flags to know if updated #ifdef IW_QUAL_DBM pAd->iw_stats.qual.updated |= IW_QUAL_DBM; // Level + Noise are dBm #endif // IW_QUAL_DBM // pAd->iw_stats.discard.nwid = 0; // Rx : Wrong nwid/essid pAd->iw_stats.miss.beacon = 0; // Missed beacons/superframe DBGPRINT(RT_DEBUG_TRACE, ("<--- rt28xx_get_wireless_stats\n")); return &pAd->iw_stats; }
int rt28xx_ap_ioctl( IN struct net_device *net_dev, IN OUT struct ifreq *rq, IN int cmd) { VOID *pAd = NULL; struct iwreq *wrqin = (struct iwreq *) rq; RTMP_IOCTL_INPUT_STRUCT rt_wrq, *wrq = &rt_wrq; int Status = NDIS_STATUS_SUCCESS; USHORT subcmd; /*, index; */ /* POS_COOKIE pObj; */ int apidx=0; UINT32 org_len; RT_CMD_AP_IOCTL_CONFIG IoctlConfig, *pIoctlConfig = &IoctlConfig; GET_PAD_FROM_NET_DEV(pAd, net_dev); /* pObj = (POS_COOKIE) pAd->OS_Cookie; */ if (pAd == NULL) { /* if 1st open fail, pAd will be free; So the net_dev->priv will be NULL in 2rd open */ return -ENETDOWN; } wrq->u.data.pointer = wrqin->u.data.pointer; wrq->u.data.length = wrqin->u.data.length; org_len = wrq->u.data.length; pIoctlConfig->Status = 0; pIoctlConfig->net_dev = net_dev; pIoctlConfig->priv_flags = RT_DEV_PRIV_FLAGS_GET(net_dev); pIoctlConfig->pCmdData = wrqin->u.data.pointer; pIoctlConfig->CmdId_RTPRIV_IOCTL_SET = RTPRIV_IOCTL_SET; pIoctlConfig->name = net_dev->name; pIoctlConfig->apidx = 0; if ((cmd != SIOCGIWPRIV) && RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_PREPARE, 0, pIoctlConfig, 0) != NDIS_STATUS_SUCCESS) { /* prepare error */ Status = pIoctlConfig->Status; goto LabelExit; } apidx = pIoctlConfig->apidx; /*+ patch for SnapGear Request even the interface is down */ if(cmd== SIOCGIWNAME){ DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWNAME\n")); RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_SIOCGIWNAME, 0, wrqin->u.name, 0); return Status; }/*- patch for SnapGear */ switch(cmd) { case RTPRIV_IOCTL_ATE: { RTMP_COM_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_ATE, 0, wrqin->ifr_name, 0); } break; case SIOCGIFHWADDR: DBGPRINT(RT_DEBUG_TRACE, ("IOCTLIOCTLIOCTL::SIOCGIFHWADDR\n")); RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_AP_SIOCGIFHWADDR, 0, NULL, 0); /* if (pObj->ioctl_if < MAX_MBSSID_NUM(pAd)) */ /* strcpy((PSTRING) wrq->u.name, (PSTRING) pAd->ApCfg.MBSSID[pObj->ioctl_if].Bssid); */ break; case SIOCSIWESSID: /*Set ESSID */ break; case SIOCGIWESSID: /*Get ESSID */ { RT_CMD_AP_IOCTL_SSID IoctlSSID, *pIoctlSSID = &IoctlSSID; struct iw_point *erq = &wrqin->u.essid; PCHAR pSsidStr = NULL; erq->flags=1; /*erq->length = pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen; */ pIoctlSSID->priv_flags = RT_DEV_PRIV_FLAGS_GET(net_dev); pIoctlSSID->apidx = apidx; RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_AP_SIOCGIWESSID, 0, pIoctlSSID, 0); pSsidStr = (PCHAR)pIoctlSSID->pSsidStr; erq->length = pIoctlSSID->length; if((erq->pointer) && (pSsidStr != NULL)) { /*if(copy_to_user(erq->pointer, pAd->ApCfg.MBSSID[pObj->ioctl_if].Ssid, erq->length)) */ if(copy_to_user(erq->pointer, pSsidStr, erq->length)) { Status = RTMP_IO_EFAULT; break; } } DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWESSID (Len=%d, ssid=%s...)\n", erq->length, (char *)erq->pointer)); } break; case SIOCGIWNWID: /* get network id */ case SIOCSIWNWID: /* set network id (the cell) */ Status = RTMP_IO_EOPNOTSUPP; break; case SIOCGIWFREQ: /* get channel/frequency (Hz) */ { ULONG Channel; RTMP_DRIVER_CHANNEL_GET(pAd, &Channel); wrqin->u.freq.m = Channel; /*pAd->CommonCfg.Channel; */ wrqin->u.freq.e = 0; wrqin->u.freq.i = 0; } break; case SIOCSIWFREQ: /*set channel/frequency (Hz) */ Status = RTMP_IO_EOPNOTSUPP; break; case SIOCGIWNICKN: case SIOCSIWNICKN: /*set node name/nickname */ Status = RTMP_IO_EOPNOTSUPP; break; case SIOCGIWRATE: /*get default bit rate (bps) */ { RT_CMD_IOCTL_RATE IoctlRate, *pIoctlRate = &IoctlRate; pIoctlRate->priv_flags = RT_DEV_PRIV_FLAGS_GET(net_dev); RTMP_DRIVER_BITRATE_GET(pAd, pIoctlRate); wrqin->u.bitrate.value = pIoctlRate->BitRate; wrqin->u.bitrate.disabled = 0; } break; case SIOCSIWRATE: /*set default bit rate (bps) */ case SIOCGIWRTS: /* get RTS/CTS threshold (bytes) */ case SIOCSIWRTS: /*set RTS/CTS threshold (bytes) */ case SIOCGIWFRAG: /*get fragmentation thr (bytes) */ case SIOCSIWFRAG: /*set fragmentation thr (bytes) */ case SIOCGIWENCODE: /*get encoding token & mode */ case SIOCSIWENCODE: /*set encoding token & mode */ Status = RTMP_IO_EOPNOTSUPP; break; case SIOCGIWAP: /*get access point MAC addresses */ { /* PCHAR pBssidStr; */ wrqin->u.ap_addr.sa_family = ARPHRD_ETHER; /*memcpy(wrqin->u.ap_addr.sa_data, &pAd->ApCfg.MBSSID[pObj->ioctl_if].Bssid, ETH_ALEN); */ RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_AP_SIOCGIWAP, 0, wrqin->u.ap_addr.sa_data, RT_DEV_PRIV_FLAGS_GET(net_dev)); } break; case SIOCGIWMODE: /*get operation mode */ wrqin->u.mode = IW_MODE_INFRA; /*SoftAP always on INFRA mode. */ break; case SIOCSIWAP: /*set access point MAC addresses */ case SIOCSIWMODE: /*set operation mode */ case SIOCGIWSENS: /*get sensitivity (dBm) */ case SIOCSIWSENS: /*set sensitivity (dBm) */ case SIOCGIWPOWER: /*get Power Management settings */ case SIOCSIWPOWER: /*set Power Management settings */ case SIOCGIWTXPOW: /*get transmit power (dBm) */ case SIOCSIWTXPOW: /*set transmit power (dBm) */ /*case SIOCGIWRANGE: //Get range of parameters */ case SIOCGIWRETRY: /*get retry limits and lifetime */ case SIOCSIWRETRY: /*set retry limits and lifetime */ Status = RTMP_IO_EOPNOTSUPP; break; case SIOCGIWRANGE: /*Get range of parameters */ { /* struct iw_range range; */ struct iw_range *prange = NULL; UINT32 len; /* allocate memory */ os_alloc_mem(NULL, (UCHAR **)&prange, sizeof(struct iw_range)); if (prange == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); break; } memset(prange, 0, sizeof(struct iw_range)); prange->we_version_compiled = WIRELESS_EXT; prange->we_version_source = 14; /* what is correct max? This was not documented exactly. At least 69 has been observed. */ prange->max_qual.qual = 100; prange->max_qual.level = 0; /* dB */ prange->max_qual.noise = 0; /* dB */ len = copy_to_user(wrq->u.data.pointer, prange, sizeof(struct iw_range)); os_free_mem(NULL, prange); } break; case RT_PRIV_IOCTL: case RT_PRIV_IOCTL_EXT: { subcmd = wrqin->u.data.flags; Status = RTMP_AP_IoctlHandle(pAd, wrq, CMD_RT_PRIV_IOCTL, subcmd, wrqin->u.data.pointer, 0); } break; #ifdef HOSTAPD_SUPPORT case SIOCSIWGENIE: DBGPRINT(RT_DEBUG_TRACE,("ioctl SIOCSIWGENIE apidx=%d\n",apidx)); DBGPRINT(RT_DEBUG_TRACE,("ioctl SIOCSIWGENIE length=%d, pointer=%x\n", wrqin->u.data.length, wrqin->u.data.pointer)); RTMP_AP_IoctlHandle(pAd, wrqin, CMD_RTPRIV_IOCTL_AP_SIOCSIWGENIE, 0, NULL, 0); break; #endif /* HOSTAPD_SUPPORT */ case SIOCGIWPRIV: if (wrqin->u.data.pointer) { if ( access_ok(VERIFY_WRITE, wrqin->u.data.pointer, sizeof(ap_privtab)) != TRUE) break; if ((sizeof(ap_privtab) / sizeof(ap_privtab[0])) <= wrq->u.data.length) { wrqin->u.data.length = sizeof(ap_privtab) / sizeof(ap_privtab[0]); if (copy_to_user(wrqin->u.data.pointer, ap_privtab, sizeof(ap_privtab))) Status = RTMP_IO_EFAULT; } else Status = RTMP_IO_E2BIG; } break; case RTPRIV_IOCTL_SET: { if( access_ok(VERIFY_READ, wrqin->u.data.pointer, wrqin->u.data.length) == TRUE) Status = RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_SET, 0, NULL, 0); } break; case RTPRIV_IOCTL_SHOW: { if( access_ok(VERIFY_READ, wrqin->u.data.pointer, wrqin->u.data.length) == TRUE) Status = RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_SHOW, 0, NULL, 0); } break; #ifdef INF_AR9 #ifdef AR9_MAPI_SUPPORT case RTPRIV_IOCTL_GET_AR9_SHOW: { if( access_ok(VERIFY_READ, wrqin->u.data.pointer, wrqin->u.data.length) == TRUE) Status = RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_GET_AR9_SHOW, 0, NULL, 0); } break; #endif /*AR9_MAPI_SUPPORT*/ #endif /* INF_AR9 */ #ifdef WSC_AP_SUPPORT case RTPRIV_IOCTL_SET_WSCOOB: RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_SET_WSCOOB, 0, NULL, 0); break; #endif/*WSC_AP_SUPPORT*/ /* modified by Red@Ralink, 2009/09/30 */ case RTPRIV_IOCTL_GET_MAC_TABLE: RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_GET_MAC_TABLE, 0, NULL, 0); break; case RTPRIV_IOCTL_GET_MAC_TABLE_STRUCT: RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_GET_MAC_TABLE_STRUCT, 0, NULL, 0); break; /* end of modification */ #ifdef AP_SCAN_SUPPORT case RTPRIV_IOCTL_GSITESURVEY: RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_GSITESURVEY, 0, NULL, 0); break; #endif /* AP_SCAN_SUPPORT */ case RTPRIV_IOCTL_STATISTICS: RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_STATISTICS, 0, NULL, 0); break; #ifdef WSC_AP_SUPPORT case RTPRIV_IOCTL_WSC_PROFILE: RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_WSC_PROFILE, 0, NULL, 0); break; #endif /* WSC_AP_SUPPORT */ #ifdef DOT11_N_SUPPORT case RTPRIV_IOCTL_QUERY_BATABLE: RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_QUERY_BATABLE, 0, NULL, 0); break; #endif /* DOT11_N_SUPPORT */ case RTPRIV_IOCTL_E2P: RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_E2P, 0, NULL, 0); break; #ifdef DBG case RTPRIV_IOCTL_BBP: RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_BBP, 0, NULL, 0); break; case RTPRIV_IOCTL_MAC: RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_MAC, 0, NULL, 0); break; #ifdef RTMP_RF_RW_SUPPORT case RTPRIV_IOCTL_RF: RTMP_AP_IoctlHandle(pAd, wrq, CMD_RTPRIV_IOCTL_RF, 0, NULL, 0); break; #endif /* RTMP_RF_RW_SUPPORT */ #endif /* DBG */ default: /* DBGPRINT(RT_DEBUG_ERROR, ("IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd)); */ Status = RTMP_IO_EOPNOTSUPP; break; } LabelExit: if (Status != 0) { RT_CMD_STATUS_TRANSLATE(Status); } else { /* If wrq length is modified, we reset the lenght of origin wrq; Or we can not modify it because the address of wrq->u.data.length maybe same as other union field, ex: iw_range, etc. if the length is not changed but we change it, the value for other union will also be changed, this is not correct. */ if (wrq->u.data.length != org_len) wrqin->u.data.length = wrq->u.data.length; } return Status; }
/* ======================================================================== Routine Description: Open raxx interface. Arguments: *net_dev the raxx interface pointer Return Value: 0 Open OK otherwise Open Fail Note: ======================================================================== */ int rt28xx_open(IN PNET_DEV dev) { struct net_device * net_dev = (struct net_device *)dev; PRTMP_ADAPTER pAd = NULL; int retval = 0; //POS_COOKIE pObj; GET_PAD_FROM_NET_DEV(pAd, net_dev); // Sanity check for pAd if (pAd == NULL) { /* if 1st open fail, pAd will be free; So the net_dev->priv will be NULL in 2rd open */ return -1; } #ifdef CONFIG_APSTA_MIXED_SUPPORT if (pAd->OpMode == OPMODE_AP) { CW_MAX_IN_BITS = 6; } else if (pAd->OpMode == OPMODE_STA) { CW_MAX_IN_BITS = 10; } #endif // CONFIG_APSTA_MIXED_SUPPORT // #if WIRELESS_EXT >= 12 if (RT_DEV_PRIV_FLAGS_GET(net_dev) == INT_MAIN) { #ifdef CONFIG_APSTA_MIXED_SUPPORT if (pAd->OpMode == OPMODE_AP) net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_ap_iw_handler_def; #endif // CONFIG_APSTA_MIXED_SUPPORT // } #endif // WIRELESS_EXT >= 12 // // Request interrupt service routine for PCI device // register the interrupt routine with the os /* AP Channel auto-selection will be run in rt28xx_init(), so we must reqister IRQ hander here. */ RtmpOSIRQRequest(net_dev); // Init IRQ parameters stored in pAd RTMP_IRQ_INIT(pAd); // Chip & other init if (rt28xx_init(pAd, mac, hostname) == FALSE) goto err; #ifdef LINUX #ifdef RT_CFG80211_SUPPORT RT_CFG80211_REINIT(pAd); RT_CFG80211_CRDA_REG_RULE_APPLY(pAd); #endif // RT_CFG80211_SUPPORT // #endif // LINUX // // Enable Interrupt RTMP_IRQ_ENABLE(pAd); // Now Enable RxTx RTMPEnableRxTx(pAd); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); { UINT32 reg = 0; RTMP_IO_READ32(pAd, 0x1300, ®); // clear garbage interrupts if (reg); DBGPRINT(RT_DEBUG_TRACE, ("0x1300 = %08x\n", reg)); } { // u32 reg; // UINT8 byte; // u16 tmp; // RTMP_IO_READ32(pAd, XIFS_TIME_CFG, ®); // tmp = 0x0805; // reg = (reg & 0xffff0000) | tmp; // RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, reg); } #ifdef CONFIG_AP_SUPPORT #ifdef BG_FT_SUPPORT BG_FTPH_Init(); #endif // BG_FT_SUPPORT // #endif // CONFIG_AP_SUPPORT // #ifdef VENDOR_FEATURE2_SUPPORT printk("Number of Packet Allocated in open = %d\n", pAd->NumOfPktAlloc); printk("Number of Packet Freed in open = %d\n", pAd->NumOfPktFree); #endif // VENDOR_FEATURE2_SUPPORT // return (retval); err: //+++Add by shiang, move from rt28xx_init() to here. RtmpOSIRQRelease(net_dev); //---Add by shiang, move from rt28xx_init() to here. return (-1); } /* End of rt28xx_open */
/* ======================================================================== Routine Description: return ethernet statistics counter Arguments: net_dev Pointer to net_device Return Value: net_device_stats* Note: ======================================================================== */ static struct net_device_stats *RT28xx_get_wds_ether_stats( IN struct net_device *net_dev) { RTMP_ADAPTER *pAd = NULL; INT WDS_apidx = 0,index; if (net_dev) { GET_PAD_FROM_NET_DEV(pAd, net_dev); } if (RT_DEV_PRIV_FLAGS_GET(net_dev) == INT_WDS) { if (pAd) { //struct net_device_stats stats; for(index = 0; index < MAX_WDS_ENTRY; index++) { if (pAd->WdsTab.WdsEntry[index].dev == net_dev) { WDS_apidx = index; break; } if(index == MAX_WDS_ENTRY) { DBGPRINT(RT_DEBUG_ERROR, ("rt28xx_ioctl can not find wds I/F\n")); return NULL; } } pAd->stats.rx_packets = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.ReceivedFragmentCount.QuadPart; pAd->stats.tx_packets = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.TransmittedFragmentCount.QuadPart; pAd->stats.rx_bytes = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.ReceivedByteCount; pAd->stats.tx_bytes = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.TransmittedByteCount; pAd->stats.rx_errors = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RxErrors; pAd->stats.tx_errors = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.TxErrors; pAd->stats.rx_dropped = 0; pAd->stats.tx_dropped = 0; pAd->stats.multicast = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.MulticastReceivedFrameCount.QuadPart; // multicast packets received pAd->stats.collisions = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.OneCollision + pAd->WdsTab.WdsEntry[index].WdsCounter.MoreCollisions; // Collision packets pAd->stats.rx_length_errors = 0; pAd->stats.rx_over_errors = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RxNoBuffer; // receiver ring buff overflow pAd->stats.rx_crc_errors = 0;//pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error pAd->stats.rx_frame_errors = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RcvAlignmentErrors; // recv'd frame alignment error pAd->stats.rx_fifo_errors = pAd->WdsTab.WdsEntry[WDS_apidx].WdsCounter.RxNoBuffer; // recv'r fifo overrun pAd->stats.rx_missed_errors = 0; // receiver missed packet // detailed tx_errors pAd->stats.tx_aborted_errors = 0; pAd->stats.tx_carrier_errors = 0; pAd->stats.tx_fifo_errors = 0; pAd->stats.tx_heartbeat_errors = 0; pAd->stats.tx_window_errors = 0; // for cslip etc pAd->stats.rx_compressed = 0; pAd->stats.tx_compressed = 0; return &pAd->stats; } else return NULL; } else return NULL; }