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

📄 atmel.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		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.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.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 void reset_irq_status(struct atmel_private *priv, u8 mask){	u8 isr;		atmel_lock_mac(priv);	isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));	isr ^= mask;	atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);	atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);}static void service_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = (struct net_device *) dev_id;	struct atmel_private *priv = (struct atmel_private *) dev->priv;	u8 isr;		if (priv->card && priv->present_callback && 	    !(*priv->present_callback)(priv->card))		return;     		atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */		while (1) {		if (!atmel_lock_mac(priv)) {			printk(KERN_ALERT "%s: MAC gone away in ISR.\n", dev->name);			/* bad things - don't re-enable interrupts */			return;		}					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_ACKINT); /* acknowledge interrupt */		else			break; /* no pending irqs */		if (isr & ISR_OUT_OF_RANGE) {			reset_irq_status(priv, 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);			}		} else if (isr & ISR_RxCOMPLETE) {			reset_irq_status(priv, ISR_RxCOMPLETE);			rx_done_irq(priv); 		} else if (isr & ISR_TxCOMPLETE) {			reset_irq_status(priv, ISR_TxCOMPLETE);			tx_done_irq(priv); 		} else if (isr & ISR_RxFRAMELOST) {			reset_irq_status(priv, ISR_RxFRAMELOST);			priv->wstats.discard.misc++;			rx_done_irq(priv);		} else if (isr & ISR_FATAL_ERROR) {			reset_irq_status(priv, ISR_FATAL_ERROR);			printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name);			atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);		} else if (isr & ISR_COMMAND_COMPLETE) {			reset_irq_status(priv, ISR_COMMAND_COMPLETE);			atmel_command_irq(priv);			} else if (isr & ISR_IBSS_MERGE) {			reset_irq_status(priv, ISR_IBSS_MERGE);			atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS, 				      priv->CurrentBSSID, 6);		} else if (isr & ISR_GENERIC_IRQ) {			reset_irq_status(priv, ISR_GENERIC_IRQ);			printk(KERN_INFO "%s: Generic_irq recieved.\n", dev->name);		}	}		atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */	return;}static struct net_device_stats *atmel_get_stats (struct net_device *dev){	struct atmel_private *priv = (struct atmel_private *)dev->priv;	return &priv->stats;}static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev){	struct atmel_private *priv = (struct atmel_private *)dev->priv;	/* update the link quality here in case we are seeing no beacons 	   at all to drive the process */	atmel_smooth_qual(priv);		priv->wstats.status = priv->station_state;	if (priv->operating_mode == IW_MODE_INFRA) {		if (priv->station_state != STATION_STATE_READY) {			priv->wstats.qual.qual = 0;			priv->wstats.qual.level	= 0;		}		priv->wstats.qual.noise = 0;		priv->wstats.qual.updated = 7;	} else {		// Quality levels cannot be determined in ad-hoc mode,		// because we can 'hear' more than one remote station.		priv->wstats.qual.qual = 0;		priv->wstats.qual.level	= 0;		priv->wstats.qual.noise	= 0;		priv->wstats.qual.updated = 0;		priv->wstats.miss.beacon = 0;	}		return (&priv->wstats);}static int atmel_change_mtu(struct net_device *dev, int new_mtu){        if ((new_mtu < 68) || (new_mtu > 2312))                return -EINVAL;        dev->mtu = new_mtu;        return 0;}static int atmel_set_mac_address(struct net_device *dev, void *p){	struct sockaddr *addr = p;                memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);	reset_atmel_card(dev);	return 0;}static int atmel_open (struct net_device *dev){	struct atmel_private *priv = (struct atmel_private *) dev->priv;	priv->station_state = STATION_STATE_INITIALIZING;	if (!reset_atmel_card(dev)) {		priv->station_state = STATION_STATE_DOWN;		return -EAGAIN;	}	return 0;}static int atmel_close (struct net_device *dev){	struct atmel_private *priv = (struct atmel_private *) dev->priv;			if (netif_running(dev))		netif_stop_queue(dev);		priv->station_state = STATION_STATE_DOWN;	if (priv->bus_type == BUS_TYPE_PCCARD) 		atmel_write16(dev, GCR, 0x0060);	atmel_write16(dev, GCR, 0x0040);	return 0;}static int atmel_proc_output (char *buf, struct atmel_private *priv){	char *p = buf;	char *s, *r, *c;		p += sprintf(p, "Driver version:\t\t%d.%d\n", DRIVER_MAJOR, DRIVER_MINOR);		if (priv->station_state != STATION_STATE_DOWN) {		p += sprintf(p, "Firmware version:\t%d.%d build %d ", 			     priv->host_info.major_version,			     priv->host_info.minor_version,			     priv->host_info.build_version);				if (priv->card_type != CARD_TYPE_EEPROM) 			p += sprintf(p, "[built-in]\n");		else if (priv->firmware) 			p += sprintf(p, "[%s loaded by host]\n", priv->firmware_id);		else			p += sprintf(p, "[%s loaded by hotplug]\n", priv->firmware_id);				switch(priv->card_type) {		case CARD_TYPE_PARALLEL_FLASH: c = "Parallel flash"; break;		case CARD_TYPE_SPI_FLASH: c = "SPI flash\n"; break;		case CARD_TYPE_EEPROM: c = "EEPROM"; break;		default: c = "<unknown>";		}		switch (priv->reg_domain) {		case REG_DOMAIN_FCC: r = "USA"; break;

⌨️ 快捷键说明

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