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

📄 hfa384x.c

📁 uClinux2.6上兼容PRISM2.0芯片组的USB设备驱动程序.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*----------------------------------------------------------------* hfa384x_cmd_aux_enable** Goes through the process of enabling the auxilary port.  This * is necessary prior to raw reads/writes to card data space.  * Direct access to the card data space is only used for downloading* code and debugging.* Note that a call to this function is required before attempting* a download.** Arguments:*	hw		device structure** Returns: *	0		success*	>0		f/w reported failure - f/w status code*	<0		driver reported error (timeout)** Side effects:** Call context:*	process thread ----------------------------------------------------------------*/int hfa384x_cmd_aux_enable(hfa384x_t *hw, int force){	int		result = -ETIMEDOUT;	unsigned long	flags;	UINT32		retries_remaining;	UINT16		reg;	UINT		auxen_mirror = hw->auxen;	DBFENTER;	/* Check for existing enable */	if ( hw->auxen ) {		hw->auxen++;		return 0;	}	/* acquire the lock */	spin_lock_irqsave( &(hw->cmdlock), flags);	/* wait for cmd register busy bit to clear */	retries_remaining = 100000;	do {		reg = hfa384x_getreg(hw, HFA384x_CMD);		udelay(10);	}	while (HFA384x_CMD_ISBUSY(reg) && --retries_remaining);	if (retries_remaining != 0) {		/* busy bit clear, it's OK to write to ParamX regs */		hfa384x_setreg(hw, HFA384x_AUXPW0,			HFA384x_PARAM0);		hfa384x_setreg(hw, HFA384x_AUXPW1,			HFA384x_PARAM1);		hfa384x_setreg(hw, HFA384x_AUXPW2,			HFA384x_PARAM2);		/* Set the aux enable in the Control register */		hfa384x_setreg(hw, HFA384x_CONTROL_AUX_DOENABLE, 			HFA384x_CONTROL);		/* Now wait for completion */		retries_remaining = 100000;		do {			reg = hfa384x_getreg(hw, HFA384x_CONTROL);			udelay(10);		}		while ( ((reg & (BIT14|BIT15)) != HFA384x_CONTROL_AUX_ISENABLED) &&			--retries_remaining );		if (retries_remaining != 0) {			result = 0;			hw->auxen++;		}	}	/* Force it enabled even if the command failed, if told.. */	if ((hw->auxen == auxen_mirror) && force)		hw->auxen++;	spin_unlock_irqrestore( &(hw->cmdlock), flags);	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_cmd_aux_disable** Goes through the process of disabling the auxilary port * enabled with aux_enable().** Arguments:*	hw		device structure** Returns: *	0		success*	>0		f/w reported failure - f/w status code*	<0		driver reported error (timeout)** Side effects:** Call context:*	process thread ----------------------------------------------------------------*/int hfa384x_cmd_aux_disable(hfa384x_t *hw){	int		result = -ETIMEDOUT;	unsigned long   timeout;	UINT16		reg = 0;	DBFENTER;	/* See if there's more than one enable */	if (hw->auxen) hw->auxen--;	if (hw->auxen) return 0;	/* Clear the aux enable in the Control register */	hfa384x_setreg(hw, 0, HFA384x_PARAM0);	hfa384x_setreg(hw, 0, HFA384x_PARAM1);	hfa384x_setreg(hw, 0, HFA384x_PARAM2);	hfa384x_setreg(hw, HFA384x_CONTROL_AUX_DODISABLE, 		HFA384x_CONTROL);	/* Now wait for completion */	timeout = jiffies + 1*HZ;	reg = hfa384x_getreg(hw, HFA384x_CONTROL);	while ( ((reg & (BIT14|BIT15)) != HFA384x_CONTROL_AUX_ISDISABLED) &&		time_before(jiffies,timeout) ){		udelay(10);		reg = hfa384x_getreg(hw, HFA384x_CONTROL);	}	if ((reg & (BIT14|BIT15)) == HFA384x_CONTROL_AUX_ISDISABLED ) {		result = 0;	}	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_drvr_low_level** Write test commands to the card.  Some test commands don't make* sense without prior set-up.  For example, continous TX isn't very* useful until you set the channel.  That functionality should be** Side effects:** Call context:*      process thread * -----------------------------------------------------------------*/int hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd){	int             result = 0;	DBFENTER;		/* Do i need a host2hfa... conversion ? */#if 0	printk(KERN_INFO "%#x %#x %#x %#x\n", cmd->cmd, cmd->parm0, cmd->parm1, cmd->parm2);#endif	spin_lock_bh(&hw->cmdlock);	result = hfa384x_docmd_wait(hw, cmd);	spin_unlock_bh(&hw->cmdlock);	DBFEXIT;	return result;}/* TODO: determine if these will ever be needed */#if 0int hfa384x_cmd_readmif(hfa384x_t *hw){	DBFENTER;	DBFEXIT;	return 0;}int hfa384x_cmd_writemif(hfa384x_t *hw){	DBFENTER;	DBFEXIT;	return 0;}#endif/*----------------------------------------------------------------* hfa384x_drvr_mmi_read** Read mmi registers.  mmi is intersil-speak for the baseband* processor registers.** Arguments:*       hw              device structure*       register        The test register to be accessed (must be even #).** Returns:*       0               success*       >0              f/w reported error - f/w status code*       <0              driver reported error** Side effects:** Call context:*       process thread----------------------------------------------------------------*/int hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 addr, UINT32 *resp){        int             result = 0;	hfa384x_metacmd_t cmd;        DBFENTER;	cmd.cmd = (UINT16) 0x30;	cmd.parm0 = (UINT16) addr;	cmd.parm1 = 0;	cmd.parm2 = 0;        /* Do i need a host2hfa... conversion ? */	spin_lock_bh(&hw->cmdlock);	result = hfa384x_docmd_wait(hw, &cmd);	spin_unlock_bh(&hw->cmdlock);	*resp = (UINT32) cmd.result.resp0;        DBFEXIT;        return result;}/*----------------------------------------------------------------* hfa384x_drvr_mmi_write** Read mmi registers.  mmi is intersil-speak for the baseband* processor registers.** Arguments:*       hw              device structure*       addr            The test register to be accessed (must be even #).*       data            The data value to write to the register.** Returns:*       0               success*       >0              f/w reported error - f/w status code*       <0              driver reported error** Side effects:** Call context:*       process thread----------------------------------------------------------------*/inthfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 addr, UINT32 data){        int             result = 0;	hfa384x_metacmd_t cmd;        DBFENTER;	cmd.cmd = (UINT16) 0x31;	cmd.parm0 = (UINT16) addr;	cmd.parm1 = (UINT16) data;	cmd.parm2 = 0;        WLAN_LOG_DEBUG(1,"mmi write : addr = 0x%08x\n", addr);        WLAN_LOG_DEBUG(1,"mmi write : data = 0x%08x\n", data);        /* Do i need a host2hfa... conversion ? */	spin_lock_bh(&hw->cmdlock);	result = hfa384x_docmd_wait(hw, &cmd);	spin_unlock_bh(&hw->cmdlock);        DBFEXIT;        return result;}/* TODO: determine if these will ever be needed */#if 0int hfa384x_cmd_readmif(hfa384x_t *hw){        DBFENTER;        DBFEXIT;        return 0;}int hfa384x_cmd_writemif(hfa384x_t *hw){        DBFENTER;        DBFEXIT;        return 0;}#endif/*----------------------------------------------------------------* hfa384x_copy_from_bap** Copies a collection of bytes from the MAC controller memory via* one set of BAP registers.** Arguments:*	hw		device structure*	bap		[0|1] which BAP to use*	id		FID or RID, destined for the select register (host order)*	offset		An _even_ offset into the buffer for the given*			FID/RID.  We haven't the means to validate this,*			so be careful. (host order)*	buf		ptr to array of bytes*	len		length of data to transfer in bytes** Returns: *	0		success*	>0		f/w reported failure - value of offset reg.*	<0		driver reported error (timeout|bad arg)** Side effects:** Call context:*	process thread*	interrupt----------------------------------------------------------------*/int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset,				void *buf, UINT len){	int		result = 0;	unsigned long	flags = 0;	UINT8		*d = (UINT8*)buf;	UINT		selectreg;	UINT		offsetreg;	UINT		datareg;	UINT		i;	UINT16		reg = 0;	DBFENTER;	/* Validate bap, offset, buf, and len */	if ( (bap > 1) || 	     (offset > HFA384x_BAP_OFFSET_MAX) || 	     (offset % 2) ||	     (buf == NULL) ||	     (len > HFA384x_BAP_DATALEN_MAX) ){	     	result = -EINVAL;	} else {		selectreg = (bap == 1) ?  HFA384x_SELECT1 : HFA384x_SELECT0 ;		offsetreg = (bap == 1) ?  HFA384x_OFFSET1 : HFA384x_OFFSET0 ;		datareg =   (bap == 1) ?  HFA384x_DATA1 : HFA384x_DATA0 ;		/* Obtain lock */		spin_lock_irqsave( &(hw->baplock), flags);				/* Write id to select reg */		hfa384x_setreg(hw, id, selectreg);		/* Write offset to offset reg */		hfa384x_setreg(hw, offset, offsetreg);		/* Wait for offset[busy] to clear (see BAP_TIMEOUT) */		i = 0; 		do {			reg = hfa384x_getreg(hw, offsetreg);			if ( i > 0 ) udelay(10);			i++;		} while ( i < prism2_bap_timeout && HFA384x_OFFSET_ISBUSY(reg));#if (WLAN_HOSTIF != WLAN_PCI)		/* Release lock */		spin_unlock_irqrestore( &(hw->baplock), flags);#endif		if ( HFA384x_OFFSET_ISBUSY(reg) ){			/* If timeout, return -ETIMEDOUT */			result = reg;		} else if ( HFA384x_OFFSET_ISERR(reg) ){			/* If offset[err] == 1, return -EINVAL */			result = reg;		} else {			/* Read even(len) buf contents from data reg */			for ( i = 0; i < (len & 0xfffe); i+=2 ) {				*(UINT16*)(&(d[i])) = 					hfa384x_getreg_noswap(hw, datareg);			}			/* If len odd, handle last byte */			if ( len % 2 ){				reg = hfa384x_getreg_noswap(hw, datareg);				d[len-1] = ((UINT8*)(&reg))[0];			}		}		/* According to Intersil errata dated 9/16/02:			"In PRISM PCI MAC host interface, if both BAPs are concurrently 		 requesing memory access, both will accept the Ack.   There is no		 firmware workaround possible.  To prevent BAP access failures or		 hang conditions the host MUST NOT access both BAPs in sucession		 unless at least 5us elapses between accesses.  The safest choice		 is to USE ONLY ONE BAP for all data movement operations."			 What this means:			 We have to serialize ALL BAP accesses, and furthermore, add a 5us		 delay after access if we're using a PCI platform.			 Unfortunately, this means we have to lock out interrupts througout		 the entire BAP copy.			 It remains to be seen if "BAP access" means "BAP setup" or the more		 literal definition of "copying data back and forth"  I'm erring for		 the latter, safer definition.  -- SLP.			*/#if (WLAN_HOSTIF == WLAN_PCI)		udelay(5);		/* Release lock */		spin_unlock_irqrestore( &(hw->baplock), flags);#endif	}	if (result) {	  WLAN_LOG_DEBUG(1, 			  "copy_from_bap(0x%04x, 0, %d) failed, result=0x%x\n", 			  reg, len, result);	}	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_copy_to_bap** Copies a collection of bytes to the MAC controller memory via* one set of BAP registers.** Arguments:*	hw		device structure*	bap		[0|1] which BAP to use*	id		FID or RID, destined for the select register (host order)*	offset		An _even_ offset into the buffer for the given*			FID/RID.  We haven't the means to validate this,*			so be careful. (host order)*	buf		ptr to array of bytes*	len		length of data to transfer (in bytes)** Returns: *	0		success*	>0		f/w reported failure - value of offset reg.*	<0		driver reported error (timeout|bad arg)** Side effects:** Call context:*	process thread*	interrupt----------------------------------------------------------------*/int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset,				void *buf, UINT len){	return hfa384x_copy_to_bap4(hw, bap, id, offset, buf, len, NULL, 0, NULL, 0, NULL, 0);}int hfa384x_copy_to_bap4(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset,			 void *buf, UINT len1, void* buf2, UINT len2,			 void *buf3, UINT len3, void *buf4, UINT len4){	int		result = 0;	unsigned long	flags = 0;	UINT8		*d;	UINT		selectreg;	UINT		offsetreg;	UINT		datareg;	UINT		i;	UINT16		reg;	DBFENTER;//	printk(KERN_DEBUG "ctb1 %d id %04x o %d %d %d %d %d\n", bap, id, offset, len1, len2, len3, len4);	/* Validate bap, offset, buf, and len */	if ( (bap > 1) || 	     (offset > HFA384x_BAP_OFFSET_MAX) || 	     (offset % 2) ||	     (buf == NULL) ||	     (len1+len2+len3+l

⌨️ 快捷键说明

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