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

📄 am930hw.c

📁 wlan_monitor monitor utility for wlan device
💻 C
📖 第 1 页 / 共 4 页
字号:
	timeout = jiffies + 500;	while(  read8(hw, hw->cmd + CMD_OFF_CODE) != 0 &&			read8(hw, hw->cmd + CMD_OFF_STATUS) == 0 &&			jiffies < timeout );	if ( jiffies >= timeout )	{		printk( KERN_DEBUG "Timed out waiting for f/w cmd byte available\n");		result.drvr_status = AM930HW_FWNOTREADY;	}	else	{		/* Make sure the status and code are set properly */		write8(hw, hw->cmd + CMD_OFF_CODE, 0);		write8(hw, hw->cmd + CMD_OFF_STATUS, 0);				/* copy the parms to the command block */		if ( parmsize != 0 )		{			writecard(hw, hw->cmd + CMD_OFF_PARMS, cmdparms, ABS(parmsize));		}		/* Tell the hw object that this cmd is the most recent */		hw->last_cmd = cmd;		/* set the command */		write8(hw, hw->cmd + CMD_OFF_CODE, cmd);		/* Now, wait for the result */		timeout = jiffies + 1500;		while ( read8(hw, hw->cmd + CMD_OFF_STATUS) == SUCMD_STAT_IDLE && 				jiffies < timeout );		/* Did we time out or did the fw finish with something? */		if ( jiffies >= timeout )		{			/* If we timed out, simply set the drvr status and return */			result.fw_status = read8(hw, hw->cmd + CMD_OFF_STATUS);			result.drvr_status = AM930HW_FWCMDTIMEOUT;			printk(KERN_DEBUG "We timed out on command: 0x%02x\n", 				hw->last_cmd);		}		else		{			/* The fw finished with something, what? */			if ( read8(hw, hw->cmd + CMD_OFF_STATUS) != SUCMD_STAT_CMPLT )			{				/* some error occurred, save the result and move on */				result.fw_status = read8(hw, hw->cmd + CMD_OFF_STATUS);				result.fw_err_off = read8(hw, hw->cmd + CMD_OFF_ERR_OFF);				printk(KERN_DEBUG "f/w cmd error, code=0x%x\n", 					result.fw_status);			}			else			{				/* Everything appears to be OK, now collect any results */				result.drvr_status = 0;				result.fw_status = read8(hw, hw->cmd + CMD_OFF_STATUS);				if ( parmsize < 0 )				{					readcard( hw, hw->cmd + CMD_OFF_PARMS, cmdparms, ABS(parmsize));				}			}			/* clear the cmd and status */			write8(hw, hw->cmd + CMD_OFF_CODE, 0);			write8(hw, hw->cmd + CMD_OFF_STATUS, 0);		}	}	DBFEXIT;	return result;} /*----------------------------------------------------------------*	am930hw_getset_int**	Attempts to access the sutro f/w control structure int_mask or*	int_status field of the given control/status block. It uses the*	lockout_fw and lockout_host fields to block the firmware from*	accessing the mask and status fields while we get or update*	them.**	action values:*		SU_GET_INTMASK1		get the interrupt mask*		SU_SET_INTMASK1		set the interrupt mask*		SU_GET_INTMASK2		get the interrupt mask*		SU_SET_INTMASK2		set the interrupt mask*		SU_GET_INTSTATUS1	get the interrupt status*		SU_GET_INTSTATUS1	get the interrupt status*		SU_SET_INTSTATUS2	set the interrupt status*		SU_SET_INTSTATUS2	set the interrupt status**	The value argument is only used by the SET actions.**	returns: -1 on failure, *			 0 or GET result on success----------------------------------------------------------------*/static UINT16 am930hw_getset_int( am930hw_t *hw, 								int action,								UINT8 mask,								UINT8 status ){	UINT16 result = 0;	DBFENTER;	if ( am930hw_lockint(hw) == 0 )	{		if (action & SU_GET_INTMASK1 )			result = read8(hw, hw->cs + CS_OFF_INT_MASK);		if ( action & SU_SET_INTMASK1 )			write8(hw, hw->cs + CS_OFF_INT_MASK, mask);		if (action & SU_GET_INTMASK2 )			result = read8(hw, hw->cs + CS_OFF_INT_MASK2);		if ( action & SU_SET_INTMASK2 )			write8(hw, hw->cs + CS_OFF_INT_MASK2, mask);		if ( action & SU_GET_INTSTATUS1 )			result = read8(hw, hw->cs + CS_OFF_INT_STATUS);		if ( action & SU_SET_INTSTATUS1 )			write8(hw, hw->cs + CS_OFF_INT_STATUS, status);		if ( action & SU_GET_INTSTATUS2 )			result = read8(hw, hw->cs + CS_OFF_INT_STATUS2);		if ( action & SU_SET_INTSTATUS2 )			write8(hw, hw->cs + CS_OFF_INT_STATUS2, status);		am930hw_unlockint(hw);	}	else	{		result = -1;	}	DBFEXIT;	return result;}/*----------------------------------------------------------------*	am930hw_init_rx_tx**	Performs the second part of the object initialization. We have*	to do this here so that all of the links are in place in the*	other objects. Particularly so that interrupts get routed to*	this object.**	returns: zero on success, non-zero on failure----------------------------------------------------------------*/int am930hw_init_rx_tx( am930hw_t *hw ){	int result = 0;	DBFENTER;	/* Configure the tx queues */	if ( am930hw_init_tx_queues(hw) != 0 )	{		result = 1;	}	else	{		/* Enable tx */		if ( am930hw_tx_enable(hw) != AM930HW_CMD_SUCCESS )		{			result = 2;		}		else		{			udelay(100);			/* Enable rx */			if ( am930hw_rx_enable(hw) != AM930HW_CMD_SUCCESS )			{				result = 3;			}			else			{				udelay(100);			}		}	}	DBFEXIT;	return result;}/*----------------------------------------------------------------*	am930hw_init_tx_queue**	Initialize the tx queue related data structures and members of*	the hw object.**	NOTE: this function takes care of am930 related queues, NOT*			any of the upper level protocol packet queues.**	returns: nothing----------------------------------------------------------------*/int am930hw_init_tx_queues( am930hw_t *hw){	int					result = 0;	int					i;	UINT32				curr_off;	am930tx_dataslot_t	ds;	DBFENTER;	/* From the MIB, find out where the TX queue is supposed to go */	if ( am930hw_mibgetitem( hw, LOC_TX_BUFFER_OFFSET, 			&(hw->tx_tail), sizeof(hw->tx_tail)) != AM930HW_CMD_SUCCESS )	{		DBPRT( DBFWCMD, "mibgetitem(LOC_TX_BUFFER_OFFSET) Failed!\n");		result = 1;	}	else	{		/* We've got the MIB, now init. the main queue */		hw->tx_base = hw->tx_tail;		curr_off = hw->tx_base;		memset( &ds.desc, 0, sizeof(am930tx_desc_t));		for ( i = 0; i < AM930_NTXDESC; i++)		{			/* first set the address where the next desc will go */			if ( i < AM930_NTXDESC - 1 )  				ds.desc.next = curr_off + sizeof(ds);			else				ds.desc.next = hw->tx_base;			/* write the descriptor */			writecard( hw, curr_off, &ds.desc, sizeof(ds.desc));			/* update the offset */			curr_off += sizeof(ds);		}	}		DBFEXIT;	return result;}/*----------------------------------------------------------------*	am930hw_ISR**	HW object interrupt service routine. Called when the pcmcia*	circuitry has generated a host interrupt in response to an*	interrupt from supposedly our card.**	returns: nothing----------------------------------------------------------------*/void am930hw_ISR( am930hw_t *hw ){	UINT8	int_status;	UINT8	int_mask;	UINT8	gcr;	/* Make sure the hw object is ready */	/*  - additional checks make sure the H/W is _really_ in the slot */	/*  - sometimes an int reaches here after a card is removed and before */	/*    card services has been notified. (Thanks David) */	if ( (hw != NULL) && 		 (hw->state & AM930HW_CONFIG) && 		 (hw->mac->di->state & DEV_PRESENT) && 		 read8(hw, hw->banner) == 'P' && read8(hw, hw->banner+1) == 'C')	{		/* Make sure we have not overlapped ISR calls */		if ( hw->state & AM930HW_INTOCURRED )		{			DBPRT( DBINT, "Overlapping Interrupt detected!\n");		}		else		{			hw->state |= AM930HW_INTOCURRED;			/* Lock the int fields */			if ( am930hw_lockint(hw) != 0 )			{				DBPRT( DBFWINT, 					"Unable to lockout f/w, skip interrupt\n");				/* Clear the ECWAIT bit of GCR (by setting...wierd) */				gcr = inb_p( GCR(hw));				gcr |= BIT3;				outb_p( gcr, GCR(hw));				/* Clear the int bit of the hw->state */				hw->state &= ~AM930HW_INTOCURRED;			}			else			{				/* save the int_mask for future restoration */				int_mask = read8( hw, hw->cs + CS_OFF_INT_MASK);				write8(hw, hw->cs + CS_OFF_INT_MASK, 0x0f);				int_status = read8(hw, hw->cs + CS_OFF_INT_STATUS);				write8(hw, hw->cs + CS_OFF_INT_STATUS, 0);				am930hw_unlockint(hw);DBPRT(DBFWINT, "Int mask=0x%02x, status=0x%02x\n", int_mask, int_status);				/* Handle various int sources */				do {					if ( SUCS_INT_IS_SCANCMPLT(int_status) )					{						am930hw_onint_scancomplete(hw);					}							if ( SUCS_INT_IS_TX(int_status) )					{						am930hw_onint_tx(hw);					}							if ( SUCS_INT_IS_RX(int_status) )					{						am930hw_onint_rx(hw);					}							if ( SUCS_INT_IS_CMD(int_status) )					{						am930hw_onint_cmdcomplete(hw);					}					/* Check the int status again, to see if more int events */					/*   have occurred */							if ( am930hw_lockint(hw) != 0 )					{						DBPRT( DBFWINT, "Unable to lockout f/w, 2nd time\n");						int_status = 0;					}					else					{						int_status = read8(hw, hw->cs + CS_OFF_INT_STATUS);						if ( int_status != 0 ) /* are we handling again? */						{							write8(hw, hw->cs + CS_OFF_INT_STATUS, 0);							am930hw_unlockint(hw);						}					}				}				while ( int_status != 0 );				/* Clear the ECWAIT bit of GCR (by setting...wierd) */				gcr = inb_p( GCR(hw));				gcr |= BIT3;				outb_p( gcr, GCR(hw));				/* Clear the int bit of the hw->state */				hw->state &= ~AM930HW_INTOCURRED;				/* set the int_mask to the setting it had on ISR entry */				write8(hw, hw->cs + CS_OFF_INT_MASK, int_mask);				/* and unlock! */				am930hw_unlockint(hw);			} /* endif lockint */		} /* endif !overlapped */	} /* hw OK, card in slot */	else	{		DBPRT( DBINT, "ISR called when hw is NULL, hw not CONFIG or "					"no card in slot, future ints may be lost!\n");	}	return;}/*----------------------------------------------------------------*	am930hw_joinbss**	I/F function used by mac and mgr to join a specific bss. The*	only nod here to the sutro implementation is the sutro_ref_time*	argument used by the sutro to update it's internal timers.**	returns: AM930HW_SUCCESS or*			 AM930HW_FAILURE----------------------------------------------------------------*/UINT32 am930hw_joinbss( am930hw_t *hw, UINT32 ch, UINT32 newBSS, 						UINT48 bssid, char *ssid, UINT32 bcn_int,						wlan_bss_ts_t ts, UINT32 sutro_ref_time ){	UINT32 				result = AM930HW_SUCCESS;	su_mib_mac_mgmt_t	mm_mib;	DBFENTER;	/* retrieve the mib */	if ( am930hw_mibget(hw, SUMIB_MGMT, 0, 				sizeof(mm_mib), &mm_mib) != AM930HW_SUCCESS )	{		result = AM930HW_FAILURE;	}	else	{		/* set the bssid */		memcpy( mm_mib.current_bssid, bssid, WLAN_ADDR_LEN );		/* set the ssid */		mm_mib.current_essid[0] = WLAN_IE_SSID;		mm_mib.current_essid[1] = strlen(ssid);		strcpy( &(mm_mib.current_essid[2]), ssid);		/* set the beaconrate */		mm_mib.beacon_period = bcn_int;		/* save the mib */		if ( am930hw_mibset(hw, SUMIB_MGMT, 0, 					sizeof(mm_mib), &mm_mib) != AM930HW_SUCCESS )		{			result = AM930HW_FAILURE;		}		else		{			DBPRT( DBFWCMD, 				"Syncing with BSS, ch=%d, newbss=%d\n", 				(int)ch, (int)newBSS);			/* send the sync command */			if ( am930hw_sync( hw, 								ch, 								newBSS, 								(newBSS == 0) ? ts : NULL, 								sutro_ref_time ) != AM930HW_CMD_SUCCESS )			{				result = AM930HW_FAILURE;			}		}	}	DBFEXIT;	return result;}/*----------------------------------------------------------------*	am930hw_onint_cmdcomplete**	ISR helper for f/w generated scan complete interrupts**	returns: nothing----------------------------------------------------------------*/void am930hw_onint_cmdcomplete( am930hw_t *hw ){	DBPRT( (DBFWINT | DBFWCMD), 		"cmd complete int, last_cmd= 0x%x\n", hw->last_cmd)	hw->last_cmd = 0;}/*----------------------------------------------------------------*	am930hw_onint_rx**	ISR helper for f/w generated rx complete interrupts**	returns: nothing----------------------------------------------------------------*/void am930hw_onint_rx( am930hw_t *hw ){	UINT8 			old_state;	UINT32			old_head;	UINT32 			next;	UINT32			len;	UINT32			data_off;	UINT8 			state;	am930rxfrm_t	*frm;	DBPRT( (DBFWINT | DBRXPATH), "RX Interrupt.\n");  /* print initial rx_desc *//*#ifdef DBMSG_ENABLED	if ( (dbmask & FILEBIT) && (dbmask & 0))	{		am930rx_desc_t	desc;		readcard(hw, hw->rx_head, &desc, sizeof(desc));		am930hw_dbprintRXdesc( &desc );	}#endif*/	/* read the state and next fields from the old head */	state = read8(hw, hw->rx_head + RXD_OFF_STATE);	next = am930hw_read_rxnext(hw);	while ( !SURXD_ST_IS_FWOWN(state) &&			SURXD_ST_IS_CONSUMED(state) &&			!SURXD_ISLAST(next) &&			((next&0x0000ffffL) >= hw->rx_base && 			 (next&0x0000ffffL) < (hw->rx_base+hw->rx_len)) )	{		/* we've got a valid next ptr, it's time to move on */			old_head = hw->rx_head;		old_state = state;		hw->rx_head = next & 0x0000ffffL;		state = read8( hw, hw->rx_head + RXD_OFF_STATE);		/* make sure we own the new descriptor */		if ( SURXD_ST_IS_FWOWN(state) )		{			/* we've been handed a desc that's still owned by the f/w */			/*  set the head back to the old one, and stop the loop */			hw->rx_head = old_head;			break;		}		else		{			/* we have a new, valid descriptor...process it */

⌨️ 快捷键说明

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