⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adm8211.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			break;		}	} else		printk(KERN_DEBUG "%s: unsupported BBP %d\n",		       wiphy_name(dev->wiphy), priv->bbp_type);	ADM8211_CSR_WRITE(SYNRF, 0);	/* Set RF CAL control source to MAC control */	reg = ADM8211_CSR_READ(SYNCTL);	reg |= ADM8211_SYNCTL_SELCAL;	ADM8211_CSR_WRITE(SYNCTL, reg);	return 0;}/* configures hw beacons/probe responses */static int adm8211_set_rate(struct ieee80211_hw *dev){	struct adm8211_priv *priv = dev->priv;	u32 reg;	int i = 0;	u8 rate_buf[12] = {0};	/* write supported rates */	if (priv->pdev->revision != ADM8211_REV_BA) {		rate_buf[0] = ARRAY_SIZE(adm8211_rates);		for (i = 0; i < ARRAY_SIZE(adm8211_rates); i++)			rate_buf[i + 1] = (adm8211_rates[i].rate / 5) | 0x80;	} else {		/* workaround for rev BA specific bug */		rate_buf[0] = 0x04;		rate_buf[1] = 0x82;		rate_buf[2] = 0x04;		rate_buf[3] = 0x0b;		rate_buf[4] = 0x16;	}	adm8211_write_sram_bytes(dev, ADM8211_SRAM_SUPP_RATE, rate_buf,				 ARRAY_SIZE(adm8211_rates) + 1);	reg = ADM8211_CSR_READ(PLCPHD) & 0x00FFFFFF; /* keep bits 0-23 */	reg |= 1 << 15;	/* short preamble */	reg |= 110 << 24;	ADM8211_CSR_WRITE(PLCPHD, reg);	/* MTMLT   = 512 TU (max TX MSDU lifetime)	 * BCNTSIG = plcp_signal (beacon, probe resp, and atim TX rate)	 * SRTYLIM = 224 (short retry limit, TX header value is default) */	ADM8211_CSR_WRITE(TXLMT, (512 << 16) | (110 << 8) | (224 << 0));	return 0;}static void adm8211_hw_init(struct ieee80211_hw *dev){	struct adm8211_priv *priv = dev->priv;	u32 reg;	u8 cline;	reg = le32_to_cpu(ADM8211_CSR_READ(PAR));	reg |= ADM8211_PAR_MRLE | ADM8211_PAR_MRME;	reg &= ~(ADM8211_PAR_BAR | ADM8211_PAR_CAL);	if (!pci_set_mwi(priv->pdev)) {		reg |= 0x1 << 24;		pci_read_config_byte(priv->pdev, PCI_CACHE_LINE_SIZE, &cline);		switch (cline) {		case  0x8: reg |= (0x1 << 14);			   break;		case 0x16: reg |= (0x2 << 14);			   break;		case 0x32: reg |= (0x3 << 14);			   break;		  default: reg |= (0x0 << 14);			   break;		}	}	ADM8211_CSR_WRITE(PAR, reg);	reg = ADM8211_CSR_READ(CSR_TEST1);	reg &= ~(0xF << 28);	reg |= (1 << 28) | (1 << 31);	ADM8211_CSR_WRITE(CSR_TEST1, reg);	/* lose link after 4 lost beacons */	reg = (0x04 << 21) | ADM8211_WCSR_TSFTWE | ADM8211_WCSR_LSOE;	ADM8211_CSR_WRITE(WCSR, reg);	/* Disable APM, enable receive FIFO threshold, and set drain receive	 * threshold to store-and-forward */	reg = ADM8211_CSR_READ(CMDR);	reg &= ~(ADM8211_CMDR_APM | ADM8211_CMDR_DRT);	reg |= ADM8211_CMDR_RTE | ADM8211_CMDR_DRT_SF;	ADM8211_CSR_WRITE(CMDR, reg);	adm8211_set_rate(dev);	/* 4-bit values:	 * PWR1UP   = 8 * 2 ms	 * PWR0PAPE = 8 us or 5 us	 * PWR1PAPE = 1 us or 3 us	 * PWR0TRSW = 5 us	 * PWR1TRSW = 12 us	 * PWR0PE2  = 13 us	 * PWR1PE2  = 1 us	 * PWR0TXPE = 8 or 6 */	if (priv->pdev->revision < ADM8211_REV_CA)		ADM8211_CSR_WRITE(TOFS2, 0x8815cd18);	else		ADM8211_CSR_WRITE(TOFS2, 0x8535cd16);	/* Enable store and forward for transmit */	priv->nar = ADM8211_NAR_SF | ADM8211_NAR_PB;	ADM8211_CSR_WRITE(NAR, priv->nar);	/* Reset RF */	ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_RADIO);	ADM8211_CSR_READ(SYNRF);	msleep(10);	ADM8211_CSR_WRITE(SYNRF, 0);	ADM8211_CSR_READ(SYNRF);	msleep(5);	/* Set CFP Max Duration to 0x10 TU */	reg = ADM8211_CSR_READ(CFPP);	reg &= ~(0xffff << 8);	reg |= 0x0010 << 8;	ADM8211_CSR_WRITE(CFPP, reg);	/* USCNT = 0x16 (number of system clocks, 22 MHz, in 1us	 * TUCNT = 0x3ff - Tu counter 1024 us  */	ADM8211_CSR_WRITE(TOFS0, (0x16 << 24) | 0x3ff);	/* SLOT=20 us, SIFS=110 cycles of 22 MHz (5 us),	 * DIFS=50 us, EIFS=100 us */	if (priv->pdev->revision < ADM8211_REV_CA)		ADM8211_CSR_WRITE(IFST, (20 << 23) | (110 << 15) |					(50 << 9)  | 100);	else		ADM8211_CSR_WRITE(IFST, (20 << 23) | (24 << 15) |					(50 << 9)  | 100);	/* PCNT = 1 (MAC idle time awake/sleep, unit S)	 * RMRD = 2346 * 8 + 1 us (max RX duration)  */	ADM8211_CSR_WRITE(RMD, (1 << 16) | 18769);	/* MART=65535 us, MIRT=256 us, TSFTOFST=0 us */	ADM8211_CSR_WRITE(RSPT, 0xffffff00);	/* Initialize BBP (and SYN) */	adm8211_hw_init_bbp(dev);	/* make sure interrupts are off */	ADM8211_CSR_WRITE(IER, 0);	/* ACK interrupts */	ADM8211_CSR_WRITE(STSR, ADM8211_CSR_READ(STSR));	/* Setup WEP (turns it off for now) */	reg = ADM8211_CSR_READ(MACTEST);	reg &= ~(7 << 20);	ADM8211_CSR_WRITE(MACTEST, reg);	reg = ADM8211_CSR_READ(WEPCTL);	reg &= ~ADM8211_WEPCTL_WEPENABLE;	reg |= ADM8211_WEPCTL_WEPRXBYP;	ADM8211_CSR_WRITE(WEPCTL, reg);	/* Clear the missed-packet counter. */	ADM8211_CSR_READ(LPC);}static int adm8211_hw_reset(struct ieee80211_hw *dev){	struct adm8211_priv *priv = dev->priv;	u32 reg, tmp;	int timeout = 100;	/* Power-on issue */	/* TODO: check if this is necessary */	ADM8211_CSR_WRITE(FRCTL, 0);	/* Reset the chip */	tmp = ADM8211_CSR_READ(PAR);	ADM8211_CSR_WRITE(PAR, ADM8211_PAR_SWR);	while ((ADM8211_CSR_READ(PAR) & ADM8211_PAR_SWR) && timeout--)		msleep(50);	if (timeout <= 0)		return -ETIMEDOUT;	ADM8211_CSR_WRITE(PAR, tmp);	if (priv->pdev->revision == ADM8211_REV_BA &&	    (priv->transceiver_type == ADM8211_RFMD2958_RF3000_CONTROL_POWER ||	     priv->transceiver_type == ADM8211_RFMD2958)) {		reg = ADM8211_CSR_READ(CSR_TEST1);		reg |= (1 << 4) | (1 << 5);		ADM8211_CSR_WRITE(CSR_TEST1, reg);	} else if (priv->pdev->revision == ADM8211_REV_CA) {		reg = ADM8211_CSR_READ(CSR_TEST1);		reg &= ~((1 << 4) | (1 << 5));		ADM8211_CSR_WRITE(CSR_TEST1, reg);	}	ADM8211_CSR_WRITE(FRCTL, 0);	reg = ADM8211_CSR_READ(CSR_TEST0);	reg |= ADM8211_CSR_TEST0_EPRLD;	/* EEPROM Recall */	ADM8211_CSR_WRITE(CSR_TEST0, reg);	adm8211_clear_sram(dev);	return 0;}static u64 adm8211_get_tsft(struct ieee80211_hw *dev){	struct adm8211_priv *priv = dev->priv;	u32 tsftl;	u64 tsft;	tsftl = ADM8211_CSR_READ(TSFTL);	tsft = ADM8211_CSR_READ(TSFTH);	tsft <<= 32;	tsft |= tsftl;	return tsft;}static void adm8211_set_interval(struct ieee80211_hw *dev,				 unsigned short bi, unsigned short li){	struct adm8211_priv *priv = dev->priv;	u32 reg;	/* BP (beacon interval) = data->beacon_interval	 * LI (listen interval) = data->listen_interval (in beacon intervals) */	reg = (bi << 16) | li;	ADM8211_CSR_WRITE(BPLI, reg);}static void adm8211_set_bssid(struct ieee80211_hw *dev, const u8 *bssid){	struct adm8211_priv *priv = dev->priv;	u32 reg;	ADM8211_CSR_WRITE(BSSID0, le32_to_cpu(*(__le32 *)bssid));	reg = ADM8211_CSR_READ(ABDA1);	reg &= 0x0000ffff;	reg |= (bssid[4] << 16) | (bssid[5] << 24);	ADM8211_CSR_WRITE(ABDA1, reg);}static int adm8211_set_ssid(struct ieee80211_hw *dev, u8 *ssid, size_t ssid_len){	struct adm8211_priv *priv = dev->priv;	u8 buf[36];	if (ssid_len > 32)		return -EINVAL;	memset(buf, 0, sizeof(buf));	buf[0] = ssid_len;	memcpy(buf + 1, ssid, ssid_len);	adm8211_write_sram_bytes(dev, ADM8211_SRAM_SSID, buf, 33);	/* TODO: configure beacon for adhoc? */	return 0;}static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf){	struct adm8211_priv *priv = dev->priv;	if (conf->channel != priv->channel) {		priv->channel = conf->channel;		adm8211_rf_set_channel(dev, priv->channel);	}	return 0;}static int adm8211_config_interface(struct ieee80211_hw *dev, int if_id,				    struct ieee80211_if_conf *conf){	struct adm8211_priv *priv = dev->priv;	if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {		adm8211_set_bssid(dev, conf->bssid);		memcpy(priv->bssid, conf->bssid, ETH_ALEN);	}	if (conf->ssid_len != priv->ssid_len ||	    memcmp(conf->ssid, priv->ssid, conf->ssid_len)) {		adm8211_set_ssid(dev, conf->ssid, conf->ssid_len);		priv->ssid_len = conf->ssid_len;		memcpy(priv->ssid, conf->ssid, conf->ssid_len);	}	return 0;}static void adm8211_configure_filter(struct ieee80211_hw *dev,				     unsigned int changed_flags,				     unsigned int *total_flags,				     int mc_count, struct dev_mc_list *mclist){	static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };	struct adm8211_priv *priv = dev->priv;	unsigned int bit_nr, new_flags;	u32 mc_filter[2];	int i;	new_flags = 0;	if (*total_flags & FIF_PROMISC_IN_BSS) {		new_flags |= FIF_PROMISC_IN_BSS;		priv->nar |= ADM8211_NAR_PR;		priv->nar &= ~ADM8211_NAR_MM;		mc_filter[1] = mc_filter[0] = ~0;	} else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) {		new_flags |= FIF_ALLMULTI;		priv->nar &= ~ADM8211_NAR_PR;		priv->nar |= ADM8211_NAR_MM;		mc_filter[1] = mc_filter[0] = ~0;	} else {		priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR);		mc_filter[1] = mc_filter[0] = 0;		for (i = 0; i < mc_count; i++) {			if (!mclist)				break;			bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;			bit_nr &= 0x3F;			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);			mclist = mclist->next;		}	}	ADM8211_IDLE_RX();	ADM8211_CSR_WRITE(MAR0, mc_filter[0]);	ADM8211_CSR_WRITE(MAR1, mc_filter[1]);	ADM8211_CSR_READ(NAR);	if (priv->nar & ADM8211_NAR_PR)		dev->flags |= IEEE80211_HW_RX_INCLUDES_FCS;	else		dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;	if (*total_flags & FIF_BCN_PRBRESP_PROMISC)		adm8211_set_bssid(dev, bcast);	else		adm8211_set_bssid(dev, priv->bssid);	ADM8211_RESTORE();	*total_flags = new_flags;}static int adm8211_add_interface(struct ieee80211_hw *dev,				 struct ieee80211_if_init_conf *conf){	struct adm8211_priv *priv = dev->priv;	if (priv->mode != IEEE80211_IF_TYPE_MNTR)		return -EOPNOTSUPP;	switch (conf->type) {	case IEEE80211_IF_TYPE_STA:		priv->mode = conf->type;		break;	default:		return -EOPNOTSUPP;	}	ADM8211_IDLE();	ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)conf->mac_addr));	ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(conf->mac_addr + 4)));	adm8211_update_mode(dev);	ADM8211_RESTORE();	return 0;}static void adm8211_remove_interface(struct ieee80211_hw *dev,				     struct ieee80211_if_init_conf *conf){	struct adm8211_priv *priv = dev->priv;	priv->mode = IEEE80211_IF_TYPE_MNTR;}static int adm8211_init_rings(struct ieee80211_hw *dev){	struct adm8211_priv *priv = dev->priv;	struct adm8211_desc *desc = NULL;	struct adm8211_rx_ring_info *rx_info;	struct adm8211_tx_ring_info *tx_info;	unsigned int i;	for (i = 0; i < priv->rx_ring_size; i++) {		desc = &priv->rx_ring[i];		desc->status = 0;		desc->length = cpu_to_le32(RX_PKT_SIZE);		priv->rx_buffers[i].skb = NULL;	}	/* Mark the end of RX ring; hw returns to base address after this	 * descriptor */	desc->length |= cpu_to_le32(RDES1_CONTROL_RER);	for (i = 0; i < priv->rx_ring_size; i++) {		desc = &priv->rx_ring[i];		rx_info = &priv->rx_buffers[i];		rx_info->skb = dev_alloc_skb(RX_PKT_SIZE);		if (rx_info->skb == NULL)			break;		rx_info->mapping = pci_map_single(priv->pdev,						  skb_tail_pointer(rx_info->skb),						  RX_PKT_SIZE,						  PCI_DMA_FROMDEVICE);		desc->buffer1 = cpu_to_le32(rx_info->mapping);		desc->status = cpu_to_le32(RDES0_STATUS_OWN | RDES0_STATUS_SQL);	}	/* Setup TX ring. TX buffers descriptors will be filled in as needed */	for (i = 0; i < priv->tx_ring_size; i++) {		desc = &priv->tx_ring[i];		tx_info = &priv->tx_buffers[i];		tx_info->skb = NULL;		tx_info->mapping = 0;		desc->status = 0;	}	desc->length = cpu_to_le32(TDES1_CONTROL_TER);	priv->cur_rx = priv->cur_tx = priv->dirty_tx = 0;	ADM8211_CSR_WRITE(RDB, priv->rx_ring_dma);	ADM8211_CSR_WRITE(TDBD, priv->tx_ring_dma);	return 0;}static void adm8211_free_rings(struct ieee80211_hw *dev){	struct adm8211_priv *priv = dev->priv;	unsigned int i;	for (i = 0; i < priv->rx_ring_size; i++) {		if (!priv->rx_buffers[i].skb)			continue;		pci_unmap_single(			priv->pdev,			priv->rx_buffers[i].mapping,			RX_PKT_SIZE, PCI_DMA_FROMDEVICE);		dev_kfree_skb(priv->rx_buffers[i].skb);	}	for (i = 0; i < priv->tx_ring_size; i++) {		if (!priv->tx_buffers[i].skb)			continue;		pci_unmap_single(priv->pdev,				 priv->tx_buffers[i].mapping,				 priv->tx_buffers[i].skb->len,				 PCI_DMA_TODEVICE);		dev_kfree_skb(priv->tx_buffers[i].skb);	}}static int adm8211_start(struct ieee80211_hw *dev){	struct adm8211_priv *priv = dev->priv;	int retval;	/* Power up MAC and RF chips */	retval = adm8211_hw_reset(dev);	if (retval) {		printk(KERN_ERR "%s: hardware reset failed\n",		       wiphy_name(dev->wiphy));		goto fail;	}	retval = adm8211_init_rings(dev);	if (retval) {		printk(KERN_ERR "%s: failed to initialize rings\n",		       wiphy_name(dev->wiphy));		goto fail;	}	/* Init hardware */	adm8211_hw_init(dev);	adm8211_rf_set_channel(dev, priv->channel);	retval = request_irq(priv->pdev->irq, &adm8211_interrupt,			     IRQF_SHARED, "adm8211", dev);	if (retval) {		printk(KERN_ERR "%s: failed to register IRQ handler\n",		       wiphy_name(dev->wiphy));		goto fail;	}	ADM8211_CSR_WRITE(IER, ADM8211_IER_NIE | ADM8211_IER_AIE |			       ADM8211_IER_RCIE | ADM8211_IER_TCIE |			       ADM8211_IER_TDUIE | ADM8211_IER_GPTIE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -