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

📄 ipw2100.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			       __LINE__);		return;	}	len = sizeof(u32);	ret = ipw2100_get_ordinal(priv, IPW_ORD_CURRENT_TX_RATE, &txrate, &len);	if (ret) {		IPW_DEBUG_INFO("failed querying ordinals at line %d\n",			       __LINE__);		return;	}	len = sizeof(u32);	ret = ipw2100_get_ordinal(priv, IPW_ORD_OUR_FREQ, &chan, &len);	if (ret) {		IPW_DEBUG_INFO("failed querying ordinals at line %d\n",			       __LINE__);		return;	}	len = ETH_ALEN;	ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, &bssid, &len);	if (ret) {		IPW_DEBUG_INFO("failed querying ordinals at line %d\n",			       __LINE__);		return;	}	memcpy(priv->ieee->bssid, bssid, ETH_ALEN);	switch (txrate) {	case TX_RATE_1_MBIT:		txratename = "1Mbps";		break;	case TX_RATE_2_MBIT:		txratename = "2Mbsp";		break;	case TX_RATE_5_5_MBIT:		txratename = "5.5Mbps";		break;	case TX_RATE_11_MBIT:		txratename = "11Mbps";		break;	default:		IPW_DEBUG_INFO("Unknown rate: %d\n", txrate);		txratename = "unknown rate";		break;	}	IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID="		       MAC_FMT ")\n",		       priv->net_dev->name, escape_essid(essid, essid_len),		       txratename, chan, MAC_ARG(bssid));	/* now we copy read ssid into dev */	if (!(priv->config & CFG_STATIC_ESSID)) {		priv->essid_len = min((u8) essid_len, (u8) IW_ESSID_MAX_SIZE);		memcpy(priv->essid, essid, priv->essid_len);	}	priv->channel = chan;	memcpy(priv->bssid, bssid, ETH_ALEN);	priv->status |= STATUS_ASSOCIATING;	priv->connect_start = get_seconds();	queue_delayed_work(priv->workqueue, &priv->wx_event_work, HZ / 10);}static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,			     int length, int batch_mode){	int ssid_len = min(length, IW_ESSID_MAX_SIZE);	struct host_command cmd = {		.host_command = SSID,		.host_command_sequence = 0,		.host_command_length = ssid_len	};	int err;	IPW_DEBUG_HC("SSID: '%s'\n", escape_essid(essid, ssid_len));	if (ssid_len)		memcpy(cmd.host_command_parameters, essid, ssid_len);	if (!batch_mode) {		err = ipw2100_disable_adapter(priv);		if (err)			return err;	}	/* Bug in FW currently doesn't honor bit 0 in SET_SCAN_OPTIONS to	 * disable auto association -- so we cheat by setting a bogus SSID */	if (!ssid_len && !(priv->config & CFG_ASSOCIATE)) {		int i;		u8 *bogus = (u8 *) cmd.host_command_parameters;		for (i = 0; i < IW_ESSID_MAX_SIZE; i++)			bogus[i] = 0x18 + i;		cmd.host_command_length = IW_ESSID_MAX_SIZE;	}	/* NOTE:  We always send the SSID command even if the provided ESSID is	 * the same as what we currently think is set. */	err = ipw2100_hw_send_command(priv, &cmd);	if (!err) {		memset(priv->essid + ssid_len, 0, IW_ESSID_MAX_SIZE - ssid_len);		memcpy(priv->essid, essid, ssid_len);		priv->essid_len = ssid_len;	}	if (!batch_mode) {		if (ipw2100_enable_adapter(priv))			err = -EIO;	}	return err;}static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status){	IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,		  "disassociated: '%s' " MAC_FMT " \n",		  escape_essid(priv->essid, priv->essid_len),		  MAC_ARG(priv->bssid));	priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);	if (priv->status & STATUS_STOPPING) {		IPW_DEBUG_INFO("Card is stopping itself, discard ASSN_LOST.\n");		return;	}	memset(priv->bssid, 0, ETH_ALEN);	memset(priv->ieee->bssid, 0, ETH_ALEN);	netif_carrier_off(priv->net_dev);	netif_stop_queue(priv->net_dev);	if (!(priv->status & STATUS_RUNNING))		return;	if (priv->status & STATUS_SECURITY_UPDATED)		queue_work(priv->workqueue, &priv->security_work);	queue_work(priv->workqueue, &priv->wx_event_work);}static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status){	IPW_DEBUG_INFO("%s: RF Kill state changed to radio OFF.\n",		       priv->net_dev->name);	/* RF_KILL is now enabled (else we wouldn't be here) */	priv->status |= STATUS_RF_KILL_HW;#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	/* Make sure the RF Kill check timer is running */	priv->stop_rf_kill = 0;	cancel_delayed_work(&priv->rf_kill);	queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);}static void isr_scan_complete(struct ipw2100_priv *priv, u32 status){	IPW_DEBUG_SCAN("scan complete\n");	/* Age the scan results... */	priv->ieee->scans++;	priv->status &= ~STATUS_SCANNING;}#ifdef CONFIG_IPW_DEBUG#define IPW2100_HANDLER(v, f) { v, f, # v }struct ipw2100_status_indicator {	int status;	void (*cb) (struct ipw2100_priv * priv, u32 status);	char *name;};#else#define IPW2100_HANDLER(v, f) { v, f }struct ipw2100_status_indicator {	int status;	void (*cb) (struct ipw2100_priv * priv, u32 status);};#endif				/* CONFIG_IPW_DEBUG */static void isr_indicate_scanning(struct ipw2100_priv *priv, u32 status){	IPW_DEBUG_SCAN("Scanning...\n");	priv->status |= STATUS_SCANNING;}static const struct ipw2100_status_indicator status_handlers[] = {	IPW2100_HANDLER(IPW_STATE_INITIALIZED, NULL),	IPW2100_HANDLER(IPW_STATE_COUNTRY_FOUND, NULL),	IPW2100_HANDLER(IPW_STATE_ASSOCIATED, isr_indicate_associated),	IPW2100_HANDLER(IPW_STATE_ASSN_LOST, isr_indicate_association_lost),	IPW2100_HANDLER(IPW_STATE_ASSN_CHANGED, NULL),	IPW2100_HANDLER(IPW_STATE_SCAN_COMPLETE, isr_scan_complete),	IPW2100_HANDLER(IPW_STATE_ENTERED_PSP, NULL),	IPW2100_HANDLER(IPW_STATE_LEFT_PSP, NULL),	IPW2100_HANDLER(IPW_STATE_RF_KILL, isr_indicate_rf_kill),	IPW2100_HANDLER(IPW_STATE_DISABLED, NULL),	IPW2100_HANDLER(IPW_STATE_POWER_DOWN, NULL),	IPW2100_HANDLER(IPW_STATE_SCANNING, isr_indicate_scanning),	IPW2100_HANDLER(-1, NULL)};static void isr_status_change(struct ipw2100_priv *priv, int status){	int i;	if (status == IPW_STATE_SCANNING &&	    priv->status & STATUS_ASSOCIATED &&	    !(priv->status & STATUS_SCANNING)) {		IPW_DEBUG_INFO("Scan detected while associated, with "			       "no scan request.  Restarting firmware.\n");		/* Wake up any sleeping jobs */		schedule_reset(priv);	}	for (i = 0; status_handlers[i].status != -1; i++) {		if (status == status_handlers[i].status) {			IPW_DEBUG_NOTIF("Status change: %s\n",					status_handlers[i].name);			if (status_handlers[i].cb)				status_handlers[i].cb(priv, status);			priv->wstats.status = status;			return;		}	}	IPW_DEBUG_NOTIF("unknown status received: %04x\n", status);}static void isr_rx_complete_command(struct ipw2100_priv *priv,				    struct ipw2100_cmd_header *cmd){#ifdef CONFIG_IPW_DEBUG	if (cmd->host_command_reg < ARRAY_SIZE(command_types)) {		IPW_DEBUG_HC("Command completed '%s (%d)'\n",			     command_types[cmd->host_command_reg],			     cmd->host_command_reg);	}#endif	if (cmd->host_command_reg == HOST_COMPLETE)		priv->status |= STATUS_ENABLED;	if (cmd->host_command_reg == CARD_DISABLE)		priv->status &= ~STATUS_ENABLED;	priv->status &= ~STATUS_CMD_ACTIVE;	wake_up_interruptible(&priv->wait_command_queue);}#ifdef CONFIG_IPW_DEBUGstatic const char *frame_types[] = {	"COMMAND_STATUS_VAL",	"STATUS_CHANGE_VAL",	"P80211_DATA_VAL",	"P8023_DATA_VAL",	"HOST_NOTIFICATION_VAL"};#endifstatic inline int ipw2100_alloc_skb(struct ipw2100_priv *priv,				    struct ipw2100_rx_packet *packet){	packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx));	if (!packet->skb)		return -ENOMEM;	packet->rxp = (struct ipw2100_rx *)packet->skb->data;	packet->dma_addr = pci_map_single(priv->pci_dev, packet->skb->data,					  sizeof(struct ipw2100_rx),					  PCI_DMA_FROMDEVICE);	/* NOTE: pci_map_single does not return an error code, and 0 is a valid	 *       dma_addr */	return 0;}#define SEARCH_ERROR   0xffffffff#define SEARCH_FAIL    0xfffffffe#define SEARCH_SUCCESS 0xfffffff0#define SEARCH_DISCARD 0#define SEARCH_SNAPSHOT 1#define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff))static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv){	int i;	if (priv->snapshot[0])		return 1;	for (i = 0; i < 0x30; i++) {		priv->snapshot[i] = (u8 *) kmalloc(0x1000, GFP_ATOMIC);		if (!priv->snapshot[i]) {			IPW_DEBUG_INFO("%s: Error allocating snapshot "				       "buffer %d\n", priv->net_dev->name, i);			while (i > 0)				kfree(priv->snapshot[--i]);			priv->snapshot[0] = NULL;			return 0;		}	}	return 1;}static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv){	int i;	if (!priv->snapshot[0])		return;	for (i = 0; i < 0x30; i++)		kfree(priv->snapshot[i]);	priv->snapshot[0] = NULL;}static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,				    size_t len, int mode){	u32 i, j;	u32 tmp;	u8 *s, *d;	u32 ret;	s = in_buf;	if (mode == SEARCH_SNAPSHOT) {		if (!ipw2100_snapshot_alloc(priv))			mode = SEARCH_DISCARD;	}	for (ret = SEARCH_FAIL, i = 0; i < 0x30000; i += 4) {		read_nic_dword(priv->net_dev, i, &tmp);		if (mode == SEARCH_SNAPSHOT)			*(u32 *) SNAPSHOT_ADDR(i) = tmp;		if (ret == SEARCH_FAIL) {			d = (u8 *) & tmp;			for (j = 0; j < 4; j++) {				if (*s != *d) {					s = in_buf;					continue;				}				s++;				d++;				if ((s - in_buf) == len)					ret = (i + j) - len + 1;			}		} else if (mode == SEARCH_DISCARD)			return ret;	}	return ret;}/* * * 0) Disconnect the SKB from the firmware (just unmap) * 1) Pack the ETH header into the SKB * 2) Pass the SKB to the network stack * * When packet is provided by the firmware, it contains the following: * * .  ieee80211_hdr * .  ieee80211_snap_hdr * * The size of the constructed ethernet * */#ifdef CONFIG_IPW2100_RX_DEBUGstatic u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];#endifstatic inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i){#ifdef CONFIG_IPW_DEBUG_C3	struct ipw2100_status *status = &priv->status_queue.drv[i];	u32 match, reg;	int j;#endif#ifdef ACPI_CSTATE_LIMIT_DEFINED	int limit;#endif	IPW_DEBUG_INFO(": PCI latency error detected at 0x%04zX.\n",		       i * sizeof(struct ipw2100_status));#ifdef ACPI_CSTATE_LIMIT_DEFINED	IPW_DEBUG_INFO(": Disabling C3 transitions.\n");	limit = acpi_get_cstate_limit();	if (limit > 2) {		priv->cstate_limit = limit;		acpi_set_cstate_limit(2);		priv->config |= CFG_C3_DISABLED;	}#endif#ifdef CONFIG_IPW_DEBUG_C3	/* Halt the fimrware so we can get a good image */	write_register(priv->net_dev, IPW_REG_RESET_REG,		       IPW_AUX_HOST_RESET_REG_STOP_MASTER);	j = 5;	do {		udelay(IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY);		read_register(priv->net_dev, IPW_REG_RESET_REG, &reg);		if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)			break;	} while (j--);	match = ipw2100_match_buf(priv, (u8 *) status,				  sizeof(struct ipw2100_status),				  SEARCH_SNAPSHOT);	if (match < SEARCH_SUCCESS)		IPW_DEBUG_INFO("%s: DMA status match in Firmware at "			       "offset 0x%06X, length %d:\n",			       priv->net_dev->name, match,			       sizeof(struct ipw2100_status));	else		IPW_DEBUG_INFO("%s: No DMA status match in "			       "Firmware.\n", priv->net_dev->name);	printk_buf((u8 *) priv->status_queue.drv,		   sizeof(struct ipw2100_status) * RX_QUEUE_LENGTH);#endif	priv->fatal_error = IPW2100_ERR_C3_CORRUPTION;	priv->ieee->stats.rx_errors++;	schedule_reset(priv);}static inline void isr_rx(struct ipw2100_priv *priv, int i,			  struct ieee80211_rx_stats *stats){	struct ipw2100_status *status = &priv->status_queue.drv[i];	struct ipw2100_rx_packet *packet = &priv->rx_buffers[i];	IPW_DEBUG_RX("Handler...\n");	if (unlikely(status->frame_size > skb_tailroom(packet->skb))) {		IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!"			       "  Dropping.\n",			       priv->net_dev->name,			       status->frame_size, skb_tailroom(packet->skb));		priv->ieee->stats.rx_errors++;		return;	}	if (unlikely(!netif_running(priv->net_dev))) {		priv->ieee->stats.rx_errors++;		priv->wstats.discard.misc++;		IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");		return;	}#ifdef CONFIG_IPW2100_MONITOR	if (unlikely(priv->ieee->iw_mode == IW_MODE_MONITOR &&		     priv->config & CFG_CRC_CHECK &&		     status->flags & IPW_STATUS_FLAG_CRC_ERROR)) {		IPW_DEBUG_RX("CRC error in packet.  Dropping.\n");		priv->ieee->stats.rx_errors++;		return;	}#endif	if (unlikely(priv->ieee->iw_mode !

⌨️ 快捷键说明

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