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

📄 ipw2100.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	err = ipw2100_wait_for_card_state(priv, IPW_HW_STATE_ENABLED);	if (err) {		IPW_DEBUG_INFO("%s: card not responding to init command.\n",			       priv->net_dev->name);		goto fail_up;	}	if (priv->stop_hang_check) {		priv->stop_hang_check = 0;		queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2);	}      fail_up:	up(&priv->adapter_sem);	return err;}static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv){#define HW_POWER_DOWN_DELAY (msecs_to_jiffies(100))	struct host_command cmd = {		.host_command = HOST_PRE_POWER_DOWN,		.host_command_sequence = 0,		.host_command_length = 0,	};	int err, i;	u32 reg;	if (!(priv->status & STATUS_RUNNING))		return 0;	priv->status |= STATUS_STOPPING;	/* We can only shut down the card if the firmware is operational.  So,	 * if we haven't reset since a fatal_error, then we can not send the	 * shutdown commands. */	if (!priv->fatal_error) {		/* First, make sure the adapter is enabled so that the PHY_OFF		 * command can shut it down */		ipw2100_enable_adapter(priv);		err = ipw2100_hw_phy_off(priv);		if (err)			printk(KERN_WARNING DRV_NAME			       ": Error disabling radio %d\n", err);		/*		 * If in D0-standby mode going directly to D3 may cause a		 * PCI bus violation.  Therefore we must change out of the D0		 * state.		 *		 * Sending the PREPARE_FOR_POWER_DOWN will restrict the		 * hardware from going into standby mode and will transition		 * out of D0-standy if it is already in that state.		 *		 * STATUS_PREPARE_POWER_DOWN_COMPLETE will be sent by the		 * driver upon completion.  Once received, the driver can		 * proceed to the D3 state.		 *		 * Prepare for power down command to fw.  This command would		 * take HW out of D0-standby and prepare it for D3 state.		 *		 * Currently FW does not support event notification for this		 * event. Therefore, skip waiting for it.  Just wait a fixed		 * 100ms		 */		IPW_DEBUG_HC("HOST_PRE_POWER_DOWN\n");		err = ipw2100_hw_send_command(priv, &cmd);		if (err)			printk(KERN_WARNING DRV_NAME ": "			       "%s: Power down command failed: Error %d\n",			       priv->net_dev->name, err);		else			schedule_timeout_uninterruptible(HW_POWER_DOWN_DELAY);	}	priv->status &= ~STATUS_ENABLED;	/*	 * Set GPIO 3 writable by FW; GPIO 1 writable	 * by driver and enable clock	 */	ipw2100_hw_set_gpio(priv);	/*	 * Power down adapter.  Sequence:	 * 1. Stop master assert (RESET_REG[9]=1)	 * 2. Wait for stop master (RESET_REG[8]==1)	 * 3. S/w reset assert (RESET_REG[7] = 1)	 */	/* Stop master assert */	write_register(priv->net_dev, IPW_REG_RESET_REG,		       IPW_AUX_HOST_RESET_REG_STOP_MASTER);	/* wait stop master not more than 50 usec.	 * Otherwise return error. */	for (i = 5; i > 0; i--) {		udelay(10);		/* Check master stop bit */		read_register(priv->net_dev, IPW_REG_RESET_REG, &reg);		if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)			break;	}	if (i == 0)		printk(KERN_WARNING DRV_NAME		       ": %s: Could now power down adapter.\n",		       priv->net_dev->name);	/* assert s/w reset */	write_register(priv->net_dev, IPW_REG_RESET_REG,		       IPW_AUX_HOST_RESET_REG_SW_RESET);	priv->status &= ~(STATUS_RUNNING | STATUS_STOPPING);	return 0;}static int ipw2100_disable_adapter(struct ipw2100_priv *priv){	struct host_command cmd = {		.host_command = CARD_DISABLE,		.host_command_sequence = 0,		.host_command_length = 0	};	int err = 0;	IPW_DEBUG_HC("CARD_DISABLE\n");	if (!(priv->status & STATUS_ENABLED))		return 0;	/* Make sure we clear the associated state */	priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);	if (!priv->stop_hang_check) {		priv->stop_hang_check = 1;		cancel_delayed_work(&priv->hang_check);	}	down(&priv->adapter_sem);	err = ipw2100_hw_send_command(priv, &cmd);	if (err) {		printk(KERN_WARNING DRV_NAME		       ": exit - failed to send CARD_DISABLE command\n");		goto fail_up;	}	err = ipw2100_wait_for_card_state(priv, IPW_HW_STATE_DISABLED);	if (err) {		printk(KERN_WARNING DRV_NAME		       ": exit - card failed to change to DISABLED\n");		goto fail_up;	}	IPW_DEBUG_INFO("TODO: implement scan state machine\n");      fail_up:	up(&priv->adapter_sem);	return err;}static int ipw2100_set_scan_options(struct ipw2100_priv *priv){	struct host_command cmd = {		.host_command = SET_SCAN_OPTIONS,		.host_command_sequence = 0,		.host_command_length = 8	};	int err;	IPW_DEBUG_INFO("enter\n");	IPW_DEBUG_SCAN("setting scan options\n");	cmd.host_command_parameters[0] = 0;	if (!(priv->config & CFG_ASSOCIATE))		cmd.host_command_parameters[0] |= IPW_SCAN_NOASSOCIATE;	if ((priv->ieee->sec.flags & SEC_ENABLED) && priv->ieee->sec.enabled)		cmd.host_command_parameters[0] |= IPW_SCAN_MIXED_CELL;	if (priv->config & CFG_PASSIVE_SCAN)		cmd.host_command_parameters[0] |= IPW_SCAN_PASSIVE;	cmd.host_command_parameters[1] = priv->channel_mask;	err = ipw2100_hw_send_command(priv, &cmd);	IPW_DEBUG_HC("SET_SCAN_OPTIONS 0x%04X\n",		     cmd.host_command_parameters[0]);	return err;}static int ipw2100_start_scan(struct ipw2100_priv *priv){	struct host_command cmd = {		.host_command = BROADCAST_SCAN,		.host_command_sequence = 0,		.host_command_length = 4	};	int err;	IPW_DEBUG_HC("START_SCAN\n");	cmd.host_command_parameters[0] = 0;	/* No scanning if in monitor mode */	if (priv->ieee->iw_mode == IW_MODE_MONITOR)		return 1;	if (priv->status & STATUS_SCANNING) {		IPW_DEBUG_SCAN("Scan requested while already in scan...\n");		return 0;	}	IPW_DEBUG_INFO("enter\n");	/* Not clearing here; doing so makes iwlist always return nothing...	 *	 * We should modify the table logic to use aging tables vs. clearing	 * the table on each scan start.	 */	IPW_DEBUG_SCAN("starting scan\n");	priv->status |= STATUS_SCANNING;	err = ipw2100_hw_send_command(priv, &cmd);	if (err)		priv->status &= ~STATUS_SCANNING;	IPW_DEBUG_INFO("exit\n");	return err;}static int ipw2100_up(struct ipw2100_priv *priv, int deferred){	unsigned long flags;	int rc = 0;	u32 lock;	u32 ord_len = sizeof(lock);	/* Quite if manually disabled. */	if (priv->status & STATUS_RF_KILL_SW) {		IPW_DEBUG_INFO("%s: Radio is disabled by Manual Disable "			       "switch\n", priv->net_dev->name);		return 0;	}	/* If the interrupt is enabled, turn it off... */	spin_lock_irqsave(&priv->low_lock, flags);	ipw2100_disable_interrupts(priv);	/* Reset any fatal_error conditions */	ipw2100_reset_fatalerror(priv);	spin_unlock_irqrestore(&priv->low_lock, flags);	if (priv->status & STATUS_POWERED ||	    (priv->status & STATUS_RESET_PENDING)) {		/* Power cycle the card ... */		if (ipw2100_power_cycle_adapter(priv)) {			printk(KERN_WARNING DRV_NAME			       ": %s: Could not cycle adapter.\n",			       priv->net_dev->name);			rc = 1;			goto exit;		}	} else		priv->status |= STATUS_POWERED;	/* Load the firmware, start the clocks, etc. */	if (ipw2100_start_adapter(priv)) {		printk(KERN_ERR DRV_NAME		       ": %s: Failed to start the firmware.\n",		       priv->net_dev->name);		rc = 1;		goto exit;	}	ipw2100_initialize_ordinals(priv);	/* Determine capabilities of this particular HW configuration */	if (ipw2100_get_hw_features(priv)) {		printk(KERN_ERR DRV_NAME		       ": %s: Failed to determine HW features.\n",		       priv->net_dev->name);		rc = 1;		goto exit;	}	lock = LOCK_NONE;	if (ipw2100_set_ordinal(priv, IPW_ORD_PERS_DB_LOCK, &lock, &ord_len)) {		printk(KERN_ERR DRV_NAME		       ": %s: Failed to clear ordinal lock.\n",		       priv->net_dev->name);		rc = 1;		goto exit;	}	priv->status &= ~STATUS_SCANNING;	if (rf_kill_active(priv)) {		printk(KERN_INFO "%s: Radio is disabled by RF switch.\n",		       priv->net_dev->name);		if (priv->stop_rf_kill) {			priv->stop_rf_kill = 0;			queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);		}		deferred = 1;	}	/* Turn on the interrupt so that commands can be processed */	ipw2100_enable_interrupts(priv);	/* Send all of the commands that must be sent prior to	 * HOST_COMPLETE */	if (ipw2100_adapter_setup(priv)) {		printk(KERN_ERR DRV_NAME ": %s: Failed to start the card.\n",		       priv->net_dev->name);		rc = 1;		goto exit;	}	if (!deferred) {		/* Enable the adapter - sends HOST_COMPLETE */		if (ipw2100_enable_adapter(priv)) {			printk(KERN_ERR DRV_NAME ": "			       "%s: failed in call to enable adapter.\n",			       priv->net_dev->name);			ipw2100_hw_stop_adapter(priv);			rc = 1;			goto exit;		}		/* Start a scan . . . */		ipw2100_set_scan_options(priv);		ipw2100_start_scan(priv);	}      exit:	return rc;}/* Called by register_netdev() */static int ipw2100_net_init(struct net_device *dev){	struct ipw2100_priv *priv = ieee80211_priv(dev);	return ipw2100_up(priv, 1);}static void ipw2100_down(struct ipw2100_priv *priv){	unsigned long flags;	union iwreq_data wrqu = {		.ap_addr = {			    .sa_family = ARPHRD_ETHER}	};	int associated = priv->status & STATUS_ASSOCIATED;	/* Kill the RF switch timer */	if (!priv->stop_rf_kill) {		priv->stop_rf_kill = 1;		cancel_delayed_work(&priv->rf_kill);	}	/* Kill the firmare hang check timer */	if (!priv->stop_hang_check) {		priv->stop_hang_check = 1;		cancel_delayed_work(&priv->hang_check);	}	/* Kill any pending resets */	if (priv->status & STATUS_RESET_PENDING)		cancel_delayed_work(&priv->reset_work);	/* Make sure the interrupt is on so that FW commands will be	 * processed correctly */	spin_lock_irqsave(&priv->low_lock, flags);	ipw2100_enable_interrupts(priv);	spin_unlock_irqrestore(&priv->low_lock, flags);	if (ipw2100_hw_stop_adapter(priv))		printk(KERN_ERR DRV_NAME ": %s: Error stopping adapter.\n",		       priv->net_dev->name);	/* Do not disable the interrupt until _after_ we disable	 * the adaptor.  Otherwise the CARD_DISABLE command will never	 * be ack'd by the firmware */	spin_lock_irqsave(&priv->low_lock, flags);	ipw2100_disable_interrupts(priv);	spin_unlock_irqrestore(&priv->low_lock, flags);#ifdef ACPI_CSTATE_LIMIT_DEFINED	if (priv->config & CFG_C3_DISABLED) {		IPW_DEBUG_INFO(": Resetting C3 transitions.\n");		acpi_set_cstate_limit(priv->cstate_limit);		priv->config &= ~CFG_C3_DISABLED;	}#endif	/* We have to signal any supplicant if we are disassociating */	if (associated)		wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);	priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);	netif_carrier_off(priv->net_dev);	netif_stop_queue(priv->net_dev);}static void ipw2100_reset_adapter(struct ipw2100_priv *priv){	unsigned long flags;	union iwreq_data wrqu = {		.ap_addr = {			    .sa_family = ARPHRD_ETHER}	};	int associated = priv->status & STATUS_ASSOCIATED;	spin_lock_irqsave(&priv->low_lock, flags);	IPW_DEBUG_INFO(": %s: Restarting adapter.\n", priv->net_dev->name);	priv->resets++;	priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);	priv->status |= STATUS_SECURITY_UPDATED;	/* Force a power cycle even if interface hasn't been opened	 * yet */	cancel_delayed_work(&priv->reset_work);	priv->status |= STATUS_RESET_PENDING;	spin_unlock_irqrestore(&priv->low_lock, flags);	down(&priv->action_sem);	/* stop timed checks so that they don't interfere with reset */	priv->stop_hang_check = 1;	cancel_delayed_work(&priv->hang_check);	/* We have to signal any supplicant if we are disassociating */	if (associated)		wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);	ipw2100_up(priv, 0);	up(&priv->action_sem);}static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status){#define MAC_ASSOCIATION_READ_DELAY (HZ)	int ret, len, essid_len;	char essid[IW_ESSID_MAX_SIZE];	u32 txrate;	u32 chan;	char *txratename;	u8 bssid[ETH_ALEN];	/*	 * TBD: BSSID is usually 00:00:00:00:00:00 here and not	 *      an actual MAC of the AP. Seems like FW sets this	 *      address too late. Read it later and expose through	 *      /proc or schedule a later task to query and update	 */	essid_len = IW_ESSID_MAX_SIZE;	ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_SSID,				  essid, &essid_len);	if (ret) {		IPW_DEBUG_INFO("failed querying ordinals at line %d\n",

⌨️ 快捷键说明

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