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

📄 main.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	u32 i;	u32 tmp;	struct b43legacy_plcp_hdr4 plcp;	plcp.data = 0;	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);	b43legacy_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;	b43legacy_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;		b43legacy_ram_write(dev, ram_offset + i - 2, tmp);	}	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_size_offset,			      size + sizeof(struct b43legacy_plcp_hdr6));}static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev,					    u16 ram_offset,					    u16 shm_size_offset, u8 rate){	int len;	const u8 *data;	B43legacy_WARN_ON(!dev->cached_beacon);	len = min((size_t)dev->cached_beacon->len,		  0x200 - sizeof(struct b43legacy_plcp_hdr6));	data = (const u8 *)(dev->cached_beacon->data);	b43legacy_write_template_common(dev, data,					len, ram_offset,					shm_size_offset, rate);}static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,					    u16 shm_offset, u16 size,					    u8 rate){	struct b43legacy_plcp_hdr4 plcp;	u32 tmp;	__le16 dur;	plcp.data = 0;	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);	dur = ieee80211_generic_frame_duration(dev->wl->hw,					       dev->wl->if_id,					       size,					       B43legacy_RATE_TO_100KBPS(rate));	/* Write PLCP in two parts and timing for packet transfer */	tmp = le32_to_cpu(plcp.data);	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset,			      tmp & 0xFFFF);	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset + 2,			      tmp >> 16);	b43legacy_shm_write16(dev, B43legacy_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 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,					 u16 *dest_size, u8 rate){	const u8 *src_data;	u8 *dest_data;	u16 src_size;	u16 elem_size;	u16 src_pos;	u16 dest_pos;	__le16 dur;	struct ieee80211_hdr *hdr;	B43legacy_WARN_ON(!dev->cached_beacon);	src_size = dev->cached_beacon->len;	src_data = (const u8 *)dev->cached_beacon->data;	if (unlikely(src_size < 0x24)) {		b43legacydbg(dev->wl, "b43legacy_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 = 0x24;	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,					       B43legacy_RATE_TO_100KBPS(rate));	hdr->duration_id = dur;	return dest_data;}static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,						u16 ram_offset,						u16 shm_size_offset, u8 rate){	u8 *probe_resp_data;	u16 size;	B43legacy_WARN_ON(!dev->cached_beacon);	size = dev->cached_beacon->len;	probe_resp_data = b43legacy_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	 */	b43legacy_write_probe_resp_plcp(dev, 0x31A, size,					B43legacy_CCK_RATE_1MB);	b43legacy_write_probe_resp_plcp(dev, 0x32C, size,					B43legacy_CCK_RATE_2MB);	b43legacy_write_probe_resp_plcp(dev, 0x33E, size,					B43legacy_CCK_RATE_5MB);	b43legacy_write_probe_resp_plcp(dev, 0x350, size,					B43legacy_CCK_RATE_11MB);	size = min((size_t)size,		   0x200 - sizeof(struct b43legacy_plcp_hdr6));	b43legacy_write_template_common(dev, probe_resp_data,					size, ram_offset,					shm_size_offset, rate);	kfree(probe_resp_data);}static int b43legacy_refresh_cached_beacon(struct b43legacy_wldev *dev,					   struct sk_buff *beacon){	if (dev->cached_beacon)		kfree_skb(dev->cached_beacon);	dev->cached_beacon = beacon;	return 0;}static void b43legacy_update_templates(struct b43legacy_wldev *dev){	u32 status;	B43legacy_WARN_ON(!dev->cached_beacon);	b43legacy_write_beacon_template(dev, 0x68, 0x18,					B43legacy_CCK_RATE_1MB);	b43legacy_write_beacon_template(dev, 0x468, 0x1A,					B43legacy_CCK_RATE_1MB);	b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,					    B43legacy_CCK_RATE_11MB);	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD);	status |= 0x03;	b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, status);}static void b43legacy_refresh_templates(struct b43legacy_wldev *dev,					struct sk_buff *beacon){	int err;	err = b43legacy_refresh_cached_beacon(dev, beacon);	if (unlikely(err))		return;	b43legacy_update_templates(dev);}static void b43legacy_set_ssid(struct b43legacy_wldev *dev,			       const u8 *ssid, u8 ssid_len){	u32 tmp;	u16 i;	u16 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;		b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,				      0x380 + i, tmp);	}	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,			      0x48, len);}static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,				     u16 beacon_int){	b43legacy_time_lock(dev);	if (dev->dev->id.revision >= 3)		b43legacy_write32(dev, 0x188, (beacon_int << 16));	else {		b43legacy_write16(dev, 0x606, (beacon_int >> 6));		b43legacy_write16(dev, 0x610, beacon_int);	}	b43legacy_time_unlock(dev);}static void handle_irq_beacon(struct b43legacy_wldev *dev){	u32 status;	if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))		return;	dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD);	if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {		/* ACK beacon IRQ. */		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,				  B43legacy_IRQ_BEACON);		dev->irq_savedstate |= B43legacy_IRQ_BEACON;		if (dev->cached_beacon)			kfree_skb(dev->cached_beacon);		dev->cached_beacon = NULL;		return;	}	if (!(status & 0x1)) {		b43legacy_write_beacon_template(dev, 0x68, 0x18,						B43legacy_CCK_RATE_1MB);		status |= 0x1;		b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,				  status);	}	if (!(status & 0x2)) {		b43legacy_write_beacon_template(dev, 0x468, 0x1A,						B43legacy_CCK_RATE_1MB);		status |= 0x2;		b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,				  status);	}}static void handle_irq_ucode_debug(struct b43legacy_wldev *dev){}/* Interrupt handler bottom-half */static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev){	u32 reason;	u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];	u32 merged_dma_reason = 0;	int i;	int activity = 0;	unsigned long flags;	spin_lock_irqsave(&dev->wl->irq_lock, flags);	B43legacy_WARN_ON(b43legacy_status(dev) <			  B43legacy_STAT_INITIALIZED);	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 & B43legacy_IRQ_MAC_TXERR))		b43legacyerr(dev->wl, "MAC transmission error\n");	if (unlikely(reason & B43legacy_IRQ_PHY_TXERR))		b43legacyerr(dev->wl, "PHY transmission error\n");	if (unlikely(merged_dma_reason & (B43legacy_DMAIRQ_FATALMASK |					  B43legacy_DMAIRQ_NONFATALMASK))) {		if (merged_dma_reason & B43legacy_DMAIRQ_FATALMASK) {			b43legacyerr(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]);			b43legacy_controller_restart(dev, "DMA error");			mmiowb();			spin_unlock_irqrestore(&dev->wl->irq_lock, flags);			return;		}		if (merged_dma_reason & B43legacy_DMAIRQ_NONFATALMASK)			b43legacyerr(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 & B43legacy_IRQ_UCODE_DEBUG))		handle_irq_ucode_debug(dev);	if (reason & B43legacy_IRQ_TBTT_INDI)		handle_irq_tbtt_indication(dev);	if (reason & B43legacy_IRQ_ATIM_END)		handle_irq_atim_end(dev);	if (reason & B43legacy_IRQ_BEACON)		handle_irq_beacon(dev);	if (reason & B43legacy_IRQ_PMQ)		handle_irq_pmq(dev);	if (reason & B43legacy_IRQ_TXFIFO_FLUSH_OK)		;/*TODO*/	if (reason & B43legacy_IRQ_NOISESAMPLE_OK)		handle_irq_noise(dev);	/* Check the DMA reason registers for received data. */	if (dma_reason[0] & B43legacy_DMAIRQ_RX_DONE) {		if (b43legacy_using_pio(dev))			b43legacy_pio_rx(dev->pio.queue0);		else			b43legacy_dma_rx(dev->dma.rx_ring0);		/* We intentionally don't set "activity" to 1, here. */	}	B43legacy_WARN_ON(dma_reason[1] & B43legacy_DMAIRQ_RX_DONE);	B43legacy_WARN_ON(dma_reason[2] & B43legacy_DMAIRQ_RX_DONE);	if (dma_reason[3] & B43legacy_DMAIRQ_RX_DONE) {		if (b43legacy_using_pio(dev))			b43legacy_pio_rx(dev->pio.queue3);		else			b43legacy_dma_rx(dev->dma.rx_ring3);		activity = 1;	}	B43legacy_WARN_ON(dma_reason[4] & B43legacy_DMAIRQ_RX_DONE);	B43legacy_WARN_ON(dma_reason[5] & B43legacy_DMAIRQ_RX_DONE);	if (reason & B43legacy_IRQ_TX_OK) {		handle_irq_transmit_status(dev);		activity = 1;		/* TODO: In AP mode, this also causes sending of powersave			 responses. */	}	if (!modparam_noleds)		b43legacy_leds_update(dev, activity);	b43legacy_interrupt_enable(dev, dev->irq_savedstate);	mmiowb();	spin_unlock_irqrestore(&dev->wl->irq_lock, flags);}static void pio_irq_workaround(struct b43legacy_wldev *dev,			       u16 base, int queueidx){	u16 rxctl;	rxctl = b43legacy_read16(dev, base + B43legacy_PIO_RXCTL);	if (rxctl & B43legacy_PIO_RXCTL_DATAAVAILABLE)		dev->dma_reason[queueidx] |= B43legacy_DMAIRQ_RX_DONE;	else		dev->dma_reason[queueidx] &= ~B43legacy_DMAIRQ_RX_DONE;}static void b43legacy_interrupt_ack(struct b43legacy_wldev *dev, u32 reason){	if (b43legacy_using_pio(dev) &&	    (dev->dev->id.revision < 3) &&	    (!(reason & B43legacy_IRQ_PIO_WORKAROUND))) {		/* Apply a PIO specific workaround to the dma_reasons */		pio_irq_workaround(dev, B43legacy_MMIO_PIO1_BASE, 0);		pio_irq_workaround(dev, B43legacy_MMIO_PIO2_BASE, 1);		pio_irq_workaround(dev, B43legacy_MMIO_PIO3_BASE, 2);		pio_irq_workaround(dev, B43legacy_MMIO_PIO4_BASE, 3);	}	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, reason);	b43legacy_write32(dev, B43legacy_MMIO_DMA0_REASON,			  dev->dma_reason[0]);	b43legacy_write32(dev, B43legacy_MMIO_DMA1_REASON,			  dev->dma_reason[1]);	b43legacy_write32(dev, B43legacy_MMIO_DMA2_REASON,			  dev->dma_reason[2]);	b43legacy_write32(dev, B43legacy_MMIO_DMA3_REASON,			  dev->dma_reason[3]);	b43legacy_write32(dev, B43legacy_MMIO_DMA4_REASON,			  dev->dma_reason[4]);	b43legacy_write32(dev, B43legacy_MMIO_DMA5_REASON,			  dev->dma_reason[5]);}/* Interrupt handler top-half */static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id){	irqreturn_t ret = IRQ_NONE;	struct b43legacy_wldev *dev = dev_id;	u32 reason;	if (!dev)		return IRQ_NONE;	spin_lock(&dev->wl->irq_lock);	if (b43legacy_status(dev) < B43legacy_STAT_STARTED)		goto out;	reason = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);	if (reason == 0xffffffff) /* shared IRQ */		goto out;	ret = IRQ_HANDLED;	reason &= b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);	if (!reason)		goto out;	dev->dma_reason[0] = b43legacy_read32(dev,					      B43legacy_MMIO_DMA0_REASON)					      & 0x0001DC00;	dev->dma_reason[1] = b43legacy_read32(dev,					      B43legacy_MMIO_DMA1_REASON)					      & 0x0000DC00;	dev->dma_reason[2] = b43legacy_read32(dev,					      B43legacy_MMIO_DMA2_REASON)					      & 0x0000DC00;	dev->dma_reason[3] = b43legacy_read32(dev,					      B43legacy_MMIO_DMA3_REASON)					      & 0x0001DC00;	dev->dma_reason[4] = b43legacy_read32(dev,					      B43legacy_MMIO_DMA4_REASON)					      & 0x0000DC00;	dev->dma_reason[5] = b43legacy_read32(dev,					      B43legacy_MMIO_DMA5_REASON)					      & 0x0000DC00;	b43legacy_interrupt_ack(dev, reason);	/* disable all IRQs. They are enabled again in the bottom half. */	dev->irq_savedstate = b43legacy_interrupt_disable(dev,							  B43legacy_IRQ_ALL);	/* save the reason code and call our bottom half. */	dev->irq_reason = reason;	tasklet_schedule(&dev->isr_tasklet);out:	mmiowb();

⌨️ 快捷键说明

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