static void temac_set_multicast_list(struct net_device *ndev) { struct temac_local *lp = netdev_priv(ndev); u32 multi_addr_msw, multi_addr_lsw, val; int i; mutex_lock(&lp->indirect_mutex); if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) || netdev_mc_count(ndev) > MULTICAST_CAM_TABLE_NUM) { /* * We must make the kernel realise we had to move * into promisc mode or we start all out war on * the cable. If it was a promisc request the * flag is already set. If not we assert it. */ ndev->flags |= IFF_PROMISC; temac_indirect_out32(lp, XTE_AFM_OFFSET, XTE_AFM_EPPRM_MASK); dev_info(&ndev->dev, "Promiscuous mode enabled.\n"); } else if (!netdev_mc_empty(ndev)) { struct netdev_hw_addr *ha; i = 0; netdev_for_each_mc_addr(ha, ndev) { if (i >= MULTICAST_CAM_TABLE_NUM) break; multi_addr_msw = ((ha->addr[3] << 24) | (ha->addr[2] << 16) | (ha->addr[1] << 8) | (ha->addr[0])); temac_indirect_out32(lp, XTE_MAW0_OFFSET, multi_addr_msw); multi_addr_lsw = ((ha->addr[5] << 8) | (ha->addr[4]) | (i << 16)); temac_indirect_out32(lp, XTE_MAW1_OFFSET, multi_addr_lsw); i++; } } else {
/* Handle multiple multicast addresses (perfect filtering)*/ static void hisi_femac_set_mc_addr_filter(struct hisi_femac_priv *priv) { struct net_device *dev = priv->ndev; u32 val; val = readl(priv->glb_base + GLB_MACTCTRL); if ((netdev_mc_count(dev) > MAX_MULTICAST_ADDRESSES) || (dev->flags & IFF_ALLMULTI)) { val |= MACTCTRL_MULTI2CPU; } else { int reg = MAX_UNICAST_ADDRESSES; int i; struct netdev_hw_addr *ha; for (i = reg; i < MAX_MAC_FILTER_NUM; i++) hisi_femac_enable_hw_addr_filter(priv, i, false); netdev_for_each_mc_addr(ha, dev) { hisi_femac_set_hw_addr_filter(priv, ha->addr, reg); reg++; } val &= ~MACTCTRL_MULTI2CPU; }
static void dwmac4_set_filter(struct mac_device_info *hw, struct net_device *dev) { void __iomem *ioaddr = (void __iomem *)dev->base_addr; unsigned int value = 0; if (dev->flags & IFF_PROMISC) { value = GMAC_PACKET_FILTER_PR | GMAC_PACKET_FILTER_PCF; } else if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > HASH_TABLE_SIZE)) { /* Pass all multi */ value = GMAC_PACKET_FILTER_PM; /* Set the 64 bits of the HASH tab. To be updated if taller * hash table is used */ writel(0xffffffff, ioaddr + GMAC_HASH_TAB_0_31); writel(0xffffffff, ioaddr + GMAC_HASH_TAB_32_63); } else if (!netdev_mc_empty(dev)) { u32 mc_filter[2]; struct netdev_hw_addr *ha; /* Hash filter for multicast */ value = GMAC_PACKET_FILTER_HMC; memset(mc_filter, 0, sizeof(mc_filter)); netdev_for_each_mc_addr(ha, dev) { /* The upper 6 bits of the calculated CRC are used to * index the content of the Hash Table Reg 0 and 1. */ int bit_nr = (bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26); /* The most significant bit determines the register * to use while the other 5 bits determines the bit * within the selected register */ mc_filter[bit_nr >> 5] |= (1 << (bit_nr & 0x1F)); }
static void aqc111_set_rx_mode(struct net_device *net) { struct usbnet *dev = netdev_priv(net); struct aqc111_data *aqc111_data = dev->driver_priv; int mc_count = 0; mc_count = netdev_mc_count(net); aqc111_data->rxctl &= ~(SFR_RX_CTL_PRO | SFR_RX_CTL_AMALL | SFR_RX_CTL_AM); if (net->flags & IFF_PROMISC) { aqc111_data->rxctl |= SFR_RX_CTL_PRO; } else if ((net->flags & IFF_ALLMULTI) || mc_count > AQ_MAX_MCAST) { aqc111_data->rxctl |= SFR_RX_CTL_AMALL; } else if (!netdev_mc_empty(net)) { u8 m_filter[AQ_MCAST_FILTER_SIZE] = { 0 }; struct netdev_hw_addr *ha = NULL; u32 crc_bits = 0; netdev_for_each_mc_addr(ha, net) { crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; m_filter[crc_bits >> 3] |= BIT(crc_bits & 7); }
static void dm9601_set_multicast(struct net_device *net) { struct usbnet *dev = netdev_priv(net); /* We use the 20 byte dev->data for our 8 byte filter buffer * to avoid allocating memory that is tricky to free later */ u8 *hashes = (u8 *) & dev->data; u8 rx_ctl = 0x31; memset(hashes, 0x00, DM_MCAST_SIZE); hashes[DM_MCAST_SIZE - 1] |= 0x80; /* broadcast address */ if (net->flags & IFF_PROMISC) { rx_ctl |= 0x02; } else if (net->flags & IFF_ALLMULTI || netdev_mc_count(net) > DM_MAX_MCAST) { rx_ctl |= 0x08; } else if (!netdev_mc_empty(net)) { struct netdev_hw_addr *ha; netdev_for_each_mc_addr(ha, net) { u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26; hashes[crc >> 3] |= 1 << (crc & 0x7); } }
/* Set or clear the multicast filter for this adaptor. */ static void set_multicast_list(struct net_device *dev) { struct eepro_local *lp = netdev_priv(dev); short ioaddr = dev->base_addr; unsigned short mode; struct netdev_hw_addr *ha; int mc_count = netdev_mc_count(dev); if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || mc_count > 63) { eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ mode = inb(ioaddr + REG2); outb(mode | PRMSC_Mode, ioaddr + REG2); mode = inb(ioaddr + REG3); outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */ } else if (mc_count == 0) { eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ mode = inb(ioaddr + REG2); outb(mode & 0xd6, ioaddr + REG2); /* Turn off Multi-IA and PRMSC_Mode bits */ mode = inb(ioaddr + REG3); outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */ } else { unsigned short status, *eaddrs; int i, boguscount = 0; /* Disable RX and TX interrupts. Necessary to avoid corruption of the HOST_ADDRESS_REG by interrupt service routines. */ eepro_dis_int(ioaddr); eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ mode = inb(ioaddr + REG2); outb(mode | Multi_IA, ioaddr + REG2); mode = inb(ioaddr + REG3); outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */ outw(lp->tx_end, ioaddr + HOST_ADDRESS_REG); outw(MC_SETUP, ioaddr + IO_PORT); outw(0, ioaddr + IO_PORT); outw(0, ioaddr + IO_PORT); outw(6 * (mc_count + 1), ioaddr + IO_PORT); netdev_for_each_mc_addr(ha, dev) { eaddrs = (unsigned short *) ha->addr; outw(*eaddrs++, ioaddr + IO_PORT); outw(*eaddrs++, ioaddr + IO_PORT); outw(*eaddrs++, ioaddr + IO_PORT); } eaddrs = (unsigned short *) dev->dev_addr; outw(eaddrs[0], ioaddr + IO_PORT); outw(eaddrs[1], ioaddr + IO_PORT); outw(eaddrs[2], ioaddr + IO_PORT); outw(lp->tx_end, ioaddr + lp->xmt_bar); outb(MC_SETUP, ioaddr); /* Update the transmit queue */ i = lp->tx_end + XMT_HEADER + 6 * (mc_count + 1); if (lp->tx_start != lp->tx_end) { /* update the next address and the chain bit in the last packet */ outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG); outw(i, ioaddr + IO_PORT); outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG); status = inw(ioaddr + IO_PORT); outw(status | CHAIN_BIT, ioaddr + IO_PORT); lp->tx_end = i ; } else { lp->tx_start = lp->tx_end = i ; } /* Acknowledge that the MC setup is done */ do { /* We should be doing this in the eepro_interrupt()! */ SLOW_DOWN; SLOW_DOWN; if (inb(ioaddr + STATUS_REG) & 0x08) { i = inb(ioaddr); outb(0x08, ioaddr + STATUS_REG); if (i & 0x20) { /* command ABORTed */ printk(KERN_NOTICE "%s: multicast setup failed.\n", dev->name); break; } else if ((i & 0x0f) == 0x03) { /* MC-Done */ printk(KERN_DEBUG "%s: set Rx mode to %d address%s.\n", dev->name, mc_count, mc_count > 1 ? "es":""); break; } } } while (++boguscount < 100); /* Re-enable RX and TX interrupts */ eepro_en_int(ioaddr); }
int android_ioctl_siwpriv(struct net_device *dev, struct iw_request_info *__info, struct iw_point *data, char *__extra) { char cmd[384]; /* assume that android command will not excess 384 */ char buf[512]; int len = sizeof(cmd)-1; AR_SOFTC_DEV_T *arPriv = (AR_SOFTC_DEV_T *)ar6k_priv(dev); AR_SOFTC_STA_T *arSta = &arPriv->arSta; if (!data->pointer) { return -EOPNOTSUPP; } if (data->length < len) { len = data->length; } if (copy_from_user(cmd, data->pointer, len)) { return -EIO; } cmd[len] = 0; if (strcasecmp(cmd, "RSSI")==0 || strcasecmp(cmd, "RSSI-APPROX") == 0) { int rssi = -200; struct iw_statistics *iwStats; struct iw_statistics* (*get_iwstats)(struct net_device *); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) get_iwstats = dev->get_wireless_stats; #else get_iwstats = dev->wireless_handlers->get_wireless_stats; #endif if (get_iwstats && arPriv->arConnected) { iwStats = get_iwstats(dev); if (iwStats) { rssi = iwStats->qual.qual; if (rssi == 255) rssi = -200; else rssi += (161 - 256); } } len = snprintf(buf, data->length, "SSID rssi %d\n", rssi) + 1; return (copy_to_user(data->pointer, buf, len)==0) ? len : -1; } else if (strcasecmp(cmd, "LINKSPEED")==0) { /* We skip to use SIOCGIWRATE since Android always asked LINKSPEED just after RSSI*/ unsigned int speed_mbps; if (arPriv->arConnected) { speed_mbps = arPriv->arTargetStats.tx_unicast_rate / 1000; } else { speed_mbps = 1; } len = snprintf(buf, data->length, "LinkSpeed %u\n", speed_mbps) + 1; return (copy_to_user(data->pointer, buf, len)==0) ? len : -1; } else if (memcmp(cmd, "CSCAN S\x01\x00\x00S\x00", 12)==0) { int iocmd = SIOCSIWSCAN - SIOCSIWCOMMIT; const iw_handler setScan = dev->wireless_handlers->standard[iocmd]; A_INT32 home_dwell=0, pas_dwell=0, act_dwell=0; A_UCHAR ssid[IW_ESSID_MAX_SIZE+1] = { 0 }; A_INT32 ssid_len = 0, ie_len; A_UINT8 index = 1; /* reserve index 0 for wext */ A_INT32 ch = 0; A_CHAR nprobe, scantype; struct iw_freq chList[IW_MAX_FREQUENCIES]; A_UCHAR *scanBuf = (A_UCHAR*)(cmd + 12); A_UCHAR *scanEnd = (A_UCHAR*)(cmd + len); A_BOOL broadcastSsid = FALSE; while ( scanBuf < scanEnd ) { A_UCHAR *sp = scanBuf; switch (*scanBuf) { case 'S': /* SSID section */ if (ssid_len > 0 && index < MAX_PROBED_SSID_INDEX) { /* setup the last parsed ssid, reserve index 0 for wext */ if (wmi_probedSsid_cmd(arPriv->arWmi, index, SPECIFIC_SSID_FLAG, ssid_len, ssid) == A_OK) { ++index; if (arSta->scanSpecificSsid<index) { arSta->scanSpecificSsid = index; } } } ie_len = ((scanBuf + 1) < scanEnd) ? ((A_INT32)*(scanBuf+1) + 1) : 0; if ((scanBuf+ie_len) < scanEnd ) { ssid_len = *(scanBuf+1); if (ssid_len == 0) { broadcastSsid = TRUE; } else { A_MEMCPY(ssid, scanBuf+2, ssid_len); ssid[ssid_len] = '\0'; } } scanBuf += 1 + ie_len; break; case 'C': /* Channel section */ if (scanBuf+1 < scanEnd) { int value = *(scanBuf+1); if (value == 0) { ch = 0; /* scan for all channels */ } else if (ch < IW_MAX_FREQUENCIES) { if (value>1000) { chList[ch].e = 1; chList[ch].m = value * 100000; } else { chList[ch].e = 0; chList[ch].m = value; } ++ch; } } scanBuf += 2; break; case 'P': /* Passive dwell section */ if (scanBuf+2 < scanEnd) { pas_dwell = *(scanBuf+1) + (*(scanBuf+2) << 8); } scanBuf += 3; break; case 'H': /* Home dwell section */ if (scanBuf+2 < scanEnd) { home_dwell = *(scanBuf+1) + (*(scanBuf+2) << 8); } scanBuf += 3; break; case 'N': /* Number of probe section */ if (scanBuf+1 < scanEnd) { nprobe = *(scanBuf+1); } scanBuf += 2; break; case 'A': /* Active dwell section */ if (scanBuf+2 < scanEnd) { act_dwell = *(scanBuf+1) + (*(scanBuf+2) << 8); } scanBuf += 3; break; case 'T': /* Scan active type section */ if (scanBuf+1 < scanEnd) { scantype = *(scanBuf+1); } scanBuf += 2; break; default: break; } if (sp == scanBuf) { return -1; /* parsing error */ } } if (ssid_len>0) { A_UINT8 idx; /* Clean up the last specific scan items */ for (idx=index; idx<arSta->scanSpecificSsid; ++idx) { wmi_probedSsid_cmd(arPriv->arWmi, idx, DISABLE_SSID_FLAG, 0, NULL); } arSta->scanSpecificSsid = index; /* * There is no way to know when we need to send broadcast probe in current Android wpa_supplicant_6 * combo scan implemenation. Always force to sent it here uniti future Android version will set * the broadcast flags for combo scan. */ #if 0 if (broadcastSsid) #endif { /* setup the last index as broadcast SSID for combo scan */ ++arSta->scanSpecificSsid; wmi_probedSsid_cmd(arPriv->arWmi, index, ANY_SSID_FLAG, 0, NULL); } } if (pas_dwell>0) { /* TODO: Should we change our passive dwell? There may be some impact for bt-coex */ } if (home_dwell>0) { /* TODO: Should we adjust home_dwell? How to pass it to wext handler? */ } if (setScan) { union iwreq_data miwr; struct iw_request_info minfo; struct iw_scan_req scanreq, *pScanReq = NULL; A_MEMZERO(&minfo, sizeof(minfo)); A_MEMZERO(&miwr, sizeof(miwr)); A_MEMZERO(&scanreq, sizeof(scanreq)); if (ssid_len > 0) { pScanReq = &scanreq; memcpy(scanreq.essid, ssid, ssid_len); scanreq.essid_len = ssid_len; miwr.data.flags |= IW_SCAN_THIS_ESSID; } if (ch > 0) { pScanReq = &scanreq; scanreq.num_channels = ch; memcpy(scanreq.channel_list, chList, ch * sizeof(chList[0])); miwr.data.flags |= IW_SCAN_THIS_FREQ; } if (pScanReq) { miwr.data.pointer = (__force void __user *)&scanreq; miwr.data.length = sizeof(scanreq); } minfo.cmd = SIOCSIWSCAN; return setScan(dev, &minfo, &miwr, (char*)pScanReq); } return -1; } else if (strcasecmp(cmd, "MACADDR")==0) { /* reply comes back in the form "Macaddr = XX:XX:XX:XX:XX:XX" where XX */ A_UCHAR *mac = dev->dev_addr; len = snprintf(buf, data->length, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) + 1; return (copy_to_user(data->pointer, buf, len)==0) ? len : -1; } else if (strcasecmp(cmd, "SCAN-ACTIVE")==0) { return 0; /* unsupport function. Suppress the error */ } else if (strcasecmp(cmd, "SCAN-PASSIVE")==0) { return 0; /* unsupport function. Suppress the error */ } else if (strcasecmp(cmd, "START")==0 || strcasecmp(cmd, "STOP")==0) { struct ifreq ifr; char userBuf[16]; int ex_arg = (strcasecmp(cmd, "START")==0) ? WLAN_ENABLED : WLAN_DISABLED; int ret; A_MEMZERO(userBuf, sizeof(userBuf)); ((int *)userBuf)[0] = AR6000_XIOCTRL_WMI_SET_WLAN_STATE; ((int *)userBuf)[1] = ex_arg; ret = android_do_ioctl_direct(dev, AR6000_IOCTL_EXTENDED, &ifr, userBuf); if (ret==0) { /* Send wireless event which need by android supplicant */ union iwreq_data wrqu; A_MEMZERO(&wrqu, sizeof(wrqu)); wrqu.data.length = strlen(cmd); wireless_send_event(dev, IWEVCUSTOM, &wrqu, cmd); } return ret; } else if (strncasecmp(cmd, "POWERMODE ", 10)==0) { int mode; if (sscanf(cmd, "%*s %d", &mode) == 1) { int iocmd = SIOCSIWPOWER - SIOCSIWCOMMIT; iw_handler setPower = dev->wireless_handlers->standard[iocmd]; if (setPower) { union iwreq_data miwr; struct iw_request_info minfo; A_MEMZERO(&minfo, sizeof(minfo)); A_MEMZERO(&miwr, sizeof(miwr)); minfo.cmd = SIOCSIWPOWER; if (mode == 0 /* auto */) miwr.power.disabled = 0; else if (mode == 1 /* active */) miwr.power.disabled = 1; else return -1; return setPower(dev, &minfo, &miwr, NULL); } } return -1; } else if (strcasecmp(cmd, "GETPOWER")==0) { struct ifreq ifr; int userBuf[2]; A_MEMZERO(userBuf, sizeof(userBuf)); ((int *)userBuf)[0] = AR6000_XIOCTRL_WMI_GET_POWER_MODE; if (android_do_ioctl_direct(dev, AR6000_IOCTL_EXTENDED, &ifr, userBuf)>=0) { WMI_POWER_MODE_CMD *getPowerMode = (WMI_POWER_MODE_CMD *)userBuf; len = snprintf(buf, data->length, "powermode = %u\n", (getPowerMode->powerMode==MAX_PERF_POWER) ? 1/*active*/ : 0/*auto*/) + 1; return (copy_to_user(data->pointer, buf, len)==0) ? len : -1; } return -1; } else if (strncasecmp(cmd, "SETSUSPENDOPT ", 14)==0) { int enable; if (sscanf(cmd, "%*s %d", &enable)==1) { /* * We set our suspend mode by wlan_config.h now. * Should we follow Android command?? TODO */ return 0; } return -1; } else if (strcasecmp(cmd, "SCAN-CHANNELS")==0) { // reply comes back in the form "Scan-Channels = X" where X is the number of channels int iocmd = SIOCGIWRANGE - SIOCSIWCOMMIT; iw_handler getRange = dev->wireless_handlers->standard[iocmd]; if (getRange) { union iwreq_data miwr; struct iw_request_info minfo; struct iw_range range; A_MEMZERO(&minfo, sizeof(minfo)); A_MEMZERO(&miwr, sizeof(miwr)); A_MEMZERO(&range, sizeof(range)); minfo.cmd = SIOCGIWRANGE; miwr.data.pointer = (__force void __user *) ⦥ miwr.data.length = sizeof(range); getRange(dev, &minfo, &miwr, (char*)&range); } if (arSta->arNumChannels!=-1) { len = snprintf(buf, data->length, "Scan-Channels = %d\n", arSta->arNumChannels) + 1; return (copy_to_user(data->pointer, buf, len)==0) ? len : -1; } return -1; } else if (strncasecmp(cmd, "SCAN-CHANNELS ", 14)==0 || strncasecmp(cmd, "COUNTRY ", 8)==0) { /* * Set the available channels with WMI_SET_CHANNELPARAMS cmd * However, the channels will be limited by the eeprom regulator domain * Try to use a regulator domain which will not limited the channels range. */ int i; int chan = 0; A_UINT16 *clist; struct ifreq ifr; char ioBuf[256]; WMI_CHANNEL_PARAMS_CMD *chParamCmd = (WMI_CHANNEL_PARAMS_CMD *)ioBuf; if (strncasecmp(cmd, "COUNTRY ", 8)==0) { char *country = cmd + 8; if (strcasecmp(country, "US")==0) { chan = 11; } else if (strcasecmp(country, "JP")==0) { chan = 14; } else if (strcasecmp(country, "EU")==0) { chan = 13; } } else if (sscanf(cmd, "%*s %d", &chan) != 1) { return -1; } if ( (chan != 11) && (chan != 13) && (chan != 14)) { return -1; } if (arPriv->arNextMode == AP_NETWORK) { return -1; } A_MEMZERO(&ifr, sizeof(ifr)); A_MEMZERO(ioBuf, sizeof(ioBuf)); chParamCmd->phyMode = WMI_11G_MODE; clist = chParamCmd->channelList; chParamCmd->numChannels = chan; chParamCmd->scanParam = 1; for (i = 0; i < chan; i++) { clist[i] = wlan_ieee2freq(i + 1); } return android_do_ioctl_direct(dev, AR6000_IOCTL_WMI_SET_CHANNELPARAMS, &ifr, ioBuf); } else if (strncasecmp(cmd, "BTCOEXMODE ", 11)==0) { int mode; if (sscanf(cmd, "%*s %d", &mode)==1) { /* * Android disable BT-COEX when obtaining dhcp packet except there is headset is connected * It enable the BT-COEX after dhcp process is finished * We ignore since we have our way to do bt-coex during dhcp obtaining. */ switch (mode) { case 1: /* Disable*/ break; case 0: /* Enable */ /* fall through */ case 2: /* Sense*/ /* fall through */ default: break; } return 0; /* ignore it */ } return -1; } else if (strcasecmp(cmd, "BTCOEXSCAN-START")==0) { /* Android enable or disable Bluetooth coexistence scan mode. When this mode is on, * some of the low-level scan parameters used by the driver are changed to * reduce interference with A2DP streaming. */ return 0; /* ignore it since we have btfilter */ } else if (strcasecmp(cmd, "BTCOEXSCAN-STOP")==0) { return 0; /* ignore it since we have btfilter */ } else if (strncasecmp(cmd, "RXFILTER-ADD ", 13)==0) { return 0; /* ignore it */ } else if (strncasecmp(cmd, "RXFILTER-REMOVE ", 16)==0) { return 0; /* ignoret it */ } else if (strcasecmp(cmd, "RXFILTER-START")==0 || strcasecmp(cmd, "RXFILTER-STOP")==0) { unsigned int flags = dev->flags; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) int mc_count = dev->mc_count; #else int mc_count = netdev_mc_count(dev); #endif if (strcasecmp(cmd, "RXFILTER-START")==0) { if (mc_count > 0 || (flags & IFF_MULTICAST) ) { flags &= ~IFF_MULTICAST; } } else { flags |= IFF_MULTICAST; } if (flags != dev->flags) { dev_change_flags(dev, flags); } return 0; } return -EOPNOTSUPP; }
static void _brcmf_set_multicast_list(struct work_struct *work) { struct brcmf_if *ifp; struct net_device *ndev; struct netdev_hw_addr *ha; u32 cmd_value, cnt; __le32 cnt_le; char *buf, *bufp; u32 buflen; s32 err; ifp = container_of(work, struct brcmf_if, multicast_work); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx); ndev = ifp->ndev; /* Determine initial value of allmulti flag */ cmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false; /* Send down the multicast list first. */ cnt = netdev_mc_count(ndev); buflen = sizeof(cnt) + (cnt * ETH_ALEN); buf = kmalloc(buflen, GFP_ATOMIC); if (!buf) return; bufp = buf; cnt_le = cpu_to_le32(cnt); memcpy(bufp, &cnt_le, sizeof(cnt_le)); bufp += sizeof(cnt_le); netdev_for_each_mc_addr(ha, ndev) { if (!cnt) break; memcpy(bufp, ha->addr, ETH_ALEN); bufp += ETH_ALEN; cnt--; } err = brcmf_fil_iovar_data_set(ifp, "mcast_list", buf, buflen); if (err < 0) { brcmf_err("Setting mcast_list failed, %d\n", err); cmd_value = cnt ? true : cmd_value; } kfree(buf); /* * Now send the allmulti setting. This is based on the setting in the * net_device flags, but might be modified above to be turned on if we * were trying to set some addresses and dongle rejected it... */ err = brcmf_fil_iovar_int_set(ifp, "allmulti", cmd_value); if (err < 0) brcmf_err("Setting allmulti failed, %d\n", err); /*Finally, pick up the PROMISC flag */ cmd_value = (ndev->flags & IFF_PROMISC) ? true : false; err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PROMISC, cmd_value); if (err < 0) brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n", err); }
/** * @brief This function sets multicast addresses to firmware * * @param dev A pointer to net_device structure * @return n/a */ static void wlan_set_multicast_list(struct net_device *dev) { wlan_private *priv = (wlan_private *) netdev_priv(dev); wlan_adapter *Adapter = priv->adapter; int OldPacketFilter; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) int mc_count = dev->mc_count; #else int mc_count = netdev_mc_count(dev); #endif ENTER(); OldPacketFilter = Adapter->CurrentPacketFilter; if (dev->flags & IFF_PROMISC) { PRINTM(INFO, "Enable Promiscuous mode\n"); Adapter->CurrentPacketFilter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; } else { /* Multicast */ Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; if (dev->flags & IFF_ALLMULTI || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) { PRINTM(INFO, "Enabling All Multicast!\n"); Adapter->CurrentPacketFilter |= HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; } else { Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; if (!mc_count) { PRINTM(INFO, "No multicast addresses - " "disabling multicast!\n"); } else { int i; Adapter->NumOfMulticastMACAddr = wlan_copy_mcast_addr(Adapter, dev); PRINTM(INFO, "Multicast addresses: %d\n", mc_count); for (i = 0; i < mc_count; i++) { PRINTM(INFO, "Multicast address %d:" "%x %x %x %x %x %x\n", i, Adapter->MulticastList[i][0], Adapter->MulticastList[i][1], Adapter->MulticastList[i][2], Adapter->MulticastList[i][3], Adapter->MulticastList[i][4], Adapter->MulticastList[i][5]); } /* set multicast addresses to firmware */ wlan_prepare_cmd(priv, HostCmd_CMD_MAC_MULTICAST_ADR, HostCmd_ACT_GEN_SET, 0, 0, NULL); } } } if (Adapter->CurrentPacketFilter != OldPacketFilter) wlan_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, 0, 0, 0, &Adapter->CurrentPacketFilter); LEAVE(); }
/* * Proc info file read handler. * * This function is called when the 'info' file is opened for reading. * It prints the following driver related information - * - Driver name * - Driver version * - Driver extended version * - Interface name * - BSS mode * - Media state (connected or disconnected) * - MAC address * - Total number of Tx bytes * - Total number of Rx bytes * - Total number of Tx packets * - Total number of Rx packets * - Total number of dropped Tx packets * - Total number of dropped Rx packets * - Total number of corrupted Tx packets * - Total number of corrupted Rx packets * - Carrier status (on or off) * - Tx queue status (started or stopped) * * For STA mode drivers, it also prints the following extra - * - ESSID * - BSSID * - Channel * - Region code * - Multicast count * - Multicast addresses */ static ssize_t mwifiex_info_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct mwifiex_private *priv = (struct mwifiex_private *) file->private_data; struct net_device *netdev = priv->netdev; struct netdev_hw_addr *ha; struct netdev_queue *txq; unsigned long page = get_zeroed_page(GFP_KERNEL); char *p = (char *) page, fmt[64]; struct mwifiex_bss_info info; ssize_t ret; int i = 0; if (!p) return -ENOMEM; memset(&info, 0, sizeof(info)); ret = mwifiex_get_bss_info(priv, &info); if (ret) goto free_and_exit; mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1); if (!priv->version_str[0]) mwifiex_get_ver_ext(priv); p += sprintf(p, "driver_name = " "\"mwifiex\"\n"); p += sprintf(p, "driver_version = %s", fmt); p += sprintf(p, "\nverext = %s", priv->version_str); p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name); if (info.bss_mode >= ARRAY_SIZE(bss_modes)) p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode); else p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]); p += sprintf(p, "media_state=\"%s\"\n", (!priv->media_connected ? "Disconnected" : "Connected")); p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr); if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { p += sprintf(p, "multicast_count=\"%d\"\n", netdev_mc_count(netdev)); p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); p += sprintf(p, "bssid=\"%pM\"\n", info.bssid); p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); p += sprintf(p, "country_code = \"%s\"\n", info.country_code); netdev_for_each_mc_addr(ha, netdev) p += sprintf(p, "multicast_address[%d]=\"%pM\"\n", i++, ha->addr); } p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) ? "on" : "off")); p += sprintf(p, "tx queue"); for (i = 0; i < netdev->num_tx_queues; i++) { txq = netdev_get_tx_queue(netdev, i); p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ? "stopped" : "started"); } p += sprintf(p, "\n"); ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, (unsigned long) p - page); free_and_exit: free_page(page); return ret; }
static int init586(struct net_device *dev) { void __iomem *ptr; int i, result = 0; struct priv *p = netdev_priv(dev); struct configure_cmd_struct __iomem *cfg_cmd; struct iasetup_cmd_struct __iomem *ias_cmd; struct tdr_cmd_struct __iomem *tdr_cmd; struct mcsetup_cmd_struct __iomem *mc_cmd; struct netdev_hw_addr *ha; int num_addrs = netdev_mc_count(dev); ptr = p->scb + 1; cfg_cmd = ptr; /* */ writew(0, &cfg_cmd->cmd_status); writew(CMD_CONFIGURE | CMD_LAST, &cfg_cmd->cmd_cmd); writew(0xFFFF, &cfg_cmd->cmd_link); /* */ writeb(0x0a, &cfg_cmd->byte_cnt); /* */ writeb(fifo, &cfg_cmd->fifo); /* */ writeb(0x40, &cfg_cmd->sav_bf); /* */ writeb(0x2e, &cfg_cmd->adr_len); writeb(0x00, &cfg_cmd->priority); writeb(0x60, &cfg_cmd->ifs); writeb(0x00, &cfg_cmd->time_low); writeb(0xf2, &cfg_cmd->time_high); writeb(0x00, &cfg_cmd->promisc); if (dev->flags & IFF_ALLMULTI) { int len = ((char __iomem *)p->iscp - (char __iomem *)ptr - 8) / 6; if (num_addrs > len) { printk(KERN_ERR "%s: switching to promisc. mode\n", dev->name); writeb(0x01, &cfg_cmd->promisc); } } if (dev->flags & IFF_PROMISC) writeb(0x01, &cfg_cmd->promisc); writeb(0x00, &cfg_cmd->carr_coll); writew(make16(cfg_cmd), &p->scb->cbl_offset); writeb(0, &p->scb->cmd_ruc); writeb(CUC_START, &p->scb->cmd_cuc); /* */ ni_attn586(); wait_for_stat_compl(cfg_cmd); if ((readw(&cfg_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK)) { printk(KERN_ERR "%s: configure command failed: %x\n", dev->name, readw(&cfg_cmd->cmd_status)); return 1; } /* */ ias_cmd = ptr; writew(0, &ias_cmd->cmd_status); writew(CMD_IASETUP | CMD_LAST, &ias_cmd->cmd_cmd); writew(0xffff, &ias_cmd->cmd_link); memcpy_toio(&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN); writew(make16(ias_cmd), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); /* */ ni_attn586(); wait_for_stat_compl(ias_cmd); if ((readw(&ias_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) { printk(KERN_ERR "%s (ni52): individual address setup command failed: %04x\n", dev->name, readw(&ias_cmd->cmd_status)); return 1; } /* */ tdr_cmd = ptr; writew(0, &tdr_cmd->cmd_status); writew(CMD_TDR | CMD_LAST, &tdr_cmd->cmd_cmd); writew(0xffff, &tdr_cmd->cmd_link); writew(0, &tdr_cmd->status); writew(make16(tdr_cmd), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); /* */ ni_attn586(); wait_for_stat_compl(tdr_cmd); if (!(readw(&tdr_cmd->cmd_status) & STAT_COMPL)) printk(KERN_ERR "%s: Problems while running the TDR.\n", dev->name); else { udelay(16); result = readw(&tdr_cmd->status); writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc); ni_attn586(); /* */ if (result & TDR_LNK_OK) ; else if (result & TDR_XCVR_PRB) printk(KERN_ERR "%s: TDR: Transceiver problem. Check the cable(s)!\n", dev->name); else if (result & TDR_ET_OPN) printk(KERN_ERR "%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK); else if (result & TDR_ET_SRT) { /* */ if (result & TDR_TIMEMASK) printk(KERN_ERR "%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK); } else printk(KERN_ERR "%s: TDR: Unknown status %04x\n", dev->name, result); } /* */ if (num_addrs && !(dev->flags & IFF_PROMISC)) { mc_cmd = ptr; writew(0, &mc_cmd->cmd_status); writew(CMD_MCSETUP | CMD_LAST, &mc_cmd->cmd_cmd); writew(0xffff, &mc_cmd->cmd_link); writew(num_addrs * 6, &mc_cmd->mc_cnt); i = 0; netdev_for_each_mc_addr(ha, dev) memcpy_toio(mc_cmd->mc_list[i++], ha->addr, 6); writew(make16(mc_cmd), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); ni_attn586(); wait_for_stat_compl(mc_cmd); if ((readw(&mc_cmd->cmd_status) & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK)) printk(KERN_ERR "%s: Can't apply multicast-address-list.\n", dev->name); } /* */ #if (NUM_XMIT_BUFFS == 1) for (i = 0; i < 2; i++) { p->nop_cmds[i] = ptr; writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd); writew(0, &p->nop_cmds[i]->cmd_status); writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link); ptr = ptr + sizeof(struct nop_cmd_struct); } #else for (i = 0; i < NUM_XMIT_BUFFS; i++) { p->nop_cmds[i] = ptr; writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd); writew(0, &p->nop_cmds[i]->cmd_status); writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link); ptr = ptr + sizeof(struct nop_cmd_struct); } #endif ptr = alloc_rfa(dev, ptr); /* */ /* */ for (i = 0; i < NUM_XMIT_BUFFS; i++) { /* */ p->xmit_cmds[i] = ptr; ptr = ptr + sizeof(struct transmit_cmd_struct); p->xmit_cbuffs[i] = ptr; /* */ ptr = ptr + XMIT_BUFF_SIZE; p->xmit_buffs[i] = ptr; /* */ ptr = ptr + sizeof(struct tbd_struct); if ((void __iomem *)ptr > (void __iomem *)p->iscp) { printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n", dev->name); return 1; } memset_io(p->xmit_cmds[i], 0, sizeof(struct transmit_cmd_struct)); memset_io(p->xmit_buffs[i], 0, sizeof(struct tbd_struct)); writew(make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]), &p->xmit_cmds[i]->cmd_link); writew(STAT_COMPL, &p->xmit_cmds[i]->cmd_status); writew(CMD_XMIT|CMD_INT, &p->xmit_cmds[i]->cmd_cmd); writew(make16(p->xmit_buffs[i]), &p->xmit_cmds[i]->tbd_offset); writew(0xffff, &p->xmit_buffs[i]->next); writel(make24(p->xmit_cbuffs[i]), &p->xmit_buffs[i]->buffer); } p->xmit_count = 0; p->xmit_last = 0; #ifndef NO_NOPCOMMANDS p->nop_point = 0; #endif /* */ #ifndef NO_NOPCOMMANDS writew(make16(p->nop_cmds[0]), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); ni_attn586(); wait_for_scb_cmd(dev); #else writew(make16(p->xmit_cmds[0]), &p->xmit_cmds[0]->cmd_link); writew(CMD_XMIT | CMD_SUSPEND | CMD_INT, &p->xmit_cmds[0]->cmd_cmd); #endif /* */ writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc); ni_attn586(); udelay(16); ni_enaint(); return 0; }
int android_ioctl_siwpriv(struct net_device *dev, struct iw_request_info *__info, struct iw_point *data, char *__extra) { char *cmd = data->pointer; char *buf = data->pointer; AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); if (!cmd || !buf) { return -EOPNOTSUPP; } if (strcasecmp(cmd, "RSSI")==0 || strcasecmp(cmd, "RSSI-APPROX") == 0) { int rssi = 255; struct iw_statistics *iwStats; struct iw_statistics* (*get_iwstats)(struct net_device *); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) get_iwstats = dev->get_wireless_stats; #else get_iwstats = dev->wireless_handlers->get_wireless_stats; #endif iwStats = get_iwstats(dev); if (iwStats) { rssi = iwStats->qual.qual; if (rssi == 255) rssi = -200; else rssi += (161 - 256); } return snprintf(buf, data->length, "SSID rssi %d\n", rssi); } else if (strcasecmp(cmd, "LINKSPEED")==0) { int iocmd = SIOCGIWRATE - SIOCSIWCOMMIT; const iw_handler getRate = dev->wireless_handlers->standard[iocmd]; if (getRate) { union iwreq_data miwr; struct iw_request_info minfo; A_MEMZERO(&minfo, sizeof(minfo)); A_MEMZERO(&miwr, sizeof(miwr)); minfo.cmd = SIOCGIWRATE; if (getRate(dev, &minfo, &miwr, NULL) == 0) { unsigned int speed_kbps = miwr.param.value / 1000000; if ((!miwr.param.fixed)) { return snprintf(buf, data->length, "LinkSpeed %u\n", speed_kbps); } } } return -1; } else if (strcasecmp(cmd, "MACADDR")==0) { /* reply comes back in the form "Macaddr = XX.XX.XX.XX.XX.XX" where XX */ A_UCHAR *mac = dev->dev_addr; return snprintf(buf, data->length, "Macaddr = %02X.%02X.%02X.%02X.%02X.%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } else if (strcasecmp(cmd, "SCAN-ACTIVE")==0) { return 0; /* unsupport function. Suppress the error */ } else if (strcasecmp(cmd, "SCAN-PASSIVE")==0) { return 0; /* unsupport function. Suppress the error */ } else if (strcasecmp(cmd, "START")==0 || strcasecmp(cmd, "STOP")==0) { struct ifreq ifr; char userBuf[16]; int ex_arg = (strcasecmp(cmd, "START")==0) ? WLAN_ENABLED : WLAN_DISABLED; A_MEMZERO(userBuf, sizeof(userBuf)); ((int *)userBuf)[0] = AR6000_XIOCTRL_WMI_SET_WLAN_STATE; ((int *)userBuf)[1] = ex_arg; return android_do_ioctl_direct(dev, AR6000_IOCTL_EXTENDED, &ifr, userBuf); } else if (strncasecmp(cmd, "POWERMODE ", 10)==0) { int mode; if (sscanf(cmd, "%*s %d", &mode) == 1) { int iocmd = SIOCSIWPOWER - SIOCSIWCOMMIT; iw_handler setPower = dev->wireless_handlers->standard[iocmd]; if (setPower) { union iwreq_data miwr; struct iw_request_info minfo; A_MEMZERO(&minfo, sizeof(minfo)); A_MEMZERO(&miwr, sizeof(miwr)); minfo.cmd = SIOCSIWPOWER; if (mode == 0 /* auto */) miwr.power.disabled = 0; else if (mode == 1 /* active */) miwr.power.disabled = 1; else return -1; return setPower(dev, &minfo, &miwr, NULL); } } return -1; } else if (strcasecmp(cmd, "SCAN-CHANNELS")==0) { /* reply comes back in the form "Scan-Channels = X" where X is the number of channels */ int iocmd = SIOCGIWRANGE - SIOCSIWCOMMIT; iw_handler getRange = dev->wireless_handlers->standard[iocmd]; if (getRange) { union iwreq_data miwr; struct iw_request_info minfo; struct iw_range range; A_MEMZERO(&minfo, sizeof(minfo)); A_MEMZERO(&miwr, sizeof(miwr)); A_MEMZERO(&range, sizeof(range)); minfo.cmd = SIOCGIWRANGE; miwr.data.pointer = (caddr_t) ⦥ miwr.data.length = sizeof(range); getRange(dev, &minfo, &miwr, (char*)&range); } if (ar->arNumChannels!=-1) { return snprintf(buf, data->length, "Scan-Channels = %d\n", ar->arNumChannels); } return -1; } else if (strncasecmp(cmd, "SCAN-CHANNELS ", 14)==0 || strncasecmp(cmd, "COUNTRY ", 8)==0) { /* * Set the available channels with WMI_SET_CHANNELPARAMS cmd * However, the channels will be limited by the eeprom regulator domain * Try to use a regulator domain which will not limited the channels range. */ int i; int chan = 0; A_UINT16 *clist; struct ifreq ifr; char ioBuf[256]; WMI_CHANNEL_PARAMS_CMD *chParamCmd = (WMI_CHANNEL_PARAMS_CMD *)ioBuf; if (strncasecmp(cmd, "COUNTRY ", 8)==0) { char *country = cmd + 8; if (strcasecmp(country, "US")==0) { chan = 11; } else if (strcasecmp(country, "JP")==0) { chan = 14; } else if (strcasecmp(country, "EU")==0) { chan = 13; } } else if (sscanf(cmd, "%*s %d", &chan) != 1) { return -1; } if ( (chan != 11) && (chan != 13) && (chan != 14)) { return -1; } if (ar->arNextMode == AP_NETWORK) { return -1; } A_MEMZERO(&ifr, sizeof(ifr)); A_MEMZERO(ioBuf, sizeof(ioBuf)); chParamCmd->phyMode = WMI_11G_MODE; clist = chParamCmd->channelList; chParamCmd->numChannels = chan; chParamCmd->scanParam = 1; for (i = 0; i < chan; i++) { clist[i] = wlan_ieee2freq(i + 1); } return android_do_ioctl_direct(dev, AR6000_IOCTL_WMI_SET_CHANNELPARAMS, &ifr, ioBuf); } else if (strncasecmp(cmd, "BTCOEXMODE ", 11)==0) { int mode; if (sscanf(cmd, "%*s %d", &mode)==1) { /* * Android disable BT-COEX when obtaining dhcp packet except there is headset is connected * It enable the BT-COEX after dhcp process is finished * We ignore since we have our way to do bt-coex during dhcp obtaining. */ switch (mode) { case 1: /* Disable*/ break; case 0: /* Enable */ /* fall through */ case 2: /* Sense*/ /* fall through */ default: break; } return 0; /* ignore it */ } return -1; } else if (strcasecmp(cmd, "BTCOEXSCAN-START")==0) { /* Android enable or disable Bluetooth coexistence scan mode. When this mode is on, * some of the low-level scan parameters used by the driver are changed to * reduce interference with A2DP streaming. */ return 0; /* ignore it since we have btfilter */ } else if (strcasecmp(cmd, "BTCOEXSCAN-STOP")==0) { return 0; /* ignore it since we have btfilter */ } else if (strncasecmp(cmd, "RXFILTER-ADD ", 13)==0) { return 0; /* ignore it */ } else if (strncasecmp(cmd, "RXFILTER-REMOVE ", 16)==0) { return 0; /* ignoret it */ } else if (strcasecmp(cmd, "RXFILTER-START")==0 || strcasecmp(cmd, "RXFILTER-STOP")==0) { unsigned int flags = dev->flags; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) int mc_count = dev->mc_count; #else int mc_count = netdev_mc_count(dev); #endif if (!(flags & IFF_UP)) { return -1; } if (strcasecmp(cmd, "RXFILTER-START")==0) { if (mc_count > 0 || (flags & IFF_MULTICAST) ) { flags &= ~IFF_MULTICAST; } } else { flags |= IFF_MULTICAST; } if (flags != dev->flags) { dev_change_flags(dev, flags); } return 0; } return -EOPNOTSUPP; }
/** * et131x_multicast - The handler to configure multicasting on the interface * @netdev: a pointer to a net_device struct representing the device */ void et131x_multicast(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); uint32_t PacketFilter = 0; unsigned long flags; struct dev_mc_list *mclist; int i; spin_lock_irqsave(&adapter->Lock, flags); /* Before we modify the platform-independent filter flags, store them * locally. This allows us to determine if anything's changed and if * we even need to bother the hardware */ PacketFilter = adapter->PacketFilter; /* Clear the 'multicast' flag locally; becuase we only have a single * flag to check multicast, and multiple multicast addresses can be * set, this is the easiest way to determine if more than one * multicast address is being set. */ PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST; /* Check the net_device flags and set the device independent flags * accordingly */ if (netdev->flags & IFF_PROMISC) { adapter->PacketFilter |= ET131X_PACKET_TYPE_PROMISCUOUS; } else { adapter->PacketFilter &= ~ET131X_PACKET_TYPE_PROMISCUOUS; } if (netdev->flags & IFF_ALLMULTI) { adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; } if (netdev_mc_count(netdev) > NIC_MAX_MCAST_LIST) { adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; } if (netdev_mc_count(netdev) < 1) { adapter->PacketFilter &= ~ET131X_PACKET_TYPE_ALL_MULTICAST; adapter->PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST; } else { adapter->PacketFilter |= ET131X_PACKET_TYPE_MULTICAST; } /* Set values in the private adapter struct */ i = 0; netdev_for_each_mc_addr(mclist, netdev) { if (i == NIC_MAX_MCAST_LIST) break; memcpy(adapter->MCList[i++], mclist->dmi_addr, ETH_ALEN); } adapter->MCAddressCount = i; /* Are the new flags different from the previous ones? If not, then no * action is required * * NOTE - This block will always update the MCList with the hardware, * even if the addresses aren't the same. */ if (PacketFilter != adapter->PacketFilter) { /* Call the device's filter function */ et131x_set_packet_filter(adapter); } spin_unlock_irqrestore(&adapter->Lock, flags); }
static void octeon_mgmt_set_rx_filtering(struct net_device *netdev) { struct octeon_mgmt *p = netdev_priv(netdev); union cvmx_agl_gmx_rxx_adr_ctl adr_ctl; union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx; unsigned long flags; unsigned int prev_packet_enable; unsigned int cam_mode = 1; /* 1 - Accept on CAM match */ unsigned int multicast_mode = 1; /* 1 - Reject all multicast. */ struct octeon_mgmt_cam_state cam_state; struct netdev_hw_addr *ha; int available_cam_entries; memset(&cam_state, 0, sizeof(cam_state)); if ((netdev->flags & IFF_PROMISC) || netdev->uc.count > 7) { cam_mode = 0; available_cam_entries = 8; } else { /* One CAM entry for the primary address, leaves seven * for the secondary addresses. */ available_cam_entries = 7 - netdev->uc.count; } if (netdev->flags & IFF_MULTICAST) { if (cam_mode == 0 || (netdev->flags & IFF_ALLMULTI) || netdev_mc_count(netdev) > available_cam_entries) multicast_mode = 2; /* 2 - Accept all multicast. */ else multicast_mode = 0; /* 0 - Use CAM. */ } if (cam_mode == 1) { /* Add primary address. */ octeon_mgmt_cam_state_add(&cam_state, netdev->dev_addr); netdev_for_each_uc_addr(ha, netdev) octeon_mgmt_cam_state_add(&cam_state, ha->addr); } if (multicast_mode == 0) { netdev_for_each_mc_addr(ha, netdev) octeon_mgmt_cam_state_add(&cam_state, ha->addr); } spin_lock_irqsave(&p->lock, flags); /* Disable packet I/O. */ agl_gmx_prtx.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG); prev_packet_enable = agl_gmx_prtx.s.en; agl_gmx_prtx.s.en = 0; cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64); adr_ctl.u64 = 0; adr_ctl.s.cam_mode = cam_mode; adr_ctl.s.mcst = multicast_mode; adr_ctl.s.bcst = 1; /* Allow broadcast */ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CTL, adr_ctl.u64); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM0, cam_state.cam[0]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM1, cam_state.cam[1]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM2, cam_state.cam[2]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM3, cam_state.cam[3]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM4, cam_state.cam[4]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM5, cam_state.cam[5]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM_EN, cam_state.cam_mask); /* Restore packet I/O. */ agl_gmx_prtx.s.en = prev_packet_enable; cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64); spin_unlock_irqrestore(&p->lock, flags); }
/** * @brief Proc read function for info * * @param page Pointer to buffer * @param start Read data starting position * @param offset Offset * @param count Counter * @param eof End of file flag * @param data Data to output * * @return Number of output data */ static int woal_info_proc_read(char *page, char **start, off_t offset, int count, int *eof, void *data) { char *p = page; struct net_device *netdev = data; char fmt[64]; moal_private *priv = (moal_private *) netdev_priv(netdev); #ifdef STA_SUPPORT int i = 0; moal_handle *handle = priv->phandle; mlan_bss_info info; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) struct dev_mc_list *mcptr = netdev->mc_list; int mc_count = netdev->mc_count; #else struct netdev_hw_addr *mcptr = NULL; int mc_count = netdev_mc_count(netdev); #endif /* < 2.6.35 */ #endif #ifdef UAP_SUPPORT mlan_ds_uap_stats ustats; #endif if (offset) { *eof = 1; goto exit; } #ifdef UAP_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { p += sprintf(p, "driver_name = " "\"uap\"\n"); woal_uap_get_version(priv, fmt, sizeof(fmt) - 1); if (MLAN_STATUS_SUCCESS != woal_uap_get_stats(priv, MOAL_PROC_WAIT, &ustats)) { *eof = 1; goto exit; } } #endif /* UAP_SUPPORT */ #ifdef STA_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) { woal_get_version(handle, fmt, sizeof(fmt) - 1); memset(&info, 0, sizeof(info)); if (MLAN_STATUS_SUCCESS != woal_get_bss_info(priv, MOAL_PROC_WAIT, &info)) { *eof = 1; goto exit; } p += sprintf(p, "driver_name = " "\"wlan\"\n"); } #endif p += sprintf(p, "driver_version = %s", fmt); p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name); #ifdef STA_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) p += sprintf(p, "bss_mode=\"%s\"\n", szModes[info.bss_mode]); #endif p += sprintf(p, "media_state=\"%s\"\n", ((priv->media_connected == MFALSE) ? "Disconnected" : "Connected")); p += sprintf(p, "mac_address=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); #ifdef STA_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) { p += sprintf(p, "multicast_count=\"%d\"\n", mc_count); p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); p += sprintf(p, "bssid=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", info.bssid[0], info.bssid[1], info.bssid[2], info.bssid[3], info.bssid[4], info.bssid[5]); p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); p += sprintf(p, "region_code = \"%02x\"\n", (t_u8) info.region_code); /* * Put out the multicast list */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) for (i = 0; i < netdev->mc_count; i++) { p += sprintf(p, "multicast_address[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", i, mcptr->dmi_addr[0], mcptr->dmi_addr[1], mcptr->dmi_addr[2], mcptr->dmi_addr[3], mcptr->dmi_addr[4], mcptr->dmi_addr[5]); mcptr = mcptr->next; } #else netdev_for_each_mc_addr(mcptr, netdev) p += sprintf(p, "multicast_address[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", i++, mcptr->addr[0], mcptr->addr[1], mcptr->addr[2], mcptr->addr[3], mcptr->addr[4], mcptr->addr[5]); #endif /* < 2.6.35 */ } #endif p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) ? "on" : "off")); p += sprintf(p, "tx queue %s\n", ((netif_queue_stopped(priv->netdev)) ? "stopped" : "started")); #ifdef UAP_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { p += sprintf(p, "tkip_mic_failures = %lu\n", ustats.tkip_mic_failures); p += sprintf(p, "ccmp_decrypt_errors = %lu\n", ustats.ccmp_decrypt_errors); p += sprintf(p, "wep_undecryptable_count = %lu\n", ustats.wep_undecryptable_count); p += sprintf(p, "wep_icv_error_count = %lu\n", ustats.wep_icv_error_count); p += sprintf(p, "decrypt_failure_count = %lu\n", ustats.decrypt_failure_count); p += sprintf(p, "mcast_tx_count = %lu\n", ustats.mcast_tx_count); p += sprintf(p, "failed_count = %lu\n", ustats.failed_count); p += sprintf(p, "retry_count = %lu\n", ustats.retry_count); p += sprintf(p, "multiple_retry_count = %lu\n", ustats.multi_retry_count); p += sprintf(p, "frame_duplicate_count = %lu\n", ustats.frame_dup_count); p += sprintf(p, "rts_success_count = %lu\n", ustats.rts_success_count); p += sprintf(p, "rts_failure_count = %lu\n", ustats.rts_failure_count); p += sprintf(p, "ack_failure_count = %lu\n", ustats.ack_failure_count); p += sprintf(p, "rx_fragment_count = %lu\n", ustats.rx_fragment_count); p += sprintf(p, "mcast_rx_frame_count = %lu\n", ustats.mcast_rx_frame_count); p += sprintf(p, "fcs_error_count = %lu\n", ustats.fcs_error_count); p += sprintf(p, "tx_frame_count = %lu\n", ustats.tx_frame_count); p += sprintf(p, "rsna_tkip_cm_invoked = %lu\n", ustats.rsna_tkip_cm_invoked); p += sprintf(p, "rsna_4way_hshk_failures = %lu\n", ustats.rsna_4way_hshk_failures); } #endif /* UAP_SUPPORT */ exit: return (p - page); }
static void bnep_net_set_mc_list(struct net_device *dev) { #ifdef CONFIG_BT_BNEP_MC_FILTER struct bnep_session *s = netdev_priv(dev); struct sock *sk = s->sock->sk; struct bnep_set_filter_req *r; struct sk_buff *skb; int size; BT_DBG("%s mc_count %d", dev->name, netdev_mc_count(dev)); size = sizeof(*r) + (BNEP_MAX_MULTICAST_FILTERS + 1) * ETH_ALEN * 2; skb = alloc_skb(size, GFP_ATOMIC); if (!skb) { BT_ERR("%s Multicast list allocation failed", dev->name); return; } r = (void *) skb->data; __skb_put(skb, sizeof(*r)); r->type = BNEP_CONTROL; r->ctrl = BNEP_FILTER_MULTI_ADDR_SET; if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) { u8 start[ETH_ALEN] = { 0x01 }; /* Request all addresses */ memcpy(__skb_put(skb, ETH_ALEN), start, ETH_ALEN); memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); r->len = htons(ETH_ALEN * 2); } else { struct netdev_hw_addr *ha; int i, len = skb->len; if (dev->flags & IFF_BROADCAST) { memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); } /* FIXME: We should group addresses here. */ i = 0; netdev_for_each_mc_addr(ha, dev) { if (i == BNEP_MAX_MULTICAST_FILTERS) break; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); #else memcpy(__skb_put(skb, ETH_ALEN), ha->dmi_addr, ETH_ALEN); memcpy(__skb_put(skb, ETH_ALEN), ha->dmi_addr, ETH_ALEN); #endif i++; } r->len = htons(skb->len - len); } skb_queue_tail(&sk->sk_write_queue, skb); wake_up_interruptible(sk_sleep(sk)); #endif }
static int init586(struct net_device *dev) { void *ptr; unsigned long s; int i, result = 0; struct priv *p = netdev_priv(dev); volatile struct configure_cmd_struct *cfg_cmd; volatile struct iasetup_cmd_struct *ias_cmd; volatile struct tdr_cmd_struct *tdr_cmd; volatile struct mcsetup_cmd_struct *mc_cmd; struct netdev_hw_addr *ha; int num_addrs = netdev_mc_count(dev); ptr = (void *) ((char *) p->scb + sizeof(struct scb_struct)); cfg_cmd = (struct configure_cmd_struct *) ptr; /* configure-command */ cfg_cmd->cmd_status = 0; cfg_cmd->cmd_cmd = CMD_CONFIGURE | CMD_LAST; cfg_cmd->cmd_link = 0xffff; cfg_cmd->byte_cnt = 0x0a; /* number of cfg bytes */ cfg_cmd->fifo = 0x08; /* fifo-limit (8=tx:32/rx:64) */ cfg_cmd->sav_bf = 0x40; /* hold or discard bad recv frames (bit 7) */ cfg_cmd->adr_len = 0x2e; /* addr_len |!src_insert |pre-len |loopback */ cfg_cmd->priority = 0x00; cfg_cmd->ifs = 0x60; cfg_cmd->time_low = 0x00; cfg_cmd->time_high = 0xf2; cfg_cmd->promisc = 0; if (dev->flags & (IFF_ALLMULTI | IFF_PROMISC)) cfg_cmd->promisc = 1; cfg_cmd->carr_coll = 0x00; p->scb->cbl_offset = make16(cfg_cmd); p->scb->cmd = CUC_START; /* cmd.-unit start */ elmc_id_attn586(); s = jiffies; /* warning: only active with interrupts on !! */ while (!(cfg_cmd->cmd_status & STAT_COMPL)) { if (time_after(jiffies, s + 30*HZ/100)) break; } if ((cfg_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_COMPL | STAT_OK)) { pr_warning("%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status); return 1; } /* * individual address setup */ ias_cmd = (struct iasetup_cmd_struct *) ptr; ias_cmd->cmd_status = 0; ias_cmd->cmd_cmd = CMD_IASETUP | CMD_LAST; ias_cmd->cmd_link = 0xffff; memcpy((char *) &ias_cmd->iaddr, (char *) dev->dev_addr, ETH_ALEN); p->scb->cbl_offset = make16(ias_cmd); p->scb->cmd = CUC_START; /* cmd.-unit start */ elmc_id_attn586(); s = jiffies; while (!(ias_cmd->cmd_status & STAT_COMPL)) { if (time_after(jiffies, s + 30*HZ/100)) break; } if ((ias_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_OK | STAT_COMPL)) { pr_warning("%s (elmc): individual address setup command failed: %04x\n", dev->name, ias_cmd->cmd_status); return 1; } /* * TDR, wire check .. e.g. no resistor e.t.c */ tdr_cmd = (struct tdr_cmd_struct *) ptr; tdr_cmd->cmd_status = 0; tdr_cmd->cmd_cmd = CMD_TDR | CMD_LAST; tdr_cmd->cmd_link = 0xffff; tdr_cmd->status = 0; p->scb->cbl_offset = make16(tdr_cmd); p->scb->cmd = CUC_START; /* cmd.-unit start */ elmc_attn586(); s = jiffies; while (!(tdr_cmd->cmd_status & STAT_COMPL)) { if (time_after(jiffies, s + 30*HZ/100)) { pr_warning("%s: %d Problems while running the TDR.\n", dev->name, __LINE__); result = 1; break; } } if (!result) { DELAY(2); /* wait for result */ result = tdr_cmd->status; p->scb->cmd = p->scb->status & STAT_MASK; elmc_id_attn586(); /* ack the interrupts */ if (result & TDR_LNK_OK) { /* empty */ } else if (result & TDR_XCVR_PRB) { pr_warning("%s: TDR: Transceiver problem!\n", dev->name); } else if (result & TDR_ET_OPN) { pr_warning("%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK); } else if (result & TDR_ET_SRT) { if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */ pr_warning("%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK); } else { pr_warning("%s: TDR: Unknown status %04x\n", dev->name, result); } } /* * ack interrupts */ p->scb->cmd = p->scb->status & STAT_MASK; elmc_id_attn586(); /* * alloc nop/xmit-cmds */ #if (NUM_XMIT_BUFFS == 1) for (i = 0; i < 2; i++) { p->nop_cmds[i] = (struct nop_cmd_struct *) ptr; p->nop_cmds[i]->cmd_cmd = CMD_NOP; p->nop_cmds[i]->cmd_status = 0; p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); ptr = (char *) ptr + sizeof(struct nop_cmd_struct); } p->xmit_cmds[0] = (struct transmit_cmd_struct *) ptr; /* transmit cmd/buff 0 */ ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); #else for (i = 0; i < NUM_XMIT_BUFFS; i++) { p->nop_cmds[i] = (struct nop_cmd_struct *) ptr; p->nop_cmds[i]->cmd_cmd = CMD_NOP; p->nop_cmds[i]->cmd_status = 0; p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); ptr = (char *) ptr + sizeof(struct nop_cmd_struct); p->xmit_cmds[i] = (struct transmit_cmd_struct *) ptr; /*transmit cmd/buff 0 */ ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); } #endif ptr = alloc_rfa(dev, (void *) ptr); /* init receive-frame-area */ /* * Multicast setup */ if (num_addrs) { /* I don't understand this: do we really need memory after the init? */ int len = ((char *) p->iscp - (char *) ptr - 8) / 6; if (len <= 0) { pr_err("%s: Ooooops, no memory for MC-Setup!\n", dev->name); } else { if (len < num_addrs) { num_addrs = len; pr_warning("%s: Sorry, can only apply %d MC-Address(es).\n", dev->name, num_addrs); } mc_cmd = (struct mcsetup_cmd_struct *) ptr; mc_cmd->cmd_status = 0; mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST; mc_cmd->cmd_link = 0xffff; mc_cmd->mc_cnt = num_addrs * 6; i = 0; netdev_for_each_mc_addr(ha, dev) memcpy((char *) mc_cmd->mc_list[i++], ha->addr, 6); p->scb->cbl_offset = make16(mc_cmd); p->scb->cmd = CUC_START; elmc_id_attn586(); s = jiffies; while (!(mc_cmd->cmd_status & STAT_COMPL)) { if (time_after(jiffies, s + 30*HZ/100)) break; } if (!(mc_cmd->cmd_status & STAT_COMPL)) { pr_warning("%s: Can't apply multicast-address-list.\n", dev->name); } } } /* * alloc xmit-buffs / init xmit_cmds */ for (i = 0; i < NUM_XMIT_BUFFS; i++) { p->xmit_cbuffs[i] = (char *) ptr; /* char-buffs */ ptr = (char *) ptr + XMIT_BUFF_SIZE; p->xmit_buffs[i] = (struct tbd_struct *) ptr; /* TBD */ ptr = (char *) ptr + sizeof(struct tbd_struct); if ((void *) ptr > (void *) p->iscp) { pr_err("%s: not enough shared-mem for your configuration!\n", dev->name); return 1; } memset((char *) (p->xmit_cmds[i]), 0, sizeof(struct transmit_cmd_struct)); memset((char *) (p->xmit_buffs[i]), 0, sizeof(struct tbd_struct)); p->xmit_cmds[i]->cmd_status = STAT_COMPL; p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT; p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i])); p->xmit_buffs[i]->next = 0xffff; p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i])); } p->xmit_count = 0; p->xmit_last = 0; #ifndef NO_NOPCOMMANDS p->nop_point = 0; #endif /* * 'start transmitter' (nop-loop) */ #ifndef NO_NOPCOMMANDS p->scb->cbl_offset = make16(p->nop_cmds[0]); p->scb->cmd = CUC_START; elmc_id_attn586(); WAIT_4_SCB_CMD(); #else p->xmit_cmds[0]->cmd_link = 0xffff; p->xmit_cmds[0]->cmd_cmd = CMD_XMIT | CMD_LAST | CMD_INT; #endif return 0; }
static int init586(struct net_device *dev) { void *ptr; int i,result=0; struct priv *p = netdev_priv(dev); volatile struct configure_cmd_struct *cfg_cmd; volatile struct iasetup_cmd_struct *ias_cmd; volatile struct tdr_cmd_struct *tdr_cmd; volatile struct mcsetup_cmd_struct *mc_cmd; struct netdev_hw_addr *ha; int num_addrs=netdev_mc_count(dev); ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct)); cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */ cfg_cmd->cmd_status = 0; cfg_cmd->cmd_cmd = swab16(CMD_CONFIGURE | CMD_LAST); cfg_cmd->cmd_link = 0xffff; cfg_cmd->byte_cnt = 0x0a; /* number of cfg bytes */ cfg_cmd->fifo = fifo; /* fifo-limit (8=tx:32/rx:64) */ cfg_cmd->sav_bf = 0x40; /* hold or discard bad recv frames (bit 7) */ cfg_cmd->adr_len = 0x2e; /* addr_len |!src_insert |pre-len |loopback */ cfg_cmd->priority = 0x00; cfg_cmd->ifs = 0x60; cfg_cmd->time_low = 0x00; cfg_cmd->time_high = 0xf2; cfg_cmd->promisc = 0; if(dev->flags & IFF_ALLMULTI) { int len = ((char *) p->iscp - (char *) ptr - 8) / 6; if(num_addrs > len) { printk("%s: switching to promisc. mode\n",dev->name); cfg_cmd->promisc = 1; } } if(dev->flags&IFF_PROMISC) cfg_cmd->promisc = 1; cfg_cmd->carr_coll = 0x00; p->scb->cbl_offset = make16(cfg_cmd); p->scb->cmd_ruc = 0; p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */ sun3_attn586(); WAIT_4_STAT_COMPL(cfg_cmd); if((swab16(cfg_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK)) { printk("%s: configure command failed: %x\n",dev->name,swab16(cfg_cmd->cmd_status)); return 1; } /* * individual address setup */ ias_cmd = (struct iasetup_cmd_struct *)ptr; ias_cmd->cmd_status = 0; ias_cmd->cmd_cmd = swab16(CMD_IASETUP | CMD_LAST); ias_cmd->cmd_link = 0xffff; memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN); p->scb->cbl_offset = make16(ias_cmd); p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */ sun3_attn586(); WAIT_4_STAT_COMPL(ias_cmd); if((swab16(ias_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) { printk("%s (82586): individual address setup command failed: %04x\n",dev->name,swab16(ias_cmd->cmd_status)); return 1; } /* * TDR, wire check .. e.g. no resistor e.t.c */ tdr_cmd = (struct tdr_cmd_struct *)ptr; tdr_cmd->cmd_status = 0; tdr_cmd->cmd_cmd = swab16(CMD_TDR | CMD_LAST); tdr_cmd->cmd_link = 0xffff; tdr_cmd->status = 0; p->scb->cbl_offset = make16(tdr_cmd); p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */ sun3_attn586(); WAIT_4_STAT_COMPL(tdr_cmd); if(!(swab16(tdr_cmd->cmd_status) & STAT_COMPL)) { printk("%s: Problems while running the TDR.\n",dev->name); } else { DELAY_16(); /* wait for result */ result = swab16(tdr_cmd->status); p->scb->cmd_cuc = p->scb->cus & STAT_MASK; sun3_attn586(); /* ack the interrupts */ if(result & TDR_LNK_OK) ; else if(result & TDR_XCVR_PRB) printk("%s: TDR: Transceiver problem. Check the cable(s)!\n",dev->name); else if(result & TDR_ET_OPN) printk("%s: TDR: No correct termination %d clocks away.\n",dev->name,result & TDR_TIMEMASK); else if(result & TDR_ET_SRT) { if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */ printk("%s: TDR: Detected a short circuit %d clocks away.\n",dev->name,result & TDR_TIMEMASK); } else printk("%s: TDR: Unknown status %04x\n",dev->name,result); } /* * Multicast setup */ if(num_addrs && !(dev->flags & IFF_PROMISC) ) { mc_cmd = (struct mcsetup_cmd_struct *) ptr; mc_cmd->cmd_status = 0; mc_cmd->cmd_cmd = swab16(CMD_MCSETUP | CMD_LAST); mc_cmd->cmd_link = 0xffff; mc_cmd->mc_cnt = swab16(num_addrs * 6); i = 0; netdev_for_each_mc_addr(ha, dev) memcpy((char *) mc_cmd->mc_list[i++], ha->addr, ETH_ALEN); p->scb->cbl_offset = make16(mc_cmd); p->scb->cmd_cuc = CUC_START; sun3_attn586(); WAIT_4_STAT_COMPL(mc_cmd); if( (swab16(mc_cmd->cmd_status) & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK) ) printk("%s: Can't apply multicast-address-list.\n",dev->name); } /* * alloc nop/xmit-cmds */ #if (NUM_XMIT_BUFFS == 1) for(i=0;i<2;i++) { p->nop_cmds[i] = (struct nop_cmd_struct *)ptr; p->nop_cmds[i]->cmd_cmd = swab16(CMD_NOP); p->nop_cmds[i]->cmd_status = 0; p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); ptr = (char *) ptr + sizeof(struct nop_cmd_struct); } #else for(i=0;i<NUM_XMIT_BUFFS;i++) { p->nop_cmds[i] = (struct nop_cmd_struct *)ptr; p->nop_cmds[i]->cmd_cmd = swab16(CMD_NOP); p->nop_cmds[i]->cmd_status = 0; p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); ptr = (char *) ptr + sizeof(struct nop_cmd_struct); } #endif ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */ /* * alloc xmit-buffs / init xmit_cmds */ for(i=0;i<NUM_XMIT_BUFFS;i++) { p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/ ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */ ptr = (char *) ptr + XMIT_BUFF_SIZE; p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */ ptr = (char *) ptr + sizeof(struct tbd_struct); if((void *)ptr > (void *)dev->mem_end) { printk("%s: not enough shared-mem for your configuration!\n",dev->name); return 1; } memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct)); memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct)); p->xmit_cmds[i]->cmd_link = make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]); p->xmit_cmds[i]->cmd_status = swab16(STAT_COMPL); p->xmit_cmds[i]->cmd_cmd = swab16(CMD_XMIT | CMD_INT); p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i])); p->xmit_buffs[i]->next = 0xffff; p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i])); } p->xmit_count = 0; p->xmit_last = 0; #ifndef NO_NOPCOMMANDS p->nop_point = 0; #endif /* * 'start transmitter' */ #ifndef NO_NOPCOMMANDS p->scb->cbl_offset = make16(p->nop_cmds[0]); p->scb->cmd_cuc = CUC_START; sun3_attn586(); WAIT_4_SCB_CMD(); #else p->xmit_cmds[0]->cmd_link = make16(p->xmit_cmds[0]); p->xmit_cmds[0]->cmd_cmd = swab16(CMD_XMIT | CMD_SUSPEND | CMD_INT); #endif /* * ack. interrupts */ p->scb->cmd_cuc = p->scb->cus & STAT_MASK; sun3_attn586(); DELAY_16(); sun3_enaint(); sun3_active(); return 0; }
int android_ioctl_siwpriv(struct net_device *dev, struct iw_request_info *__info, struct iw_point *data, char *__extra) { char cmd[32]; /* assume that android command will not excess 32 */ char buf[32]; char *cmdbuf; int len = sizeof(cmd)-1; AR_SOFTC_DEV_T *arPriv = (AR_SOFTC_DEV_T *)ar6k_priv(dev); AR_SOFTC_STA_T *arSta = &arPriv->arSta; if (!data->pointer) { return -EOPNOTSUPP; } if (data->length < len) { len = data->length; } if (copy_from_user(cmd, data->pointer, len)) { return -EIO; } cmd[len] = 0; if (strcasecmp(cmd, "RSSI")==0 || strcasecmp(cmd, "RSSI-APPROX") == 0) { int rssi = -200; struct iw_statistics *iwStats; struct iw_statistics* (*get_iwstats)(struct net_device *); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) get_iwstats = dev->get_wireless_stats; #else get_iwstats = dev->wireless_handlers->get_wireless_stats; #endif if (get_iwstats && arPriv->arConnected) { iwStats = get_iwstats(dev); if (iwStats) { rssi = iwStats->qual.qual; if (rssi == 255) rssi = -200; else rssi += (161 - 256); } } len = snprintf(buf, data->length, "SSID rssi %d\n", rssi) + 1; return (copy_to_user(data->pointer, buf, len)==0) ? len : -1; } else if (strcasecmp(cmd, "LINKSPEED")==0) { /* We skip to use SIOCGIWRATE since Android always asked LINKSPEED just after RSSI*/ unsigned int speed_mbps; if (arPriv->arConnected) { speed_mbps = arPriv->arTargetStats.tx_unicast_rate / 1000; } else { speed_mbps = 1; } len = snprintf(buf, data->length, "LinkSpeed %u\n", speed_mbps) + 1; return (copy_to_user(data->pointer, buf, len)==0) ? len : -1; } else if (memcmp(cmd, "CSCAN S\x01\x00\x00S\x00", 12)==0) { int ret=0; if (!(cmdbuf = A_MALLOC(data->length))) return -ENOMEM; if (copy_from_user(cmdbuf, data->pointer, data->length)) { A_FREE(cmdbuf); return -EFAULT; } ret = ar6000_cscan(dev,data, cmdbuf); A_FREE(cmdbuf); return ret; } else if (strcasecmp(cmd, "MACADDR")==0) { /* reply comes back in the form "Macaddr = XX:XX:XX:XX:XX:XX" where XX */ A_UCHAR *mac = dev->dev_addr; len = snprintf(buf, data->length, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) + 1; return (copy_to_user(data->pointer, buf, len)==0) ? len : -1; } else if (strcasecmp(cmd, "SCAN-ACTIVE")==0) { return 0; /* unsupport function. Suppress the error */ } else if (strcasecmp(cmd, "SCAN-PASSIVE")==0) { return 0; /* unsupport function. Suppress the error */ } else if (strcasecmp(cmd, "START")==0 || strcasecmp(cmd, "STOP")==0) { struct ifreq ifr; char userBuf[16]; int ex_arg = (strcasecmp(cmd, "START")==0) ? WLAN_ENABLED : WLAN_DISABLED; int ret; A_MEMZERO(userBuf, sizeof(userBuf)); ((int *)userBuf)[0] = AR6000_XIOCTRL_WMI_SET_WLAN_STATE; ((int *)userBuf)[1] = ex_arg; ret = android_do_ioctl_direct(dev, AR6000_IOCTL_EXTENDED, &ifr, userBuf); if (ret==0) { /* Send wireless event which need by android supplicant */ union iwreq_data wrqu; A_MEMZERO(&wrqu, sizeof(wrqu)); wrqu.data.length = strlen(cmd); wireless_send_event(dev, IWEVCUSTOM, &wrqu, cmd); } return ret; } else if (strncasecmp(cmd, "POWERMODE ", 10)==0) { int mode; if (sscanf(cmd, "%*s %d", &mode) == 1) { int iocmd = SIOCSIWPOWER - SIOCSIWCOMMIT; iw_handler setPower = dev->wireless_handlers->standard[iocmd]; if (setPower) { union iwreq_data miwr; struct iw_request_info minfo; A_MEMZERO(&minfo, sizeof(minfo)); A_MEMZERO(&miwr, sizeof(miwr)); minfo.cmd = SIOCSIWPOWER; if (mode == 0 /* auto */) miwr.power.disabled = 0; else if (mode == 1 /* active */) miwr.power.disabled = 1; else return -1; return setPower(dev, &minfo, &miwr, NULL); } } return -1; } else if (strcasecmp(cmd, "GETPOWER")==0) { struct ifreq ifr; int userBuf[2]; A_MEMZERO(userBuf, sizeof(userBuf)); ((int *)userBuf)[0] = AR6000_XIOCTRL_WMI_GET_POWER_MODE; if (android_do_ioctl_direct(dev, AR6000_IOCTL_EXTENDED, &ifr, userBuf)>=0) { WMI_POWER_MODE_CMD *getPowerMode = (WMI_POWER_MODE_CMD *)userBuf; len = snprintf(buf, data->length, "powermode = %u\n", (getPowerMode->powerMode==MAX_PERF_POWER) ? 1/*active*/ : 0/*auto*/) + 1; return (copy_to_user(data->pointer, buf, len)==0) ? len : -1; } return -1; } else if (strcasecmp(cmd, "GETBAND")==0) { int band; /*0: auto, 1: 5GHz only, 2: 2.4GHz Only*/ switch (arPriv->arPhyCapability) { case WMI_11A_CAPABILITY: case WMI_11NA_CAPABILITY: band = 1; break; case WMI_11NG_CAPABILITY: case WMI_11G_CAPABILITY: band = 2; break; case WMI_11AG_CAPABILITY: case WMI_11NAG_CAPABILITY: default: band = 0; break; } len = snprintf(buf, data->length, "Band %d\n", band) + 1; return (copy_to_user(data->pointer, buf, len)==0) ? len : -1; } else if (strncasecmp(cmd, "SETBAND ", 8)==0) { int band; if (sscanf(cmd, "%*s %d", &band) == 1) { switch (band) { case 1: /* 5GHz Only*/ /* TODO: Using WMI_CHANNEL_PARAMS_CMD to disable all 5GHz channels? */ break; case 2: /* 5GHz Only*/ /* TODO: Using WMI_CHANNEL_PARAMS_CMD to disable all 2.4GHz channels? */ break; case 0: /* auto */ default: break; } return 0; } return -1; } else if (strncasecmp(cmd, "SETSUSPENDOPT ", 14)==0) { int enable; if (sscanf(cmd, "%*s %d", &enable)==1) { /* * We set our suspend mode by wlan_config.h now. * Should we follow Android command?? TODO */ return 0; } return -1; } else if (strcasecmp(cmd, "SCAN-CHANNELS")==0) { // reply comes back in the form "Scan-Channels = X" where X is the number of channels int iocmd = SIOCGIWRANGE - SIOCSIWCOMMIT; iw_handler getRange = dev->wireless_handlers->standard[iocmd]; if (getRange) { union iwreq_data miwr; struct iw_request_info minfo; struct iw_range range; A_MEMZERO(&minfo, sizeof(minfo)); A_MEMZERO(&miwr, sizeof(miwr)); A_MEMZERO(&range, sizeof(range)); minfo.cmd = SIOCGIWRANGE; miwr.data.pointer = (__force void __user *) ⦥ miwr.data.length = sizeof(range); getRange(dev, &minfo, &miwr, (char*)&range); } if (arSta->arNumChannels!=-1) { len = snprintf(buf, data->length, "Scan-Channels = %d\n", arSta->arNumChannels) + 1; return (copy_to_user(data->pointer, buf, len)==0) ? len : -1; } return -1; } else if (strncasecmp(cmd, "SCAN-CHANNELS ", 14)==0 || strncasecmp(cmd, "COUNTRY ", 8)==0) { /* * Set the available channels with WMI_SET_CHANNELPARAMS cmd * However, the channels will be limited by the eeprom regulator domain * Try to use a regulator domain which will not limited the channels range. */ int i; int chan = 0; A_UINT16 *clist; struct ifreq ifr; char ioBuf[256]; WMI_CHANNEL_PARAMS_CMD *chParamCmd = (WMI_CHANNEL_PARAMS_CMD *)ioBuf; if (strncasecmp(cmd, "COUNTRY ", 8)==0) { char *country = cmd + 8; if (strcasecmp(country, "US")==0) { chan = 11; } else if (strcasecmp(country, "JP")==0) { chan = 14; } else if (strcasecmp(country, "EU")==0) { chan = 13; } } else if (sscanf(cmd, "%*s %d", &chan) != 1) { return -1; } if ( (chan != 11) && (chan != 13) && (chan != 14)) { return -1; } if (arPriv->arNextMode == AP_NETWORK) { return -1; } A_MEMZERO(&ifr, sizeof(ifr)); A_MEMZERO(ioBuf, sizeof(ioBuf)); chParamCmd->phyMode = WMI_11G_MODE; clist = chParamCmd->channelList; chParamCmd->numChannels = chan; chParamCmd->scanParam = 1; for (i = 0; i < chan; i++) { clist[i] = wlan_ieee2freq(i + 1); } return android_do_ioctl_direct(dev, AR6000_IOCTL_WMI_SET_CHANNELPARAMS, &ifr, ioBuf); } else if (strncasecmp(cmd, "BTCOEXMODE ", 11)==0) { int mode; if (sscanf(cmd, "%*s %d", &mode)==1) { /* * Android disable BT-COEX when obtaining dhcp packet except there is headset is connected * It enable the BT-COEX after dhcp process is finished * We ignore since we have our way to do bt-coex during dhcp obtaining. */ switch (mode) { case 1: /* Disable*/ break; case 0: /* Enable */ /* fall through */ case 2: /* Sense*/ /* fall through */ default: break; } return 0; /* ignore it */ } return -1; } else if (strcasecmp(cmd, "BTCOEXSCAN-START")==0) { /* Android enable or disable Bluetooth coexistence scan mode. When this mode is on, * some of the low-level scan parameters used by the driver are changed to * reduce interference with A2DP streaming. */ return 0; /* ignore it since we have btfilter */ } else if (strcasecmp(cmd, "BTCOEXSCAN-STOP")==0) { return 0; /* ignore it since we have btfilter */ } else if (strncasecmp(cmd, "RXFILTER-ADD ", 13)==0) { return 0; /* ignore it */ } else if (strncasecmp(cmd, "RXFILTER-REMOVE ", 16)==0) { return 0; /* ignoret it */ } else if (strcasecmp(cmd, "RXFILTER-START")==0 || strcasecmp(cmd, "RXFILTER-STOP")==0) { unsigned int flags = dev->flags; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) int mc_count = dev->mc_count; #else int mc_count = netdev_mc_count(dev); #endif if (strcasecmp(cmd, "RXFILTER-START")==0) { if (mc_count > 0 || (flags & IFF_MULTICAST) ) { //flags &= ~IFF_MULTICAST; //to always enable multicast flags |= IFF_MULTICAST; } } else { flags |= IFF_MULTICAST; } if (flags != dev->flags) { dev_change_flags(dev, flags); } return 0; } return -EOPNOTSUPP; }