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

📄 wl3501_cs.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		.sig_id		 = WL3501_SIG_ASSOC_REQ,		.timeout	 = 1000,		.listen_interval = 5,		.cap_info	 = this->cap_info,	};	dprintk(3, "entry");	memcpy(sig.mac_addr, this->bssid, ETH_ALEN);	return wl3501_esbq_exec(this, &sig, sizeof(sig));}static void wl3501_mgmt_join_confirm(struct net_device *dev, u16 addr){	struct wl3501_card *this = dev->priv;	struct wl3501_join_confirm sig;	dprintk(3, "entry");	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));	if (sig.status == WL3501_STATUS_SUCCESS) {		if (this->net_type == IW_MODE_INFRA) {			if (this->join_sta_bss < this->bss_cnt) {				const int i = this->join_sta_bss;				memcpy(this->bssid,				       this->bss_set[i].bssid, ETH_ALEN);				this->chan = this->bss_set[i].ds_pset.chan;				iw_copy_mgmt_info_element(&this->keep_essid.el,						     &this->bss_set[i].ssid.el);				wl3501_mgmt_auth(this);			}		} else {			const int i = this->join_sta_bss;			memcpy(&this->bssid, &this->bss_set[i].bssid, ETH_ALEN);			this->chan = this->bss_set[i].ds_pset.chan;			iw_copy_mgmt_info_element(&this->keep_essid.el,						  &this->bss_set[i].ssid.el);			wl3501_online(dev);		}	} else {		int i;		this->join_sta_bss++;		for (i = this->join_sta_bss; i < this->bss_cnt; i++)			if (!wl3501_mgmt_join(this, i))				break;		this->join_sta_bss = i;		if (this->join_sta_bss == this->bss_cnt) {			if (this->net_type == IW_MODE_INFRA)				wl3501_mgmt_scan(this, 100);			else {				this->adhoc_times++;				if (this->adhoc_times > WL3501_MAX_ADHOC_TRIES)					wl3501_mgmt_start(this);				else					wl3501_mgmt_scan(this, 100);			}		}	}}static inline void wl3501_alarm_interrupt(struct net_device *dev,					  struct wl3501_card *this){	if (this->net_type == IW_MODE_INFRA) {		printk(KERN_INFO "Wireless LAN offline\n");		netif_stop_queue(dev);		wl3501_mgmt_resync(this);	}}static inline void wl3501_md_confirm_interrupt(struct net_device *dev,					       struct wl3501_card *this,					       u16 addr){	struct wl3501_md_confirm sig;	dprintk(3, "entry");	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));	wl3501_free_tx_buffer(this, sig.data);	if (netif_queue_stopped(dev))		netif_wake_queue(dev);}static inline void wl3501_md_ind_interrupt(struct net_device *dev,					   struct wl3501_card *this, u16 addr){	struct wl3501_md_ind sig;	struct sk_buff *skb;	u8 rssi, addr4[ETH_ALEN];	u16 pkt_len;	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));	this->start_seg = sig.data;	wl3501_get_from_wla(this,			    sig.data + offsetof(struct wl3501_rx_hdr, rssi),			    &rssi, sizeof(rssi));	this->rssi = rssi <= 63 ? (rssi * 100) / 64 : 255;	wl3501_get_from_wla(this,			    sig.data +				offsetof(struct wl3501_rx_hdr, addr4),			    &addr4, sizeof(addr4));	if (!(addr4[0] == 0xAA && addr4[1] == 0xAA &&	      addr4[2] == 0x03 && addr4[4] == 0x00)) {		printk(KERN_INFO "Insupported packet type!\n");		return;	}	pkt_len = sig.size + 12 - 24 - 4 - 6;	skb = dev_alloc_skb(pkt_len + 5);	if (!skb) {		printk(KERN_WARNING "%s: Can't alloc a sk_buff of size %d.\n",		       dev->name, pkt_len);		this->stats.rx_dropped++;	} else {		skb->dev = dev;		skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */		eth_copy_and_sum(skb, (unsigned char *)&sig.daddr, 12, 0);		wl3501_receive(this, skb->data, pkt_len);		skb_put(skb, pkt_len);		skb->protocol	= eth_type_trans(skb, dev);		dev->last_rx	= jiffies;		this->stats.rx_packets++;		this->stats.rx_bytes += skb->len;		netif_rx(skb);	}}static inline void wl3501_get_confirm_interrupt(struct wl3501_card *this,						u16 addr, void *sig, int size){	dprintk(3, "entry");	wl3501_get_from_wla(this, addr, &this->sig_get_confirm,			    sizeof(this->sig_get_confirm));	wake_up(&this->wait);}static inline void wl3501_start_confirm_interrupt(struct net_device *dev,						  struct wl3501_card *this,						  u16 addr){	struct wl3501_start_confirm sig;	dprintk(3, "entry");	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));	if (sig.status == WL3501_STATUS_SUCCESS)		netif_wake_queue(dev);}static inline void wl3501_assoc_confirm_interrupt(struct net_device *dev,						  u16 addr){	struct wl3501_card *this = dev->priv;	struct wl3501_assoc_confirm sig;	dprintk(3, "entry");	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));	if (sig.status == WL3501_STATUS_SUCCESS)		wl3501_online(dev);}static inline void wl3501_auth_confirm_interrupt(struct wl3501_card *this,						 u16 addr){	struct wl3501_auth_confirm sig;	dprintk(3, "entry");	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));	if (sig.status == WL3501_STATUS_SUCCESS)		wl3501_mgmt_association(this);	else		wl3501_mgmt_resync(this);}static inline void wl3501_rx_interrupt(struct net_device *dev){	int morepkts;	u16 addr;	u8 sig_id;	struct wl3501_card *this = dev->priv;	dprintk(3, "entry");loop:	morepkts = 0;	if (!wl3501_esbq_confirm(this))		goto free;	wl3501_get_from_wla(this, this->esbq_confirm, &addr, sizeof(addr));	wl3501_get_from_wla(this, addr + 2, &sig_id, sizeof(sig_id));	switch (sig_id) {	case WL3501_SIG_DEAUTH_IND:	case WL3501_SIG_DISASSOC_IND:	case WL3501_SIG_ALARM:		wl3501_alarm_interrupt(dev, this);		break;	case WL3501_SIG_MD_CONFIRM:		wl3501_md_confirm_interrupt(dev, this, addr);		break;	case WL3501_SIG_MD_IND:		wl3501_md_ind_interrupt(dev, this, addr);		break;	case WL3501_SIG_GET_CONFIRM:		wl3501_get_confirm_interrupt(this, addr,					     &this->sig_get_confirm,					     sizeof(this->sig_get_confirm));		break;	case WL3501_SIG_PWR_MGMT_CONFIRM:		wl3501_get_confirm_interrupt(this, addr,					     &this->sig_pwr_mgmt_confirm,					    sizeof(this->sig_pwr_mgmt_confirm));		break;	case WL3501_SIG_START_CONFIRM:		wl3501_start_confirm_interrupt(dev, this, addr);		break;	case WL3501_SIG_SCAN_CONFIRM:		wl3501_mgmt_scan_confirm(this, addr);		break;	case WL3501_SIG_JOIN_CONFIRM:		wl3501_mgmt_join_confirm(dev, addr);		break;	case WL3501_SIG_ASSOC_CONFIRM:		wl3501_assoc_confirm_interrupt(dev, addr);		break;	case WL3501_SIG_AUTH_CONFIRM:		wl3501_auth_confirm_interrupt(this, addr);		break;	case WL3501_SIG_RESYNC_CONFIRM:		wl3501_mgmt_resync(this); /* FIXME: should be resync_confirm */		break;	}	wl3501_esbq_confirm_done(this);	morepkts = 1;	/* free request if necessary */free:	wl3501_esbq_req_free(this);	if (morepkts)		goto loop;}static inline void wl3501_ack_interrupt(struct wl3501_card *this){	wl3501_outb(WL3501_GCR_ECINT, this->base_addr + WL3501_NIC_GCR);}/** * wl3501_interrupt - Hardware interrupt from card. * @irq - Interrupt number * @dev_id - net_device * @regs - registers * * We must acknowledge the interrupt as soon as possible, and block the * interrupt from the same card immediately to prevent re-entry. * * Before accessing the Control_Status_Block, we must lock SUTRO first. * On the other hand, to prevent SUTRO from malfunctioning, we must * unlock the SUTRO as soon as possible. */static irqreturn_t wl3501_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = (struct net_device *)dev_id;	struct wl3501_card *this;	int handled = 1;	if (!dev)		goto unknown;	this = dev->priv;	spin_lock(&this->lock);	wl3501_ack_interrupt(this);	wl3501_block_interrupt(this);	wl3501_rx_interrupt(dev);	wl3501_unblock_interrupt(this);	spin_unlock(&this->lock);out:	return IRQ_RETVAL(handled);unknown:	handled = 0;	printk(KERN_ERR "%s: irq %d for unknown device.\n", __FUNCTION__, irq);	goto out;}static int wl3501_reset_board(struct wl3501_card *this){	u8 tmp = 0;	int i, rc = 0;	/* Coreset */	wl3501_outb_p(WL3501_GCR_CORESET, this->base_addr + WL3501_NIC_GCR);	wl3501_outb_p(0, this->base_addr + WL3501_NIC_GCR);	wl3501_outb_p(WL3501_GCR_CORESET, this->base_addr + WL3501_NIC_GCR);	/* Reset SRAM 0x480 to zero */	wl3501_set_to_wla(this, 0x480, &tmp, sizeof(tmp));	/* Start up */	wl3501_outb_p(0, this->base_addr + WL3501_NIC_GCR);	WL3501_NOPLOOP(1024 * 50);	wl3501_unblock_interrupt(this);	/* acme: was commented */	/* Polling Self_Test_Status */	for (i = 0; i < 10000; i++) {		wl3501_get_from_wla(this, 0x480, &tmp, sizeof(tmp));		if (tmp == 'W') {			/* firmware complete all test successfully */			tmp = 'A';			wl3501_set_to_wla(this, 0x480, &tmp, sizeof(tmp));			goto out;		}		WL3501_NOPLOOP(10);	}	printk(KERN_WARNING "%s: failed to reset the board!\n", __FUNCTION__);	rc = -ENODEV;out:	return rc;}static int wl3501_init_firmware(struct wl3501_card *this){	u16 ptr, next;	int rc = wl3501_reset_board(this);	if (rc)		goto fail;	this->card_name[0] = '\0';	wl3501_get_from_wla(this, 0x1a00,			    this->card_name, sizeof(this->card_name));	this->card_name[sizeof(this->card_name) - 1] = '\0';	this->firmware_date[0] = '\0';	wl3501_get_from_wla(this, 0x1a40,			    this->firmware_date, sizeof(this->firmware_date));	this->firmware_date[sizeof(this->firmware_date) - 1] = '\0';	/* Switch to SRAM Page 0 */	wl3501_switch_page(this, WL3501_BSS_SPAGE0);	/* Read parameter from card */	wl3501_get_from_wla(this, 0x482, &this->esbq_req_start, 2);	wl3501_get_from_wla(this, 0x486, &this->esbq_req_end, 2);	wl3501_get_from_wla(this, 0x488, &this->esbq_confirm_start, 2);	wl3501_get_from_wla(this, 0x48c, &this->esbq_confirm_end, 2);	wl3501_get_from_wla(this, 0x48e, &this->tx_buffer_head, 2);	wl3501_get_from_wla(this, 0x492, &this->tx_buffer_size, 2);	this->esbq_req_tail	= this->esbq_req_head = this->esbq_req_start;	this->esbq_req_end     += this->esbq_req_start;	this->esbq_confirm	= this->esbq_confirm_start;	this->esbq_confirm_end += this->esbq_confirm_start;	/* Initial Tx Buffer */	this->tx_buffer_cnt = 1;	ptr = this->tx_buffer_head;	next = ptr + WL3501_BLKSZ;	while ((next - this->tx_buffer_head) < this->tx_buffer_size) {		this->tx_buffer_cnt++;		wl3501_set_to_wla(this, ptr, &next, sizeof(next));		ptr = next;		next = ptr + WL3501_BLKSZ;	}	rc = 0;	next = 0;	wl3501_set_to_wla(this, ptr, &next, sizeof(next));	this->tx_buffer_tail = ptr;out:	return rc;fail:	printk(KERN_WARNING "%s: failed!\n", __FUNCTION__);	goto out;}static int wl3501_close(struct net_device *dev){	struct wl3501_card *this = dev->priv;	int rc = -ENODEV;	unsigned long flags;	dev_link_t *link;	spin_lock_irqsave(&this->lock, flags);	/* Check if the device is in wl3501_dev_list */	for (link = wl3501_dev_list; link; link = link->next)		if (link->priv == dev)			break;	if (!link)		goto out;	link->open--;	/* Stop wl3501_hard_start_xmit() from now on */	netif_stop_queue(dev);	wl3501_ack_interrupt(this);	/* Mask interrupts from the SUTRO */	wl3501_block_interrupt(this);	rc = 0;	printk(KERN_INFO "%s: WL3501 closed\n", dev->name);out:	spin_unlock_irqrestore(&this->lock, flags);	return rc;}/** * wl3501_reset - Reset the SUTRO. * @dev - network device * * It is almost the same as wl3501_open(). In fact, we may just wl3501_close() * and wl3501_open() again, but I wouldn't like to free_irq() when the driver * is running. It seems to be dangerous. */static int wl3501_reset(struct net_device *dev){	struct wl3501_card *this = dev->priv;	int rc = -ENODEV;	wl3501_block_interrupt(this);	if (wl3501_init_firmware(this)) {		printk(KERN_WARNING "%s: Can't initialize Firmware!\n",		       dev->name);		/* Free IRQ, and mark IRQ as unused */		free_irq(dev->irq, dev);		goto out;	}	/*	 * Queue has to be started only when the Card is Started	 */	netif_stop_queue(dev);	this->adhoc_times = 0;	wl3501_ack_interrupt(this);	wl3501_unblock_interrupt(this);	wl3501_mgmt_scan(this, 100);	dprintk(1, "%s: device reset", dev->name);	rc = 0;out:	return rc;}static void wl3501_tx_timeout(struct net_device *dev){	struct wl3501_card *this = dev->priv;	struct net_device_stats *stats = &this->stats;	unsigned long flags;	int rc;	stats->tx_errors++;	spin_lock_irqsave(&this->lock, flags);	rc = wl3501_reset(dev);	spin_unlock_irqrestore(&this->lock, flags);	if (rc)		printk(KERN_ERR "%s: Error %d resetting card on Tx timeout!\n",		       dev->name, rc);	else {		dev->trans_start = jiffies;		netif_wake_queue(dev);	}}

⌨️ 快捷键说明

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