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

📄 hostap_hw.c

📁 IEEE 802.11a/b/g linux2.4/2.6 驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		printk(KERN_DEBUG "%s: hfa384x_cmd: command was not "		       "completed (res=%d, entry=%p, type=%d, cmd=0x%04x, "		       "param0=0x%04x, EVSTAT=%04x INTEN=%04x)\n", dev->name,		       res, entry, entry->type, entry->cmd, entry->param0, reg,		       HFA384X_INW(HFA384X_INTEN_OFF));		if (reg & HFA384X_EV_CMD) {			/* Command completion event is pending, but the			 * interrupt was not delivered - probably an issue			 * with pcmcia-cs configuration. */			printk(KERN_WARNING "%s: interrupt delivery does not "			       "seem to work\n", dev->name);		}		prism2_io_debug_error(dev, 3);		res = -ETIMEDOUT;		goto done;	}	if (resp0 != NULL)		*resp0 = entry->resp0;#ifndef final_version	if (entry->res) {		printk(KERN_DEBUG "%s: CMD=0x%04x => res=0x%02x, "		       "resp0=0x%04x\n",		       dev->name, cmd, entry->res, entry->resp0);	}#endif /* final_version */	res = entry->res; done:	hostap_cmd_queue_free(local, entry, 1);	return res;}/** * hfa384x_cmd_callback - Issue a Prism2 command; callback when completed * @dev: pointer to net_device * @cmd: Prism2 command code (HFA384X_CMD_CODE_*) * @param0: value for Param0 register * @callback: command completion callback function (%NULL = no callback) * @context: context data to be given to the callback function * * Issue given command (possibly after waiting in command queue) and use * callback function to indicate command completion. This can be called both * from user and interrupt context. The callback function will be called in * hardware IRQ context. It can be %NULL, when no function is called when * command is completed. */static int hfa384x_cmd_callback(struct net_device *dev, u16 cmd, u16 param0,				void (*callback)(struct net_device *dev,						 long context, u16 resp0,						 u16 status),				long context){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	int issue, ret;	unsigned long flags;	struct hostap_cmd_queue *entry;	if (local->cmd_queue_len >= HOSTAP_CMD_QUEUE_MAX_LEN + 2) {		printk(KERN_DEBUG "%s: hfa384x_cmd: cmd_queue full\n",		       dev->name);		return -1;	}	entry = (struct hostap_cmd_queue *)		kmalloc(sizeof(*entry), GFP_ATOMIC);	if (entry == NULL) {		printk(KERN_DEBUG "%s: hfa384x_cmd_callback - kmalloc "		       "failed\n", dev->name);		return -ENOMEM;	}	memset(entry, 0, sizeof(*entry));	atomic_set(&entry->usecnt, 1);	entry->type = CMD_CALLBACK;	entry->cmd = cmd;	entry->param0 = param0;	entry->callback = callback;	entry->context = context;	spin_lock_irqsave(&local->cmdlock, flags);	issue = list_empty(&local->cmd_queue);	if (issue)		entry->issuing = 1;	list_add_tail(&entry->list, &local->cmd_queue);	local->cmd_queue_len++;	spin_unlock_irqrestore(&local->cmdlock, flags);	if (issue && hfa384x_cmd_issue(dev, entry))		ret = -ETIMEDOUT;	else		ret = 0;	hostap_cmd_queue_free(local, entry, ret);	return ret;}/** * __hfa384x_cmd_no_wait - Issue a Prism2 command (private) * @dev: pointer to net_device * @cmd: Prism2 command code (HFA384X_CMD_CODE_*) * @param0: value for Param0 register * @io_debug_num: I/O debug error number * * Shared helper function for hfa384x_cmd_wait() and hfa384x_cmd_no_wait(). */static int __hfa384x_cmd_no_wait(struct net_device *dev, u16 cmd, u16 param0,				 int io_debug_num){	int tries;	u16 reg;	/* wait until busy bit is clear; this should always be clear since the	 * commands are serialized */	tries = HFA384X_CMD_BUSY_TIMEOUT;	while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) {		tries--;		udelay(1);	}	if (tries == 0) {		reg = HFA384X_INW(HFA384X_CMD_OFF);		prism2_io_debug_error(dev, io_debug_num);		printk(KERN_DEBUG "%s: __hfa384x_cmd_no_wait(%d) - timeout - "		       "reg=0x%04x\n", dev->name, io_debug_num, reg);		return -ETIMEDOUT;	}	/* write command */	HFA384X_OUTW(param0, HFA384X_PARAM0_OFF);	HFA384X_OUTW(cmd, HFA384X_CMD_OFF);	return 0;}/** * hfa384x_cmd_wait - Issue a Prism2 command and busy wait for completion * @dev: pointer to net_device * @cmd: Prism2 command code (HFA384X_CMD_CODE_*) * @param0: value for Param0 register */static int hfa384x_cmd_wait(struct net_device *dev, u16 cmd, u16 param0){	int res, tries;	u16 reg;	res = __hfa384x_cmd_no_wait(dev, cmd, param0, 4);	if (res)		return res;        /* wait for command completion */	if ((cmd & HFA384X_CMDCODE_MASK) == HFA384X_CMDCODE_DOWNLOAD)		tries = HFA384X_DL_COMPL_TIMEOUT;	else		tries = HFA384X_CMD_COMPL_TIMEOUT;        while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD) &&               tries > 0) {                tries--;                udelay(10);        }        if (tries == 0) {                reg = HFA384X_INW(HFA384X_EVSTAT_OFF);		prism2_io_debug_error(dev, 5);                printk(KERN_DEBUG "%s: hfa384x_cmd_wait - timeout2 - "		       "reg=0x%04x\n", dev->name, reg);                return -ETIMEDOUT;        }        res = (HFA384X_INW(HFA384X_STATUS_OFF) &               (BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) |                BIT(8))) >> 8;#ifndef final_version	if (res) {		printk(KERN_DEBUG "%s: CMD=0x%04x => res=0x%02x\n",		       dev->name, cmd, res);	}#endif	HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);	return res;}/** * hfa384x_cmd_no_wait - Issue a Prism2 command; do not wait for completion * @dev: pointer to net_device * @cmd: Prism2 command code (HFA384X_CMD_CODE_*) * @param0: value for Param0 register */static inline int hfa384x_cmd_no_wait(struct net_device *dev, u16 cmd,				      u16 param0){	return __hfa384x_cmd_no_wait(dev, cmd, param0, 6);}/** * prism2_cmd_ev - Prism2 command completion event handler * @dev: pointer to net_device * * Interrupt handler for command completion events. Called by the main * interrupt handler in hardware IRQ context. Read Resp0 and status registers * from the hardware and ACK the event. Depending on the issued command type * either wake up the sleeping process that is waiting for command completion * or call the callback function. Issue the next command, if one is pending. */static void prism2_cmd_ev(struct net_device *dev){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	struct hostap_cmd_queue *entry = NULL;	spin_lock(&local->cmdlock);	if (!list_empty(&local->cmd_queue)) {		entry = list_entry(local->cmd_queue.next,				   struct hostap_cmd_queue, list);		atomic_inc(&entry->usecnt);		list_del_init(&entry->list);		local->cmd_queue_len--;		if (!entry->issued) {			printk(KERN_DEBUG "%s: Command completion event, but "			       "cmd not issued\n", dev->name);			__hostap_cmd_queue_free(local, entry, 1);			entry = NULL;		}	}	spin_unlock(&local->cmdlock);	if (!entry) {		HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);		printk(KERN_DEBUG "%s: Command completion event, but no "		       "pending commands\n", dev->name);		return;	}	entry->resp0 = HFA384X_INW(HFA384X_RESP0_OFF);	entry->res = (HFA384X_INW(HFA384X_STATUS_OFF) &		      (BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) |		       BIT(9) | BIT(8))) >> 8;	HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);	/* TODO: rest of the CmdEv handling could be moved to tasklet */	if (entry->type == CMD_SLEEP) {		entry->type = CMD_COMPLETED;		wake_up_interruptible(&entry->compl);	} else if (entry->type == CMD_CALLBACK) {		if (entry->callback)			entry->callback(dev, entry->context, entry->resp0,					entry->res);	} else {		printk(KERN_DEBUG "%s: Invalid command completion type %d\n",		       dev->name, entry->type);	}	hostap_cmd_queue_free(local, entry, 1);	/* issue next command, if pending */	entry = NULL;	spin_lock(&local->cmdlock);	if (!list_empty(&local->cmd_queue)) {		entry = list_entry(local->cmd_queue.next,				   struct hostap_cmd_queue, list);		if (entry->issuing) {			/* hfa384x_cmd() has already started issuing this			 * command, so do not start here */			entry = NULL;		}		if (entry)			atomic_inc(&entry->usecnt);	}	spin_unlock(&local->cmdlock);	if (entry) {		/* issue next command; if command issuing fails, remove the		 * entry from cmd_queue */		int res = hfa384x_cmd_issue(dev, entry);		spin_lock(&local->cmdlock);		__hostap_cmd_queue_free(local, entry, res);		spin_unlock(&local->cmdlock);	}}static inline int hfa384x_wait_offset(struct net_device *dev, u16 o_off){	int tries = HFA384X_BAP_BUSY_TIMEOUT;	int res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY;	while (res && tries > 0) {		tries--;		udelay(1);		res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY;	}	return res;}/* Offset must be even */static int hfa384x_setup_bap(struct net_device *dev, u16 bap, u16 id,			     int offset){	u16 o_off, s_off;	int ret = 0;	if (offset % 2 || bap > 1)		return -EINVAL;	if (bap == BAP1) {		o_off = HFA384X_OFFSET1_OFF;		s_off = HFA384X_SELECT1_OFF;	} else {		o_off = HFA384X_OFFSET0_OFF;		s_off = HFA384X_SELECT0_OFF;	}	if (hfa384x_wait_offset(dev, o_off)) {		prism2_io_debug_error(dev, 7);		printk(KERN_DEBUG "%s: hfa384x_setup_bap - timeout before\n",		       dev->name);		ret = -ETIMEDOUT;		goto out;	}	HFA384X_OUTW(id, s_off);	HFA384X_OUTW(offset, o_off);	if (hfa384x_wait_offset(dev, o_off)) {		prism2_io_debug_error(dev, 8);		printk(KERN_DEBUG "%s: hfa384x_setup_bap - timeout after\n",		       dev->name);		ret = -ETIMEDOUT;		goto out;	}#ifndef final_version	if (HFA384X_INW(o_off) & HFA384X_OFFSET_ERR) {		prism2_io_debug_error(dev, 9);		printk(KERN_DEBUG "%s: hfa384x_setup_bap - offset error "		       "(%d,0x04%x,%d); reg=0x%04x\n",		       dev->name, bap, id, offset, HFA384X_INW(o_off));		ret = -EINVAL;	}#endif out:	return ret;}static int hfa384x_get_rid(struct net_device *dev, u16 rid, void *buf, int len,			   int exact_len){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	int res, rlen = 0;	struct hfa384x_rid_hdr rec;	if (local->no_pri) {		printk(KERN_DEBUG "%s: cannot get RID %04x (len=%d) - no PRI "		       "f/w\n", dev->name, rid, len);		return -ENOTTY; /* Well.. not really correct, but return				 * something unique enough.. */	}	if ((local->func->card_present && !local->func->card_present(local)) ||	    local->hw_downloading)		return -ENODEV;	res = down_interruptible(&local->rid_bap_sem);	if (res)		return res;	res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS, rid, NULL, NULL);	if (res) {		printk(KERN_DEBUG "%s: hfa384x_get_rid: CMDCODE_ACCESS failed "		       "(res=%d, rid=%04x, len=%d)\n",		       dev->name, res, rid, len);		up(&local->rid_bap_sem);		return res;	}	spin_lock_bh(&local->baplock);	res = hfa384x_setup_bap(dev, BAP0, rid, 0);	if (!res)		res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec));	if (le16_to_cpu(rec.len) == 0) {		/* RID not available */		res = -ENODATA;	}	rlen = (le16_to_cpu(rec.len) - 1) * 2;	if (!res && exact_len && rlen != len) {		printk(KERN_DEBUG "%s: hfa384x_get_rid - RID len mismatch: "		       "rid=0x%04x, len=%d (expected %d)\n",		       dev->name, rid, rlen, len);		res = -ENODATA;	}	if (!res)		res = hfa384x_from_bap(dev, BAP0, buf, len);	spin_unlock_bh(&local->baplock);	up(&local->rid_bap_sem);	if (res) {		if (res != -ENODATA)			printk(KERN_DEBUG "%s: hfa384x_get_rid (rid=%04x, "			       "len=%d) - failed - res=%d\n", dev->name, rid,			       len, res);		if (res == -ETIMEDOUT)			prism2_hw_reset(dev);		return res;	}	return rlen;}static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len){	struct hostap_interface *iface = dev->priv;	local_info_t *local = iface->local;	struct hfa384x_rid_hdr rec;	int res;	if (local->no_pri) {		printk(KERN_DEBUG "%s: cannot set RID %04x (len=%d) - no PRI "		       "f/w\n", dev->name, rid, len);		return -ENOTTY; /* Well.. not really correct, but return				 * something unique enough.. */	}	if ((local->func->card_present && !local->func->card_present(local)) ||	    local->hw_downloading)		return -ENODEV;	rec.rid = cpu_to_le16(rid);	/* RID len in words and +1 for rec.rid */	rec.len = cpu_to_le16(len / 2 + len % 2 + 1);	res = down_interruptible(&local->rid_bap_sem);	if (res)		return res;	spin_lock_bh(&local->baplock);	res = hfa384x_setup_bap(dev, BAP0, rid, 0);	if (!res)		res = hfa384x_to_bap(dev, BAP0, &rec, sizeof(rec));	if (!res)		res = hfa384x_to_bap(dev, BAP0, buf, len);	spin_unlock_bh(&local->baplock);	if (res) {		printk(KERN_DEBUG "%s: hfa384x_set_rid (rid=%04x, len=%d) - "		       "failed - res=%d\n", dev->name, rid, len, res);		up(&local->rid_bap_sem);

⌨️ 快捷键说明

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