ipw2200.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 2,379 行 · 第 1/5 页

C
2,379
字号
{	u32 reg = 0;	struct ipw_priv *p = d->driver_data;	reg = ipw_read_reg32(p, IPW_INTERNAL_CMD_EVENT);	return sprintf(buf, "0x%08x\n", reg);}static ssize_t store_command_event_reg(struct device *d,				       struct device_attribute *attr,				       const char *buf, size_t count){	u32 reg;	struct ipw_priv *p = d->driver_data;	sscanf(buf, "%x", &reg);	ipw_write_reg32(p, IPW_INTERNAL_CMD_EVENT, reg);	return strnlen(buf, count);}static DEVICE_ATTR(command_event_reg, S_IWUSR | S_IRUGO,		   show_command_event_reg, store_command_event_reg);static ssize_t show_mem_gpio_reg(struct device *d,				 struct device_attribute *attr, char *buf){	u32 reg = 0;	struct ipw_priv *p = d->driver_data;	reg = ipw_read_reg32(p, 0x301100);	return sprintf(buf, "0x%08x\n", reg);}static ssize_t store_mem_gpio_reg(struct device *d,				  struct device_attribute *attr,				  const char *buf, size_t count){	u32 reg;	struct ipw_priv *p = d->driver_data;	sscanf(buf, "%x", &reg);	ipw_write_reg32(p, 0x301100, reg);	return strnlen(buf, count);}static DEVICE_ATTR(mem_gpio_reg, S_IWUSR | S_IRUGO,		   show_mem_gpio_reg, store_mem_gpio_reg);static ssize_t show_indirect_dword(struct device *d,				   struct device_attribute *attr, char *buf){	u32 reg = 0;	struct ipw_priv *priv = d->driver_data;	if (priv->status & STATUS_INDIRECT_DWORD)		reg = ipw_read_reg32(priv, priv->indirect_dword);	else		reg = 0;	return sprintf(buf, "0x%08x\n", reg);}static ssize_t store_indirect_dword(struct device *d,				    struct device_attribute *attr,				    const char *buf, size_t count){	struct ipw_priv *priv = d->driver_data;	sscanf(buf, "%x", &priv->indirect_dword);	priv->status |= STATUS_INDIRECT_DWORD;	return strnlen(buf, count);}static DEVICE_ATTR(indirect_dword, S_IWUSR | S_IRUGO,		   show_indirect_dword, store_indirect_dword);static ssize_t show_indirect_byte(struct device *d,				  struct device_attribute *attr, char *buf){	u8 reg = 0;	struct ipw_priv *priv = d->driver_data;	if (priv->status & STATUS_INDIRECT_BYTE)		reg = ipw_read_reg8(priv, priv->indirect_byte);	else		reg = 0;	return sprintf(buf, "0x%02x\n", reg);}static ssize_t store_indirect_byte(struct device *d,				   struct device_attribute *attr,				   const char *buf, size_t count){	struct ipw_priv *priv = d->driver_data;	sscanf(buf, "%x", &priv->indirect_byte);	priv->status |= STATUS_INDIRECT_BYTE;	return strnlen(buf, count);}static DEVICE_ATTR(indirect_byte, S_IWUSR | S_IRUGO,		   show_indirect_byte, store_indirect_byte);static ssize_t show_direct_dword(struct device *d,				 struct device_attribute *attr, char *buf){	u32 reg = 0;	struct ipw_priv *priv = d->driver_data;	if (priv->status & STATUS_DIRECT_DWORD)		reg = ipw_read32(priv, priv->direct_dword);	else		reg = 0;	return sprintf(buf, "0x%08x\n", reg);}static ssize_t store_direct_dword(struct device *d,				  struct device_attribute *attr,				  const char *buf, size_t count){	struct ipw_priv *priv = d->driver_data;	sscanf(buf, "%x", &priv->direct_dword);	priv->status |= STATUS_DIRECT_DWORD;	return strnlen(buf, count);}static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO,		   show_direct_dword, store_direct_dword);static int rf_kill_active(struct ipw_priv *priv){	if (0 == (ipw_read32(priv, 0x30) & 0x10000))		priv->status |= STATUS_RF_KILL_HW;	else		priv->status &= ~STATUS_RF_KILL_HW;	return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0;}static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr,			    char *buf){	/* 0 - RF kill not enabled	   1 - SW based RF kill active (sysfs)	   2 - HW based RF kill active	   3 - Both HW and SW baed RF kill active */	struct ipw_priv *priv = d->driver_data;	int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) |	    (rf_kill_active(priv) ? 0x2 : 0x0);	return sprintf(buf, "%i\n", val);}static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio){	if ((disable_radio ? 1 : 0) ==	    ((priv->status & STATUS_RF_KILL_SW) ? 1 : 0))		return 0;	IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO  %s\n",			  disable_radio ? "OFF" : "ON");	if (disable_radio) {		priv->status |= STATUS_RF_KILL_SW;		if (priv->workqueue)			cancel_delayed_work(&priv->request_scan);		queue_work(priv->workqueue, &priv->down);	} else {		priv->status &= ~STATUS_RF_KILL_SW;		if (rf_kill_active(priv)) {			IPW_DEBUG_RF_KILL("Can not turn radio back on - "					  "disabled by HW switch\n");			/* Make sure the RF_KILL check timer is running */			cancel_delayed_work(&priv->rf_kill);			queue_delayed_work(priv->workqueue, &priv->rf_kill,					   2 * HZ);		} else			queue_work(priv->workqueue, &priv->up);	}	return 1;}static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr,			     const char *buf, size_t count){	struct ipw_priv *priv = d->driver_data;	ipw_radio_kill_sw(priv, buf[0] == '1');	return count;}static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);static ssize_t show_speed_scan(struct device *d, struct device_attribute *attr,			       char *buf){	struct ipw_priv *priv = (struct ipw_priv *)d->driver_data;	int pos = 0, len = 0;	if (priv->config & CFG_SPEED_SCAN) {		while (priv->speed_scan[pos] != 0)			len += sprintf(&buf[len], "%d ",				       priv->speed_scan[pos++]);		return len + sprintf(&buf[len], "\n");	}	return sprintf(buf, "0\n");}static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr,				const char *buf, size_t count){	struct ipw_priv *priv = (struct ipw_priv *)d->driver_data;	int channel, pos = 0;	const char *p = buf;	/* list of space separated channels to scan, optionally ending with 0 */	while ((channel = simple_strtol(p, NULL, 0))) {		if (pos == MAX_SPEED_SCAN - 1) {			priv->speed_scan[pos] = 0;			break;		}		if (ieee80211_is_valid_channel(priv->ieee, channel))			priv->speed_scan[pos++] = channel;		else			IPW_WARNING("Skipping invalid channel request: %d\n",				    channel);		p = strchr(p, ' ');		if (!p)			break;		while (*p == ' ' || *p == '\t')			p++;	}	if (pos == 0)		priv->config &= ~CFG_SPEED_SCAN;	else {		priv->speed_scan_pos = 0;		priv->config |= CFG_SPEED_SCAN;	}	return count;}static DEVICE_ATTR(speed_scan, S_IWUSR | S_IRUGO, show_speed_scan,		   store_speed_scan);static ssize_t show_net_stats(struct device *d, struct device_attribute *attr,			      char *buf){	struct ipw_priv *priv = (struct ipw_priv *)d->driver_data;	return sprintf(buf, "%c\n", (priv->config & CFG_NET_STATS) ? '1' : '0');}static ssize_t store_net_stats(struct device *d, struct device_attribute *attr,			       const char *buf, size_t count){	struct ipw_priv *priv = (struct ipw_priv *)d->driver_data;	if (buf[0] == '1')		priv->config |= CFG_NET_STATS;	else		priv->config &= ~CFG_NET_STATS;	return count;}static DEVICE_ATTR(net_stats, S_IWUSR | S_IRUGO,		   show_net_stats, store_net_stats);static void notify_wx_assoc_event(struct ipw_priv *priv){	union iwreq_data wrqu;	wrqu.ap_addr.sa_family = ARPHRD_ETHER;	if (priv->status & STATUS_ASSOCIATED)		memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN);	else		memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);	wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);}static void ipw_irq_tasklet(struct ipw_priv *priv){	u32 inta, inta_mask, handled = 0;	unsigned long flags;	int rc = 0;	spin_lock_irqsave(&priv->lock, flags);	inta = ipw_read32(priv, IPW_INTA_RW);	inta_mask = ipw_read32(priv, IPW_INTA_MASK_R);	inta &= (IPW_INTA_MASK_ALL & inta_mask);	/* Add any cached INTA values that need to be handled */	inta |= priv->isr_inta;	/* handle all the justifications for the interrupt */	if (inta & IPW_INTA_BIT_RX_TRANSFER) {		ipw_rx(priv);		handled |= IPW_INTA_BIT_RX_TRANSFER;	}	if (inta & IPW_INTA_BIT_TX_CMD_QUEUE) {		IPW_DEBUG_HC("Command completed.\n");		rc = ipw_queue_tx_reclaim(priv, &priv->txq_cmd, -1);		priv->status &= ~STATUS_HCMD_ACTIVE;		wake_up_interruptible(&priv->wait_command_queue);		handled |= IPW_INTA_BIT_TX_CMD_QUEUE;	}	if (inta & IPW_INTA_BIT_TX_QUEUE_1) {		IPW_DEBUG_TX("TX_QUEUE_1\n");		rc = ipw_queue_tx_reclaim(priv, &priv->txq[0], 0);		handled |= IPW_INTA_BIT_TX_QUEUE_1;	}	if (inta & IPW_INTA_BIT_TX_QUEUE_2) {		IPW_DEBUG_TX("TX_QUEUE_2\n");		rc = ipw_queue_tx_reclaim(priv, &priv->txq[1], 1);		handled |= IPW_INTA_BIT_TX_QUEUE_2;	}	if (inta & IPW_INTA_BIT_TX_QUEUE_3) {		IPW_DEBUG_TX("TX_QUEUE_3\n");		rc = ipw_queue_tx_reclaim(priv, &priv->txq[2], 2);		handled |= IPW_INTA_BIT_TX_QUEUE_3;	}	if (inta & IPW_INTA_BIT_TX_QUEUE_4) {		IPW_DEBUG_TX("TX_QUEUE_4\n");		rc = ipw_queue_tx_reclaim(priv, &priv->txq[3], 3);		handled |= IPW_INTA_BIT_TX_QUEUE_4;	}	if (inta & IPW_INTA_BIT_STATUS_CHANGE) {		IPW_WARNING("STATUS_CHANGE\n");		handled |= IPW_INTA_BIT_STATUS_CHANGE;	}	if (inta & IPW_INTA_BIT_BEACON_PERIOD_EXPIRED) {		IPW_WARNING("TX_PERIOD_EXPIRED\n");		handled |= IPW_INTA_BIT_BEACON_PERIOD_EXPIRED;	}	if (inta & IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE) {		IPW_WARNING("HOST_CMD_DONE\n");		handled |= IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE;	}	if (inta & IPW_INTA_BIT_FW_INITIALIZATION_DONE) {		IPW_WARNING("FW_INITIALIZATION_DONE\n");		handled |= IPW_INTA_BIT_FW_INITIALIZATION_DONE;	}	if (inta & IPW_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE) {		IPW_WARNING("PHY_OFF_DONE\n");		handled |= IPW_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE;	}	if (inta & IPW_INTA_BIT_RF_KILL_DONE) {		IPW_DEBUG_RF_KILL("RF_KILL_DONE\n");		priv->status |= STATUS_RF_KILL_HW;		wake_up_interruptible(&priv->wait_command_queue);		priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);		cancel_delayed_work(&priv->request_scan);		schedule_work(&priv->link_down);		queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);		handled |= IPW_INTA_BIT_RF_KILL_DONE;	}	if (inta & IPW_INTA_BIT_FATAL_ERROR) {		IPW_WARNING("Firmware error detected.  Restarting.\n");		if (priv->error) {			IPW_DEBUG_FW("Sysfs 'error' log already exists.\n");#ifdef CONFIG_IPW2200_DEBUG			if (ipw_debug_level & IPW_DL_FW_ERRORS) {				struct ipw_fw_error *error =				    ipw_alloc_error_log(priv);				ipw_dump_error_log(priv, error);				if (error)					ipw_free_error_log(error);			}#endif		} else {			priv->error = ipw_alloc_error_log(priv);			if (priv->error)				IPW_DEBUG_FW("Sysfs 'error' log captured.\n");			else				IPW_DEBUG_FW("Error allocating sysfs 'error' "					     "log.\n");#ifdef CONFIG_IPW2200_DEBUG			if (ipw_debug_level & IPW_DL_FW_ERRORS)				ipw_dump_error_log(priv, priv->error);#endif		}		/* XXX: If hardware encryption is for WPA/WPA2,		 * we have to notify the supplicant. */		if (priv->ieee->sec.encrypt) {			priv->status &= ~STATUS_ASSOCIATED;			notify_wx_assoc_event(priv);		}		/* Keep the restart process from trying to send host		 * commands by clearing the INIT status bit */		priv->status &= ~STATUS_INIT;		/* Cancel currently queued command. */		priv->status &= ~STATUS_HCMD_ACTIVE;		wake_up_interruptible(&priv->wait_command_queue);		queue_work(priv->workqueue, &priv->adapter_restart);		handled |= IPW_INTA_BIT_FATAL_ERROR;	}	if (inta & IPW_INTA_BIT_PARITY_ERROR) {		IPW_ERROR("Parity error\n");		handled |= IPW_INTA_BIT_PARITY_ERROR;	}	if (handled != inta) {		IPW_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled);	}	/* enable all interrupts */	ipw_enable_interrupts(priv);	spin_unlock_irqrestore(&priv->lock, flags);}#define IPW_CMD(x) case IPW_CMD_ ## x : return #xstatic char *get_cmd_string(u8 cmd){	switch (cmd) {		IPW_CMD(HOST_COMPLETE);		IPW_CMD(POWER_DOWN);		IPW_CMD(SYSTEM_CONFIG);		IPW_CMD(MULTICAST_ADDRESS);		IPW_CMD(SSID);		IPW_CMD(ADAPTER_ADDRESS);		IPW_CMD(PORT_TYPE);		IPW_CMD(RTS_THRESHOLD);		IPW_CMD(FRAG_THRESHOLD);		IPW_CMD(POWER_MODE);		IPW_CMD(WEP_KEY);		IPW_CMD(TGI_TX_KEY);		IPW_CMD(SCAN_REQUEST);		IPW_CMD(SCAN_REQUEST_EXT);		IPW_CMD(ASSOCIATE);		IPW_CMD(SUPPORTED_RATES);		IPW_CMD(SCAN_ABORT);		IPW_CMD(TX_FLUSH);		IPW_CMD(QOS_PARAMETERS);		IPW_CMD(DINO_CONFIG);		IPW_CMD(RSN_CAPABILITIES);		IPW_CMD(RX_KEY);		IPW_CMD(CARD_DISABLE);		IPW_CMD(SEED_NUMBER);		IPW_CMD(TX_POWER);		IPW_CMD(COUNTRY_INFO);		IPW_CMD(AIRONET_INFO);		IPW_CMD(AP_TX_POWER);		IPW_CMD(CCKM_INFO);		IPW_CMD(CCX_VER_INFO);		IPW_CMD(SET_CALIBRATION);		IPW_CMD(SENSITIVITY_CALIB);		IPW_CMD(RETRY_LIMIT);		IPW_CMD(IPW_PRE_POWER_DOWN);		IPW_CMD(VAP_BEACON_TEMPLATE);		IPW_CMD(VAP_DTIM_PERIOD);		IPW_CMD(EXT_SUPPORTED_RATES);		IPW_CMD(VAP_LOCAL_TX_PWR_CONSTRAINT);		IPW_CMD(VAP_QUIET_INTERVALS);		IPW_CMD(VAP_CHANNEL_SWITCH);		IPW_CMD(VAP_MANDATORY_CHANNELS);		IPW_CMD(VAP_CELL_PWR_LIMIT);		IPW_CMD(VAP_CF_PARAM_SET);

⌨️ 快捷键说明

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