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

📄 atmel.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		return 1;	}		frame_ctl = IEEE802_11_FTYPE_DATA;	header.duration_id = 0;	header.seq_ctl = 0;	if (priv->wep_is_on)		frame_ctl |= IEEE802_11_FCTL_WEP;	if (priv->operating_mode == IW_MODE_ADHOC) {		memcpy(&header.addr1, skb->data, 6);		memcpy(&header.addr2, dev->dev_addr, 6);		memcpy(&header.addr3, priv->BSSID, 6);	} else {		frame_ctl |= IEEE802_11_FCTL_TODS;		memcpy(&header.addr1, priv->CurrentBSSID, 6);		memcpy(&header.addr2, dev->dev_addr, 6);		memcpy(&header.addr3, skb->data, 6);	}		if (priv->use_wpa)		memcpy(&header.addr4, SNAP_RFC1024, 6);	header.frame_ctl = cpu_to_le16(frame_ctl);	/* Copy the wireless header into the card */	atmel_copy_to_card(dev, buff, (unsigned char *)&header, DATA_FRAME_WS_HEADER_SIZE);	/* Copy the packet sans its 802.3 header addresses which have been replaced */	atmel_copy_to_card(dev, buff + DATA_FRAME_WS_HEADER_SIZE, skb->data + 12, len - 12);	priv->tx_buff_tail += len - 12 + DATA_FRAME_WS_HEADER_SIZE;		/* low bit of first byte of destination tells us if broadcast */	tx_update_descriptor(priv, *(skb->data) & 0x01, len + 18, buff, TX_PACKET_TYPE_DATA);	dev->trans_start = jiffies;	priv->stats.tx_bytes += len;		spin_unlock_irqrestore(&priv->irqlock, flags);	spin_unlock_bh(&priv->timerlock);	dev_kfree_skb(skb);		return 0;	}static void atmel_transmit_management_frame(struct atmel_private *priv, 					    struct ieee802_11_hdr *header,					    u8 *body, int body_len){	u16 buff;	int len =  MGMT_FRAME_BODY_OFFSET + body_len;		if (!(buff = find_tx_buff(priv, len))) 		return;	atmel_copy_to_card(priv->dev, buff, (u8 *)header, MGMT_FRAME_BODY_OFFSET);	atmel_copy_to_card(priv->dev, buff + MGMT_FRAME_BODY_OFFSET, body, body_len);	priv->tx_buff_tail += len;	tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);}	static void fast_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header, 			 u16 msdu_size, u16 rx_packet_loc, u32 crc){	/* fast path: unfragmented packet copy directly into skbuf */	u8 mac4[6]; 	struct sk_buff 	*skb;	unsigned char *skbp;		/* get the final, mac 4 header field, this tells us encapsulation */	atmel_copy_to_host(priv->dev, mac4, rx_packet_loc + 24, 6);	msdu_size -= 6;		if (priv->do_rx_crc) {		crc = crc32_le(crc, mac4, 6);		msdu_size -= 4;	}		if (!(skb = dev_alloc_skb(msdu_size + 14))) {		priv->stats.rx_dropped++;		return;	}	skb_reserve(skb, 2);	skbp = skb_put(skb, msdu_size + 12);	atmel_copy_to_host(priv->dev, skbp + 12, rx_packet_loc + 30, msdu_size);		if (priv->do_rx_crc) {		u32 netcrc;		crc = crc32_le(crc, skbp + 12, msdu_size);		atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + 30 + msdu_size, 4);		if ((crc ^ 0xffffffff) != netcrc) {			priv->stats.rx_crc_errors++;			dev_kfree_skb(skb);			return;		}	}		memcpy(skbp, header->addr1, 6); /* destination address */	if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS) 		memcpy(&skbp[6], header->addr3, 6);	else		memcpy(&skbp[6], header->addr2, 6); /* source address */		priv->dev->last_rx=jiffies;	skb->dev = priv->dev;	skb->protocol = eth_type_trans(skb, priv->dev);	skb->ip_summed = CHECKSUM_NONE;		netif_rx(skb);	priv->stats.rx_bytes += 12 + msdu_size;	priv->stats.rx_packets++;}/* Test to see if the packet in card memory at packet_loc has a valid CRC   It doesn't matter that this is slow: it is only used to proble the first few packets. */static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size){	int i = msdu_size - 4;	u32 netcrc, crc = 0xffffffff;	if (msdu_size < 4)		return 0;	atmel_copy_to_host(priv->dev, (void *)&netcrc, packet_loc + i, 4);		atmel_writeAR(priv->dev, packet_loc);	while (i--) {		u8 octet = atmel_read8(priv->dev, DR);		crc = crc32_le(crc, &octet, 1);	}	return (crc ^ 0xffffffff) == netcrc;}static void frag_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header, 			 u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags){	u8 mac4[6]; 	u8 source[6];	struct sk_buff *skb;	if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS) 		memcpy(source, header->addr3, 6);	else		memcpy(source, header->addr2, 6); 		rx_packet_loc += 24; /* skip header */		if (priv->do_rx_crc)		msdu_size -= 4;	if (frag_no == 0) { /* first fragment */		atmel_copy_to_host(priv->dev, mac4, rx_packet_loc, 6);		msdu_size -= 6;		rx_packet_loc += 6;		if (priv->do_rx_crc) 			crc = crc32_le(crc, mac4, 6);	       		priv->frag_seq = seq_no;		priv->frag_no = 1;		priv->frag_len = msdu_size;		memcpy(priv->frag_source, source, 6); 		memcpy(&priv->rx_buf[6], source, 6);		memcpy(priv->rx_buf, header->addr1, 6);						atmel_copy_to_host(priv->dev, &priv->rx_buf[12], rx_packet_loc, msdu_size);		if (priv->do_rx_crc) {			u32 netcrc;			crc = crc32_le(crc, &priv->rx_buf[12], msdu_size);			atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);			if ((crc ^ 0xffffffff) != netcrc) {				priv->stats.rx_crc_errors++;				memset(priv->frag_source, 0xff, 6);			}		}			} else if (priv->frag_no == frag_no &&		   priv->frag_seq == seq_no &&		   memcmp(priv->frag_source, source, 6) == 0) {				atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len], 				   rx_packet_loc, msdu_size);		if (priv->do_rx_crc) {			u32 netcrc;			crc = crc32_le(crc, 				       &priv->rx_buf[12 + priv->frag_len], 				       msdu_size);			atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);			if ((crc ^ 0xffffffff) != netcrc) {				priv->stats.rx_crc_errors++;				memset(priv->frag_source, 0xff, 6);				more_frags = 1; /* don't send broken assembly */			}		}				priv->frag_len += msdu_size;		priv->frag_no++;		if (!more_frags) { /* last one */			memset(priv->frag_source, 0xff, 6);			if (!(skb = dev_alloc_skb(priv->frag_len + 14))) {				priv->stats.rx_dropped++;			} else {				skb_reserve(skb, 2);				memcpy(skb_put(skb, priv->frag_len + 12), 				       priv->rx_buf,				       priv->frag_len + 12);				priv->dev->last_rx = jiffies;				skb->dev = priv->dev;				skb->protocol = eth_type_trans(skb, priv->dev);				skb->ip_summed = CHECKSUM_NONE;					netif_rx(skb);				priv->stats.rx_bytes += priv->frag_len + 12;				priv->stats.rx_packets++;			}		}			} else		priv->wstats.discard.fragment++;}		static void rx_done_irq(struct atmel_private *priv){	int i;	struct ieee802_11_hdr header;		for (i = 0; 	     atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&		     i < priv->host_info.rx_desc_count;	     i++) {						u16 msdu_size, rx_packet_loc, frame_ctl, seq_control;		u8 status = atmel_rmem8(priv, atmel_rx(priv, RX_DESC_STATUS_OFFSET, priv->rx_desc_head));		u32 crc = 0xffffffff;				if (status != RX_STATUS_SUCCESS) {			if (status == 0xc1) /* determined by experiment */				priv->wstats.discard.nwid++;			else				priv->stats.rx_errors++; 			goto next;		}		msdu_size = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_SIZE_OFFSET, priv->rx_desc_head));		rx_packet_loc = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_POS_OFFSET, priv->rx_desc_head));				if (msdu_size < 30) {			priv->stats.rx_errors++; 			goto next;		}				/* Get header as far as end of seq_ctl */		atmel_copy_to_host(priv->dev, (char *)&header, rx_packet_loc, 24);		frame_ctl = le16_to_cpu(header.frame_ctl);		seq_control = le16_to_cpu(header.seq_ctl);		/* probe for CRC use here if needed  once five packets have arrived with		   the same crc status, we assume we know what's happening and stop probing */		if (priv->probe_crc) {			if (!priv->wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP)) {				priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);			} else {				priv->do_rx_crc = probe_crc(priv, rx_packet_loc + 24, msdu_size - 24);			}			if (priv->do_rx_crc) {				if (priv->crc_ok_cnt++ > 5)					priv->probe_crc = 0;			} else {				if (priv->crc_ko_cnt++ > 5)					priv->probe_crc = 0;			}		}		    		/* don't CRC header when WEP in use */		if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP))) {			crc = crc32_le(0xffffffff, (unsigned char *)&header, 24);		}		msdu_size -= 24; /* header */		if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_DATA) { 						int more_fragments = frame_ctl & IEEE802_11_FCTL_MOREFRAGS;			u8 packet_fragment_no = seq_control & IEEE802_11_SCTL_FRAG;			u16 packet_sequence_no = (seq_control & IEEE802_11_SCTL_SEQ) >> 4;						if (!more_fragments && packet_fragment_no == 0 ) {				fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc);			} else {				frag_rx_path(priv, &header, msdu_size, rx_packet_loc, crc,					     packet_sequence_no, packet_fragment_no, more_fragments);			}		}				if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_MGMT) {			/* copy rest of packet into buffer */			atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size);						/* we use the same buffer for frag reassembly and control packets */			memset(priv->frag_source, 0xff, 6);						if (priv->do_rx_crc) {				/* last 4 octets is crc */				msdu_size -= 4;				crc = crc32_le(crc, (unsigned char *)&priv->rx_buf, msdu_size);				if ((crc ^ 0xffffffff) != (*((u32 *)&priv->rx_buf[msdu_size]))) {					priv->stats.rx_crc_errors++;					goto next;				}			}			atmel_management_frame(priv, &header, msdu_size,					       atmel_rmem8(priv, atmel_rx(priv, RX_DESC_RSSI_OFFSET, priv->rx_desc_head)));		} 	next:		/* release descriptor */		atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED);  				if (priv->rx_desc_head < (priv->host_info.rx_desc_count - 1))			priv->rx_desc_head++;							else			priv->rx_desc_head = 0;	}}	static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = (struct net_device *) dev_id;	struct atmel_private *priv = netdev_priv(dev);	u8 isr;	int i = -1;	static u8 irq_order[] = { 		ISR_OUT_OF_RANGE,		ISR_RxCOMPLETE,		ISR_TxCOMPLETE,		ISR_RxFRAMELOST,		ISR_FATAL_ERROR,		ISR_COMMAND_COMPLETE,		ISR_IBSS_MERGE,		ISR_GENERIC_IRQ	};			if (priv->card && priv->present_callback && 	    !(*priv->present_callback)(priv->card))		return IRQ_HANDLED;	/* In this state upper-level code assumes it can mess with	   the card unhampered by interrupts which may change register state.	   Note that even though the card shouldn't generate interrupts	   the inturrupt line may be shared. This allows card setup 	   to go on without disabling interrupts for a long time. */	if (priv->station_state == STATION_STATE_DOWN)		return IRQ_NONE;     		atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */	while (1) {		if (!atmel_lock_mac(priv)) {			/* failed to contact card */			printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);			return IRQ_HANDLED;		}				isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));		atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);				if (!isr) {			atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */			return i == -1 ? IRQ_NONE : IRQ_HANDLED;		}				atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */				for (i = 0; i < sizeof(irq_order)/sizeof(u8); i++)			if (isr & irq_order[i])				break;				if (!atmel_lock_mac(priv)) {			/* failed to contact card */			printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);			return IRQ_HANDLED;		}				isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));		isr ^= irq_order[i];		atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);		atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);				switch (irq_order[i]) {					case ISR_OUT_OF_RANGE: 			if (priv->operating_mode == IW_MODE_INFRA && 			    priv->station_state == STATION_STATE_READY) {				priv->station_is_associated = 0;				atmel_scan(priv, 1);			}			break;		case ISR_RxFRAMELOST:			priv->wstats.discard.misc++;			/* fall through */		case ISR_RxCOMPLETE:			rx_done_irq(priv); 			break;					case ISR_TxCOMPLETE:			tx_done_irq(priv); 			break;					case ISR_FATAL_ERROR:			printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name);			atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);			break;					case ISR_COMMAND_COMPLETE: 			atmel_command_irq(priv);			break;		case ISR_IBSS_MERGE:			atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS, 				      priv->CurrentBSSID, 6);			/* The WPA stuff cares about the current AP address */			if (priv->use_wpa)

⌨️ 快捷键说明

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