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

📄 ipw2200.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 inline 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 (ipw_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_ERROR("Firmware error detected.  Restarting.\n");		if (priv->error) {			IPW_ERROR("Sysfs 'error' log already exists.\n");#ifdef CONFIG_IPW_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_ERROR("Sysfs 'error' log captured.\n");			else				IPW_ERROR("Error allocating sysfs 'error' "					  "log.\n");#ifdef CONFIG_IPW_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);		IPW_CMD(VAP_SET_BEACONING_STATE);		IPW_CMD(MEASUREMENT);		IPW_CMD(POWER_CAPABILITY);		IPW_CMD(SUPPORTED_CHANNELS);		IPW_CMD(TPC_REPORT);		IPW_CMD(WME_INFO);		IPW_CMD(PRODUCTION_COMMAND);	default:		return "UNKNOWN";	}}#define HOST_COMPLETE_TIMEOUT HZstatic int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd){	int rc = 0;	unsigned long flags;	spin_lock_irqsave(&priv->lock, flags);	if (priv->status & STATUS_HCMD_ACTIVE) {		IPW_ERROR("Failed to send %s: Already sending a command.\n",			  get_cmd_string(cmd->cmd));		spin_unlock_irqrestore(&priv->lock, flags);		return -EAGAIN;	}	priv->status |= STATUS_HCMD_ACTIVE;	if (priv->cmdlog) {		priv->cmdlog[priv->cmdlog_pos].jiffies = jiffies;		priv->cmdlog[priv->cmdlog_pos].cmd.cmd = cmd->cmd;		priv->cmdlog[priv->cmdlog_pos].cmd.len = cmd->len;		memcpy(priv->cmdlog[priv->cmdlog_pos].cmd.param, cmd->param,		       cmd->len);		priv->cmdlog[priv->cmdlog_pos].retcode = -1;	}	IPW_DEBUG_HC("%s command (#%d) %d bytes: 0x%08X\n",		     get_cmd_string(cmd->cmd), cmd->cmd, cmd->len,		     priv->status);	printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len);	rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0);	if (rc) {		priv->status &= ~STATUS_HCMD_ACTIVE;		IPW_ERROR("Failed to send %s: Reason %d\n",			  get_cmd_string(cmd->cmd), rc);		spin_unlock_irqrestore(&priv->lock, flags);		goto exit;	}	spin_unlock_irqrestore(&priv->lock, flags);	rc = wait_event_interruptible_timeout(priv->wait_command_queue,					      !(priv->						status & STATUS_HCMD_ACTIVE),					      HOST_COMPLETE_TIMEOUT);	if (rc == 0) {		spin_lock_irqsave(&priv->lock, flags);		if (priv->status & STATUS_HCMD_ACTIVE) {			IPW_ERROR("Failed to send %s: Command timed out.\n",				  get_cmd_string(cmd->cmd));			priv->status &= ~STATUS_HCMD_ACTIVE;			spin_unlock_irqrestore(&priv->lock, flags);			rc = -EIO;			goto exit;		}		spin_unlock_irqrestore(&priv->lock, flags);	} else		rc = 0;	if (priv->status & STATUS_RF_KILL_HW) {		IPW_ERROR("Failed to send %s: Aborted due to RF kill switch.\n",			  get_cmd_string(cmd->cmd));		rc = -EIO;		goto exit;	}      exit:	if (priv->cmdlog) {		priv->cmdlog[priv->cmdlog_pos++].retcode = rc;		priv->cmdlog_pos %= priv->cmdlog_len;	}	return rc;}static int ipw_send_host_complete(struct ipw_priv *priv){	struct host_cmd cmd = {		.cmd = IPW_CMD_HOST_COMPLETE,		.len = 0	};	if (!priv) {

⌨️ 快捷键说明

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