hfa384x.c

来自「Linux的无线局域网方案是一个Linux设备驱动程序和子系统 一揽子方案的用」· C语言 代码 · 共 2,425 行 · 第 1/5 页

C
2,425
字号
	}	result = hfa384x_copy_from_bap( hw, hw->bap, rid, 0, &rec, sizeof(rec));	if ( result ) {		WLAN_LOG_DEBUG0(3,"Call to hfa384x_copy_from_bap failed\n");		goto fail;	}	/* Validate the record length */	if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) {  /* note body len calculation in bytes */		WLAN_LOG_DEBUG3(1,			"RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n",			rid, len, (hfa384x2host_16(rec.reclen)-1)*2);		result = -ENODATA;		goto fail;	}	result = hfa384x_copy_from_bap( hw, hw->bap, rid, sizeof(rec), buf, len);fail:	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_drvr_getconfig16** Performs the sequence necessary to read a 16 bit config/info item* and convert it to host order.** Arguments:*	hw		device structure*	rid		config/info record id (in host order)*	val		ptr to 16 bit buffer to receive value (in host order)** 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_getconfig16(hfa384x_t *hw, UINT16 rid, void *val){	int		result = 0;	DBFENTER;	result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16));	if ( result == 0 ) {		*((UINT16*)val) = hfa384x2host_16(*((UINT16*)val));	}	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_drvr_getconfig32** Performs the sequence necessary to read a 32 bit config/info item* and convert it to host order.** Arguments:*	hw		device structure*	rid		config/info record id (in host order)*	val		ptr to 32 bit buffer to receive value (in host order)** 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_getconfig32(hfa384x_t *hw, UINT16 rid, void *val){	int		result = 0;	DBFENTER;	result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32));	if ( result == 0 ) {		*((UINT32*)val) = hfa384x2host_32(*((UINT32*)val));	}	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_drvr_setconfig** Performs the sequence necessary to write a config/info item.** Arguments:*	hw		device structure*	rid		config/info record id (in host order)*	buf		host side record buffer*	len		buffer length (in bytes)** 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_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len){	int		result = 0;	hfa384x_rec_t	rec;	DBFENTER;	rec.rid = host2hfa384x_16(rid);	rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */	/* write the record header */	result = hfa384x_copy_to_bap( hw, hw->bap, rid, 0, &rec, sizeof(rec));	if ( result ) {		WLAN_LOG_DEBUG0(3,"Failure writing record header\n");		goto fail;	}	/* write the record data (if there is any) */	if ( len > 0 ) {		result = hfa384x_copy_to_bap( hw, hw->bap, rid, sizeof(rec), buf, len);		if ( result ) {			WLAN_LOG_DEBUG0(3,"Failure writing record data\n");			goto fail;		}	}	result = hfa384x_cmd_access( hw, 1, rid);fail:	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_drvr_setconfig16** Performs the sequence necessary to write a 16 bit config/info item.** Arguments:*	hw		device structure*	rid		config/info record id (in host order)*	val		16 bit value to store (in host order)** 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_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 *val){	int	result;	UINT16	value;	DBFENTER;	value = host2hfa384x_16(*val);	result = hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT16));	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_drvr_setconfig32** Performs the sequence necessary to write a 32 bit config/info item.** Arguments:*	hw		device structure*	rid		config/info record id (in host order)*	val		32 bit value to store (in host order)** 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_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 *val){	int	result;	UINT32	value;	DBFENTER;	value = host2hfa384x_32(*val);	result = hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT32));	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_drvr_readpda** Performs the sequence to read the PDA space.  Note there is no* drvr_writepda() function.  Writing a PDA is* generally implemented by a calling component via calls to * cmd_download and writing to the flash download buffer via the * aux regs.** Arguments:*	hw		device structure*	buf		buffer to store PDA in*	len		buffer length** Returns: *	0		success*	>0		f/w reported error - f/w status code*	<0		driver reported error*	-ETIMEOUT	timout waiting for the cmd regs to become*			available, or waiting for the control reg*			to indicate the Aux port is enabled.*	-ENODATA	the buffer does NOT contain a valid PDA.*			Either the card PDA is bad, or the auxdata*			reads are giving us garbage.** Side effects:** Call context:*	process thread or non-card interrupt.----------------------------------------------------------------*/int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len){	int		result = 0;	UINT16		*pda = buf;	int		pdaok = 0;	int		morepdrs = 1;	int		currpdr = 0;	/* word offset of the current pdr */	int		i;	UINT16		pdrlen;		/* pdr length in bytes, host order */	UINT16		pdrcode;	/* pdr code, host order */	UINT16		crc;	UINT16		pdacrc;	struct pdaloc {		UINT32	cardaddr;		UINT16	auxctl;	} pdaloc[] =	{		{ HFA3842_PDA_BASE,		HFA384x_AUX_CTL_NV},		{ HFA3842_PDA_BASE,		HFA384x_AUX_CTL_EXTDS},		{ HFA3841_PDA_BASE,		HFA384x_AUX_CTL_NV}, 		{ HFA3841_PDA_BASE,		HFA384x_AUX_CTL_EXTDS}, 		{ HFA3841_PDA_BOGUS_BASE,	HFA384x_AUX_CTL_NV}	};	DBFENTER;	/* Check for aux available */	result = hfa384x_cmd_aux_enable(hw);	if ( result ) {		WLAN_LOG_DEBUG1(1,"aux_enable() failed. result=%d\n", result);		goto failed;	}	/* Read the pda from each known address.  */	for ( i = 0; i < (sizeof(pdaloc)/sizeof(pdaloc[0])); i++) {		WLAN_LOG_DEBUG2( 3, "Checking PDA@(0x%08lx,%s)\n",			pdaloc[i].cardaddr,			pdaloc[i].auxctl == HFA384x_AUX_CTL_NV ?			"CTL_NV" : "CTL_EXTDS");		/* Copy bufsize bytes from our current pdaloc */		hfa384x_copy_from_aux(hw, 			pdaloc[i].cardaddr, 			pdaloc[i].auxctl, 			buf, 			len);		/* Test for garbage */		/* Traverse the PDR list Looking for PDA-END */		pdaok = 1;	/* intially assume good */		morepdrs = 1;		currpdr = 0;		while ( pdaok && morepdrs ) {			pdrlen = hfa384x2host_16(pda[currpdr]) * 2;			pdrcode = hfa384x2host_16(pda[currpdr+1]);							/* Test for completion at END record */			if ( pdrcode == HFA384x_PDR_END_OF_PDA ) {				if ( pdrlen == 4 ) { 					morepdrs = 0;					/* Calculate CRC-16 and compare to PDA					 * value.  Note the addition of 2 words					 * for ENDREC.len and ENDREC.code					 * fields.					 */					crc = hfa384x_mkcrc16( (UINT8*)pda, 						(currpdr + 2) * sizeof(UINT16));					pdacrc =hfa384x2host_16(pda[currpdr+2]);					if ( crc != pdacrc ) {						WLAN_LOG_DEBUG2(3,						"PDA crc failed:						calc_crc=0x%04x,						pdr_crc=0x%04x.\n",						crc, pdacrc);						pdaok = 0;					}				} else {					WLAN_LOG_DEBUG1(3, 					"END record detected w/ "					"len(%d) != 2, assuming bad PDA\n",					pdrlen);					pdaok = 0;				}				break;			}				/* Test the record length */			if ( pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) {				WLAN_LOG_DEBUG4(3,					"pdrlen for address #%d "					"at %#lx:%#x:%d\n",					i, pdaloc[i].cardaddr, 					pdaloc[i].auxctl, pdrlen);				WLAN_LOG_DEBUG1(3,"pdrlen invalid=%d\n", 					pdrlen);				pdaok = 0;				break;			}			/* Move to the next pdr */			if ( morepdrs ) {				/* note the access to pda[], we need words */				currpdr += hfa384x2host_16(pda[currpdr]) + 1;				if (currpdr*sizeof(UINT16) > len) {					WLAN_LOG_DEBUG0(3,					"Didn't find PDA_END in buffer, "					"trying next location.\n");					pdaok = 0;					break;				}			}		}			if ( pdaok ) {			WLAN_LOG_INFO2(				"PDA Read from 0x%08lx in %s space.\n",				pdaloc[i].cardaddr, 				pdaloc[i].auxctl == 0 ? "EXTDS" :				pdaloc[i].auxctl == 1 ? "NV" :				pdaloc[i].auxctl == 2 ? "PHY" :				pdaloc[i].auxctl == 3 ? "ICSRAM" : 				"<bogus auxctl>");			break;		} 	}	result = pdaok ? 0 : -ENODATA;	if ( result ) {		WLAN_LOG_DEBUG0(3,"Failure: pda is not okay\n");	}	hfa384x_cmd_aux_disable(hw);failed:	DBFEXIT;	return result;}/*----------------------------------------------------------------* mkpda_crc** Calculates the CRC16 for the given PDA and inserts the value* into the end record.** Arguments:*	pda	ptr to the PDA data structure.** Returns: *	0	- success *	~0	- failure (probably an errno)----------------------------------------------------------------*/static UINT16 hfa384x_mkcrc16(UINT8 *p, int len){	UINT16	crc = 0;	UINT8	*lim = p + len;	while (p < lim) {			crc = (crc >> 8 ) ^ crc16tab[(crc & 0xff) ^ *p++];	}	return crc;}/*----------------------------------------------------------------* hfa384x_drvr_ramdl_enable** Begins the ram download state.  Checks to see that we're not* already in a download state and that a port isn't enabled.* Sets the download state and calls cmd_download with the * ENABLE_VOLATILE subcommand and the exeaddr argument.** Arguments:*	hw		device structure*	exeaddr		the card execution address that will be *                       jumped to when ramdl_disable() is called*			(host order).** 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_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr){	int		result = 0;	UINT16		lowaddr;	UINT16		hiaddr;	int		i;	DBFENTER;	/* Check that a port isn't active */	for ( i = 0; i < HFA384x_PORTID_MAX; i++) {		if ( hw->port_enabled[i] ) {			WLAN_LOG_DEBUG0(1,"Can't download with a port enabled.\n");			return -EINVAL; 		}	}	/* Check that we're not already in a download state */	if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) {		WLAN_LOG_DEBUG0(1,"Download state not disabled.\n");		return -EINVAL;	}	/* Retrieve the buffer loc&size and timeout */	if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, 				&(hw->bufinfo), sizeof(hw->bufinfo))) ) {		return result;	}	hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page);	hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset);	hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len);	if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, 				&(hw->dltimeout))) ) {		return result;	}	hw->dltimeout = hfa384x2host_16(hw->dltimeout);#if 0WLAN_LOG_DEBUG1(1,"ramdl_enable, exeaddr=0x%08x\n", exeaddr);hw->dlstate = HFA384x_DLSTATE_RAMENABLED;#endif		/* Enable the aux port */	if ( (result = hfa384x_cmd_aux_enable(hw)) ) {		WLAN_LOG_DEBUG1(1,"Aux enable failed, result=%d.\n", result);		return result;	}	/* Call the download(1,addr) function */	lowaddr = HFA384x_ADDR_CMD_MKOFF(exeaddr);	hiaddr =  HFA384x_ADDR_CMD_MKPAGE(exeaddr);	result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_RAM, 			lowaddr, hiaddr, 0);

⌨️ 快捷键说明

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