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

📄 wavelan.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	printk(" MHz\n");#endif				/* DEBUG_BASIC_SHOW */#ifdef DEBUG_VERSION_SHOW	/* Print version information */	printk(KERN_NOTICE "%s", version);#endif}				/* wv_init_info *//********************* IOCTL, STATS & RECONFIG *********************//* * We found here routines that are called by Linux on different * occasions after the configuration and not for transmitting data * These may be called when the user use ifconfig, /proc/net/dev * or wireless extensions *//*------------------------------------------------------------------*//* * Get the current Ethernet statistics. This may be called with the * card open or closed. * Used when the user read /proc/net/dev */static en_stats *wavelan_get_stats(struct net_device * dev){#ifdef DEBUG_IOCTL_TRACE	printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name);#endif	return (&((net_local *) dev->priv)->stats);}/*------------------------------------------------------------------*//* * Set or clear the multicast filter for this adaptor. * num_addrs == -1	Promiscuous mode, receive all packets * num_addrs == 0	Normal mode, clear multicast list * num_addrs > 0	Multicast mode, receive normal and MC packets, *			and do best-effort filtering. */static void wavelan_set_multicast_list(struct net_device * dev){	net_local *lp = (net_local *) dev->priv;#ifdef DEBUG_IOCTL_TRACE	printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n",	       dev->name);#endif#ifdef DEBUG_IOCTL_INFO	printk(KERN_DEBUG	       "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n",	       dev->name, dev->flags, dev->mc_count);#endif	/* Are we asking for promiscuous mode,	 * or all multicast addresses (we don't have that!)	 * or too many multicast addresses for the hardware filter? */	if ((dev->flags & IFF_PROMISC) ||	    (dev->flags & IFF_ALLMULTI) ||	    (dev->mc_count > I82586_MAX_MULTICAST_ADDRESSES)) {		/*		 * Enable promiscuous mode: receive all packets.		 */		if (!lp->promiscuous) {			lp->promiscuous = 1;			lp->mc_count = 0;			wv_82586_reconfig(dev);			/* Tell the kernel that we are doing a really bad job. */			dev->flags |= IFF_PROMISC;		}	} else		/* Are there multicast addresses to send? */	if (dev->mc_list != (struct dev_mc_list *) NULL) {		/*		 * Disable promiscuous mode, but receive all packets		 * in multicast list		 */#ifdef MULTICAST_AVOID		if (lp->promiscuous || (dev->mc_count != lp->mc_count))#endif		{			lp->promiscuous = 0;			lp->mc_count = dev->mc_count;			wv_82586_reconfig(dev);		}	} else {		/*		 * Switch to normal mode: disable promiscuous mode and 		 * clear the multicast list.		 */		if (lp->promiscuous || lp->mc_count == 0) {			lp->promiscuous = 0;			lp->mc_count = 0;			wv_82586_reconfig(dev);		}	}#ifdef DEBUG_IOCTL_TRACE	printk(KERN_DEBUG "%s: <-wavelan_set_multicast_list()\n",	       dev->name);#endif}/*------------------------------------------------------------------*//* * This function doesn't exist. * (Note : it was a nice way to test the reconfigure stuff...) */#ifdef SET_MAC_ADDRESSstatic int wavelan_set_mac_address(struct net_device * dev, void *addr){	struct sockaddr *mac = addr;	/* Copy the address. */	memcpy(dev->dev_addr, mac->sa_data, WAVELAN_ADDR_SIZE);	/* Reconfigure the beast. */	wv_82586_reconfig(dev);	return 0;}#endif				/* SET_MAC_ADDRESS */#ifdef WIRELESS_EXT		/* if wireless extensions exist in the kernel *//*------------------------------------------------------------------*//* * Frequency setting (for hardware capable of it) * It's a bit complicated and you don't really want to look into it. * (called in wavelan_ioctl) */static inline int wv_set_frequency(unsigned long ioaddr,	/* I/O port of the card */				   iw_freq * frequency){	const int BAND_NUM = 10;	/* Number of bands */	long freq = 0L;		/* offset to 2.4 GHz in .5 MHz */#ifdef DEBUG_IOCTL_INFO	int i;#endif	/* Setting by frequency */	/* Theoretically, you may set any frequency between	 * the two limits with a 0.5 MHz precision. In practice,	 * I don't want you to have trouble with local regulations.	 */	if ((frequency->e == 1) &&	    (frequency->m >= (int) 2.412e8)	    && (frequency->m <= (int) 2.487e8)) {		freq = ((frequency->m / 10000) - 24000L) / 5;	}	/* Setting by channel (same as wfreqsel) */	/* Warning: each channel is 22 MHz wide, so some of the channels	 * will interfere. */	if ((frequency->e == 0) && (frequency->m < BAND_NUM)) {		/* Get frequency offset. */		freq = channel_bands[frequency->m] >> 1;	}	/* Verify that the frequency is allowed. */	if (freq != 0L) {		u16 table[10];	/* Authorized frequency table */		/* Read the frequency table. */		fee_read(ioaddr, 0x71, table, 10);#ifdef DEBUG_IOCTL_INFO		printk(KERN_DEBUG "Frequency table: ");		for (i = 0; i < 10; i++) {			printk(" %04X", table[i]);		}		printk("\n");#endif		/* Look in the table to see whether the frequency is allowed. */		if (!(table[9 - ((freq - 24) / 16)] &		      (1 << ((freq - 24) % 16)))) return -EINVAL;	/* not allowed */	} else		return -EINVAL;	/* if we get a usable frequency */	if (freq != 0L) {		unsigned short area[16];		unsigned short dac[2];		unsigned short area_verify[16];		unsigned short dac_verify[2];		/* Corresponding gain (in the power adjust value table)		 * See AT&T WaveLAN Data Manual, REF 407-024689/E, page 3-8		 * and WCIN062D.DOC, page 6.2.9. */		unsigned short power_limit[] = { 40, 80, 120, 160, 0 };		int power_band = 0;	/* Selected band */		unsigned short power_adjust;	/* Correct value */		/* Search for the gain. */		power_band = 0;		while ((freq > power_limit[power_band]) &&		       (power_limit[++power_band] != 0));		/* Read the first area. */		fee_read(ioaddr, 0x00, area, 16);		/* Read the DAC. */		fee_read(ioaddr, 0x60, dac, 2);		/* Read the new power adjust value. */		fee_read(ioaddr, 0x6B - (power_band >> 1), &power_adjust,			 1);		if (power_band & 0x1)			power_adjust >>= 8;		else			power_adjust &= 0xFF;#ifdef DEBUG_IOCTL_INFO		printk(KERN_DEBUG "WaveLAN EEPROM Area 1: ");		for (i = 0; i < 16; i++) {			printk(" %04X", area[i]);		}		printk("\n");		printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n",		       dac[0], dac[1]);#endif		/* Frequency offset (for info only) */		area[0] = ((freq << 5) & 0xFFE0) | (area[0] & 0x1F);		/* Receiver Principle main divider coefficient */		area[3] = (freq >> 1) + 2400L - 352L;		area[2] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);		/* Transmitter Main divider coefficient */		area[13] = (freq >> 1) + 2400L;		area[12] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);		/* Other parts of the area are flags, bit streams or unused. */		/* Set the value in the DAC. */		dac[1] = ((power_adjust >> 1) & 0x7F) | (dac[1] & 0xFF80);		dac[0] = ((power_adjust & 0x1) << 4) | (dac[0] & 0xFFEF);		/* Write the first area. */		fee_write(ioaddr, 0x00, area, 16);		/* Write the DAC. */		fee_write(ioaddr, 0x60, dac, 2);		/* We now should verify here that the writing of the EEPROM went OK. */		/* Reread the first area. */		fee_read(ioaddr, 0x00, area_verify, 16);		/* Reread the DAC. */		fee_read(ioaddr, 0x60, dac_verify, 2);		/* Compare. */		if (memcmp(area, area_verify, 16 * 2) ||		    memcmp(dac, dac_verify, 2 * 2)) {#ifdef DEBUG_IOCTL_ERROR			printk(KERN_INFO			       "WaveLAN: wv_set_frequency: unable to write new frequency to EEPROM(?).\n");#endif			return -EOPNOTSUPP;		}		/* We must download the frequency parameters to the		 * synthesizers (from the EEPROM - area 1)		 * Note: as the EEPROM is automatically decremented, we set the end		 * if the area... */		mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x0F);		mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),			MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);		/* Wait until the download is finished. */		fee_wait(ioaddr, 100, 100);		/* We must now download the power adjust value (gain) to		 * the synthesizers (from the EEPROM - area 7 - DAC). */		mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x61);		mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),			MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);		/* Wait for the download to finish. */		fee_wait(ioaddr, 100, 100);#ifdef DEBUG_IOCTL_INFO		/* Verification of what we have done */		printk(KERN_DEBUG "WaveLAN EEPROM Area 1: ");		for (i = 0; i < 16; i++) {			printk(" %04X", area_verify[i]);		}		printk("\n");		printk(KERN_DEBUG "WaveLAN EEPROM DAC:  %04X %04X\n",		       dac_verify[0], dac_verify[1]);#endif		return 0;	} else		return -EINVAL;	/* Bah, never get there... */}/*------------------------------------------------------------------*//* * Give the list of available frequencies. */static inline int wv_frequency_list(unsigned long ioaddr,	/* I/O port of the card */				    iw_freq * list,	/* List of frequencies to fill */				    int max){				/* Maximum number of frequencies */	u16 table[10];	/* Authorized frequency table */	long freq = 0L;		/* offset to 2.4 GHz in .5 MHz + 12 MHz */	int i;			/* index in the table */	int c = 0;		/* Channel number */	/* Read the frequency table. */	fee_read(ioaddr, 0x71 /* frequency table */ , table, 10);	/* Check all frequencies. */	i = 0;	for (freq = 0; freq < 150; freq++)		/* Look in the table if the frequency is allowed */		if (table[9 - (freq / 16)] & (1 << (freq % 16))) {			/* Compute approximate channel number */			while ((((channel_bands[c] >> 1) - 24) < freq) &&			       (c < NELS(channel_bands)))				c++;			list[i].i = c;	/* Set the list index */			/* put in the list */			list[i].m = (((freq + 24) * 5) + 24000L) * 10000;			list[i++].e = 1;			/* Check number. */			if (i >= max)				return (i);		}	return (i);}#ifdef IW_WIRELESS_SPY/*------------------------------------------------------------------*//* * Gather wireless spy statistics:  for each packet, compare the source * address with our list, and if they match, get the statistics. * Sorry, but this function really needs the wireless extensions. */static inline void wl_spy_gather(struct net_device * dev,				 u8 *	mac,	/* MAC address */				 u8 *	stats)	/* Statistics to gather */{	struct iw_quality wstats;	wstats.qual = stats[2] & MMR_SGNL_QUAL;	wstats.level = stats[0] & MMR_SIGNAL_LVL;	wstats.noise = stats[1] & MMR_SILENCE_LVL;	wstats.updated = 0x7;	/* Update spy records */	wireless_spy_update(dev, mac, &wstats);}#endif /* IW_WIRELESS_SPY */#ifdef HISTOGRAM/*------------------------------------------------------------------*//* * This function calculates a histogram of the signal level. * As the noise is quite constant, it's like doing it on the SNR. * We have defined a set of interval (lp->his_range), and each time * the level goes in that interval, we increment the count (lp->his_sum). * With this histogram you may detect if one WaveLAN is really weak, * or you may also calculate the mean and standard deviation of the level. */static inline void wl_his_gather(struct net_device * dev, u8 * stats){				/* Statistics to gather */	net_local *lp = (net_local *) dev->priv;	u8 level = stats[0] & MMR_SIGNAL_LVL;	int i;	/* Find the correct interval. */	i = 0;	while ((i < (lp->his_number - 1))	       && (level >= lp->his_range[i++]));	/* Increment interval counter. */	(lp->his_sum[i])++;}#endif /* HISTOGRAM *//*------------------------------------------------------------------*//* * Wireless Handler : get protocol name */static int wavelan_get_name(struct net_device *dev,			    struct iw_request_info *info,			    union iwreq_data *wrqu,			    char *extra){	strcpy(wrqu->name, "WaveLAN");	return 0;}/*------------------------------------------------------------------*//* * Wireless Handler : set NWID */static int wavelan_set_nwid(struct net_device *dev,			    struct iw_request_info *info,			    union iwreq_data *wrqu,			    char *extra){	unsigned long ioaddr = dev->base_addr;	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */	psa_t psa;	mm_t m;	unsigned long flags;	int ret = 0;	/* Disable interrupts and save flags. */	spin_lock_irqsave(&lp->spinlock, flags);		/* Set NWID in WaveLAN. */	if (!wrqu->nwid.disabled) {		/* Set NWID in psa */		psa.psa_nwid[0] = (wrqu->nwid.value & 0xFF00) >> 8;		psa.psa_nwid[1] = wrqu->nwid.value & 0xFF;		psa.psa_nwid_select = 0x01;		psa_write(ioaddr, lp->hacr,			  (char *) psa.psa_nwid - (char *) &psa,			  (unsigned char *) psa.psa_nwid, 3);		/* Set NWID in mmc. */		m.w.mmw_netw_id_l = psa.psa_nwid[1];		m.w.mmw_netw_id_h = psa.psa_nwid[0];		mmc_write(ioaddr,			  (char *) &m.w.mmw_netw_id_l -			  (char *) &m,			  (unsigned char *) &m.w.mmw_netw_id_l, 2);		mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);	} else {		/* Disable NWID in the psa. */		psa.psa_nwid_select = 0x00;		psa_write(ioaddr, lp->hacr,			  (char *) &psa.psa_nwid_select -			  (char *) &psa,			  (unsigned char *) &psa.psa_nwid_select,			  1);		/* Disable NWID in the mmc (no filtering). */		mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel),			MMW_LOOPT_SEL_DIS_NWID);	}	/* update the Wavelan checksum */

⌨️ 快捷键说明

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