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

📄 main.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (dev->dev->id.revision < 5)		return;	/* Read all entries from the microcode TXstatus FIFO	 * and throw them away.	 */	while (1) {		dummy = b43_read32(dev, B43_MMIO_XMITSTAT_0);		if (!(dummy & 0x00000001))			break;		dummy = b43_read32(dev, B43_MMIO_XMITSTAT_1);	}}static u32 b43_jssi_read(struct b43_wldev *dev){	u32 val = 0;	val = b43_shm_read16(dev, B43_SHM_SHARED, 0x08A);	val <<= 16;	val |= b43_shm_read16(dev, B43_SHM_SHARED, 0x088);	return val;}static void b43_jssi_write(struct b43_wldev *dev, u32 jssi){	b43_shm_write16(dev, B43_SHM_SHARED, 0x088, (jssi & 0x0000FFFF));	b43_shm_write16(dev, B43_SHM_SHARED, 0x08A, (jssi & 0xFFFF0000) >> 16);}static void b43_generate_noise_sample(struct b43_wldev *dev){	b43_jssi_write(dev, 0x7F7F7F7F);	b43_write32(dev, B43_MMIO_STATUS2_BITFIELD,		    b43_read32(dev, B43_MMIO_STATUS2_BITFIELD)		    | (1 << 4));	B43_WARN_ON(dev->noisecalc.channel_at_start != dev->phy.channel);}static void b43_calculate_link_quality(struct b43_wldev *dev){	/* Top half of Link Quality calculation. */	if (dev->noisecalc.calculation_running)		return;	dev->noisecalc.channel_at_start = dev->phy.channel;	dev->noisecalc.calculation_running = 1;	dev->noisecalc.nr_samples = 0;	b43_generate_noise_sample(dev);}static void handle_irq_noise(struct b43_wldev *dev){	struct b43_phy *phy = &dev->phy;	u16 tmp;	u8 noise[4];	u8 i, j;	s32 average;	/* Bottom half of Link Quality calculation. */	B43_WARN_ON(!dev->noisecalc.calculation_running);	if (dev->noisecalc.channel_at_start != phy->channel)		goto drop_calculation;	*((__le32 *)noise) = cpu_to_le32(b43_jssi_read(dev));	if (noise[0] == 0x7F || noise[1] == 0x7F ||	    noise[2] == 0x7F || noise[3] == 0x7F)		goto generate_new;	/* Get the noise samples. */	B43_WARN_ON(dev->noisecalc.nr_samples >= 8);	i = dev->noisecalc.nr_samples;	noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);	noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);	noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);	noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);	dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]];	dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]];	dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]];	dev->noisecalc.samples[i][3] = phy->nrssi_lt[noise[3]];	dev->noisecalc.nr_samples++;	if (dev->noisecalc.nr_samples == 8) {		/* Calculate the Link Quality by the noise samples. */		average = 0;		for (i = 0; i < 8; i++) {			for (j = 0; j < 4; j++)				average += dev->noisecalc.samples[i][j];		}		average /= (8 * 4);		average *= 125;		average += 64;		average /= 128;		tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x40C);		tmp = (tmp / 128) & 0x1F;		if (tmp >= 8)			average += 2;		else			average -= 25;		if (tmp == 8)			average -= 72;		else			average -= 48;		dev->stats.link_noise = average;	      drop_calculation:		dev->noisecalc.calculation_running = 0;		return;	}      generate_new:	b43_generate_noise_sample(dev);}static void handle_irq_tbtt_indication(struct b43_wldev *dev){	if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) {		///TODO: PS TBTT	} else {		if (1 /*FIXME: the last PSpoll frame was sent successfully */ )			b43_power_saving_ctl_bits(dev, 0);	}	dev->reg124_set_0x4 = 0;	if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))		dev->reg124_set_0x4 = 1;}static void handle_irq_atim_end(struct b43_wldev *dev){	if (!dev->reg124_set_0x4 /*FIXME rename this variable */ )		return;	b43_write32(dev, B43_MMIO_STATUS2_BITFIELD,		    b43_read32(dev, B43_MMIO_STATUS2_BITFIELD)		    | 0x4);}static void handle_irq_pmq(struct b43_wldev *dev){	u32 tmp;	//TODO: AP mode.	while (1) {		tmp = b43_read32(dev, B43_MMIO_PS_STATUS);		if (!(tmp & 0x00000008))			break;	}	/* 16bit write is odd, but correct. */	b43_write16(dev, B43_MMIO_PS_STATUS, 0x0002);}static void b43_write_template_common(struct b43_wldev *dev,				      const u8 * data, u16 size,				      u16 ram_offset,				      u16 shm_size_offset, u8 rate){	u32 i, tmp;	struct b43_plcp_hdr4 plcp;	plcp.data = 0;	b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);	b43_ram_write(dev, ram_offset, le32_to_cpu(plcp.data));	ram_offset += sizeof(u32);	/* The PLCP is 6 bytes long, but we only wrote 4 bytes, yet.	 * So leave the first two bytes of the next write blank.	 */	tmp = (u32) (data[0]) << 16;	tmp |= (u32) (data[1]) << 24;	b43_ram_write(dev, ram_offset, tmp);	ram_offset += sizeof(u32);	for (i = 2; i < size; i += sizeof(u32)) {		tmp = (u32) (data[i + 0]);		if (i + 1 < size)			tmp |= (u32) (data[i + 1]) << 8;		if (i + 2 < size)			tmp |= (u32) (data[i + 2]) << 16;		if (i + 3 < size)			tmp |= (u32) (data[i + 3]) << 24;		b43_ram_write(dev, ram_offset + i - 2, tmp);	}	b43_shm_write16(dev, B43_SHM_SHARED, shm_size_offset,			size + sizeof(struct b43_plcp_hdr6));}static void b43_write_beacon_template(struct b43_wldev *dev,				      u16 ram_offset,				      u16 shm_size_offset, u8 rate){	int len;	const u8 *data;	B43_WARN_ON(!dev->cached_beacon);	len = min((size_t) dev->cached_beacon->len,		  0x200 - sizeof(struct b43_plcp_hdr6));	data = (const u8 *)(dev->cached_beacon->data);	b43_write_template_common(dev, data,				  len, ram_offset, shm_size_offset, rate);}static void b43_write_probe_resp_plcp(struct b43_wldev *dev,				      u16 shm_offset, u16 size, u8 rate){	struct b43_plcp_hdr4 plcp;	u32 tmp;	__le16 dur;	plcp.data = 0;	b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);	dur = ieee80211_generic_frame_duration(dev->wl->hw,					       dev->wl->if_id, size,					       B43_RATE_TO_BASE100KBPS(rate));	/* Write PLCP in two parts and timing for packet transfer */	tmp = le32_to_cpu(plcp.data);	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF);	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 2, tmp >> 16);	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 6, le16_to_cpu(dur));}/* Instead of using custom probe response template, this function * just patches custom beacon template by: * 1) Changing packet type * 2) Patching duration field * 3) Stripping TIM */static u8 *b43_generate_probe_resp(struct b43_wldev *dev,				   u16 * dest_size, u8 rate){	const u8 *src_data;	u8 *dest_data;	u16 src_size, elem_size, src_pos, dest_pos;	__le16 dur;	struct ieee80211_hdr *hdr;	B43_WARN_ON(!dev->cached_beacon);	src_size = dev->cached_beacon->len;	src_data = (const u8 *)dev->cached_beacon->data;	if (unlikely(src_size < 0x24)) {		b43dbg(dev->wl, "b43_generate_probe_resp: " "invalid beacon\n");		return NULL;	}	dest_data = kmalloc(src_size, GFP_ATOMIC);	if (unlikely(!dest_data))		return NULL;	/* 0x24 is offset of first variable-len Information-Element	 * in beacon frame.	 */	memcpy(dest_data, src_data, 0x24);	src_pos = dest_pos = 0x24;	for (; src_pos < src_size - 2; src_pos += elem_size) {		elem_size = src_data[src_pos + 1] + 2;		if (src_data[src_pos] != 0x05) {	/* TIM */			memcpy(dest_data + dest_pos, src_data + src_pos,			       elem_size);			dest_pos += elem_size;		}	}	*dest_size = dest_pos;	hdr = (struct ieee80211_hdr *)dest_data;	/* Set the frame control. */	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |					 IEEE80211_STYPE_PROBE_RESP);	dur = ieee80211_generic_frame_duration(dev->wl->hw,					       dev->wl->if_id, *dest_size,					       B43_RATE_TO_BASE100KBPS(rate));	hdr->duration_id = dur;	return dest_data;}static void b43_write_probe_resp_template(struct b43_wldev *dev,					  u16 ram_offset,					  u16 shm_size_offset, u8 rate){	u8 *probe_resp_data;	u16 size;	B43_WARN_ON(!dev->cached_beacon);	size = dev->cached_beacon->len;	probe_resp_data = b43_generate_probe_resp(dev, &size, rate);	if (unlikely(!probe_resp_data))		return;	/* Looks like PLCP headers plus packet timings are stored for	 * all possible basic rates	 */	b43_write_probe_resp_plcp(dev, 0x31A, size, B43_CCK_RATE_1MB);	b43_write_probe_resp_plcp(dev, 0x32C, size, B43_CCK_RATE_2MB);	b43_write_probe_resp_plcp(dev, 0x33E, size, B43_CCK_RATE_5MB);	b43_write_probe_resp_plcp(dev, 0x350, size, B43_CCK_RATE_11MB);	size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6));	b43_write_template_common(dev, probe_resp_data,				  size, ram_offset, shm_size_offset, rate);	kfree(probe_resp_data);}static int b43_refresh_cached_beacon(struct b43_wldev *dev,				     struct sk_buff *beacon){	if (dev->cached_beacon)		kfree_skb(dev->cached_beacon);	dev->cached_beacon = beacon;	return 0;}static void b43_update_templates(struct b43_wldev *dev){	u32 status;	B43_WARN_ON(!dev->cached_beacon);	b43_write_beacon_template(dev, 0x68, 0x18, B43_CCK_RATE_1MB);	b43_write_beacon_template(dev, 0x468, 0x1A, B43_CCK_RATE_1MB);	b43_write_probe_resp_template(dev, 0x268, 0x4A, B43_CCK_RATE_11MB);	status = b43_read32(dev, B43_MMIO_STATUS2_BITFIELD);	status |= 0x03;	b43_write32(dev, B43_MMIO_STATUS2_BITFIELD, status);}static void b43_refresh_templates(struct b43_wldev *dev, struct sk_buff *beacon){	int err;	err = b43_refresh_cached_beacon(dev, beacon);	if (unlikely(err))		return;	b43_update_templates(dev);}static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len){	u32 tmp;	u16 i, len;	len = min((u16) ssid_len, (u16) 0x100);	for (i = 0; i < len; i += sizeof(u32)) {		tmp = (u32) (ssid[i + 0]);		if (i + 1 < len)			tmp |= (u32) (ssid[i + 1]) << 8;		if (i + 2 < len)			tmp |= (u32) (ssid[i + 2]) << 16;		if (i + 3 < len)			tmp |= (u32) (ssid[i + 3]) << 24;		b43_shm_write32(dev, B43_SHM_SHARED, 0x380 + i, tmp);	}	b43_shm_write16(dev, B43_SHM_SHARED, 0x48, len);}static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int){	b43_time_lock(dev);	if (dev->dev->id.revision >= 3) {		b43_write32(dev, 0x188, (beacon_int << 16));	} else {		b43_write16(dev, 0x606, (beacon_int >> 6));		b43_write16(dev, 0x610, beacon_int);	}	b43_time_unlock(dev);}static void handle_irq_beacon(struct b43_wldev *dev){	u32 status;	if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))		return;	dev->irq_savedstate &= ~B43_IRQ_BEACON;	status = b43_read32(dev, B43_MMIO_STATUS2_BITFIELD);	if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {		/* ACK beacon IRQ. */		b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);		dev->irq_savedstate |= B43_IRQ_BEACON;		if (dev->cached_beacon)			kfree_skb(dev->cached_beacon);		dev->cached_beacon = NULL;		return;	}	if (!(status & 0x1)) {		b43_write_beacon_template(dev, 0x68, 0x18, B43_CCK_RATE_1MB);		status |= 0x1;		b43_write32(dev, B43_MMIO_STATUS2_BITFIELD, status);	}	if (!(status & 0x2)) {		b43_write_beacon_template(dev, 0x468, 0x1A, B43_CCK_RATE_1MB);		status |= 0x2;		b43_write32(dev, B43_MMIO_STATUS2_BITFIELD, status);	}}static void handle_irq_ucode_debug(struct b43_wldev *dev){	//TODO}/* Interrupt handler bottom-half */static void b43_interrupt_tasklet(struct b43_wldev *dev){	u32 reason;	u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];	u32 merged_dma_reason = 0;	int i;	unsigned long flags;	spin_lock_irqsave(&dev->wl->irq_lock, flags);	B43_WARN_ON(b43_status(dev) != B43_STAT_STARTED);	reason = dev->irq_reason;	for (i = 0; i < ARRAY_SIZE(dma_reason); i++) {		dma_reason[i] = dev->dma_reason[i];		merged_dma_reason |= dma_reason[i];	}	if (unlikely(reason & B43_IRQ_MAC_TXERR))		b43err(dev->wl, "MAC transmission error\n");	if (unlikely(reason & B43_IRQ_PHY_TXERR))		b43err(dev->wl, "PHY transmission error\n");	if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK |					  B43_DMAIRQ_NONFATALMASK))) {		if (merged_dma_reason & B43_DMAIRQ_FATALMASK) {			b43err(dev->wl, "Fatal DMA error: "			       "0x%08X, 0x%08X, 0x%08X, "			       "0x%08X, 0x%08X, 0x%08X\n",			       dma_reason[0], dma_reason[1],			       dma_reason[2], dma_reason[3],			       dma_reason[4], dma_reason[5]);			b43_controller_restart(dev, "DMA error");			mmiowb();			spin_unlock_irqrestore(&dev->wl->irq_lock, flags);			return;		}		if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {			b43err(dev->wl, "DMA error: "			       "0x%08X, 0x%08X, 0x%08X, "			       "0x%08X, 0x%08X, 0x%08X\n",			       dma_reason[0], dma_reason[1],			       dma_reason[2], dma_reason[3],			       dma_reason[4], dma_reason[5]);		}	}	if (unlikely(reason & B43_IRQ_UCODE_DEBUG))		handle_irq_ucode_debug(dev);	if (reason & B43_IRQ_TBTT_INDI)		handle_irq_tbtt_indication(dev);	if (reason & B43_IRQ_ATIM_END)		handle_irq_atim_end(dev);	if (reason & B43_IRQ_BEACON)		handle_irq_beacon(dev);	if (reason & B43_IRQ_PMQ)		handle_irq_pmq(dev);	if (reason & B43_IRQ_TXFIFO_FLUSH_OK)		;/* TODO */	if (reason & B43_IRQ_NOISESAMPLE_OK)		handle_irq_noise(dev);	/* Check the DMA reason registers for received data. */	if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {		if (b43_using_pio(dev))			b43_pio_rx(dev->pio.queue0);		else			b43_dma_rx(dev->dma.rx_ring0);	}	B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE);	B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE);	if (dma_reason[3] & B43_DMAIRQ_RX_DONE) {		if (b43_using_pio(dev))			b43_pio_rx(dev->pio.queue3);		else			b43_dma_rx(dev->dma.rx_ring3);	}	B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE);	B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE);	if (reason & B43_IRQ_TX_OK)		handle_irq_transmit_status(dev);	b43_interrupt_enable(dev, dev->irq_savedstate);	mmiowb();	spin_unlock_irqrestore(&dev->wl->irq_lock, flags);}

⌨️ 快捷键说明

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