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

📄 am930hw.c

📁 Linux Wireless LAN Project 的目标是开发一个完整的
💻 C
📖 第 1 页 / 共 5 页
字号:
				/* Clear the int bit of the hw->state */				hw->state &= ~AM930HW_INTOCURRED;			}			else			{				/* save the int_mask for future restoration */				int_mask1 = read8( hw, hw->cs + CS_OFF_INT_MASK);				int_mask2 = read8( hw, hw->cs + CS_OFF_INT_MASK2);				write8(hw, hw->cs + CS_OFF_INT_MASK, 0xff);				write8(hw, hw->cs + CS_OFF_INT_MASK2, 0xff);				int_status1 = read8(hw, hw->cs + CS_OFF_INT_STATUS);				int_status2 = read8(hw, hw->cs + CS_OFF_INT_STATUS2);				write8(hw, hw->cs + CS_OFF_INT_STATUS, 0);				write8(hw, hw->cs + CS_OFF_INT_STATUS2, 0);				am930hw_unlockint(hw);				WLAN_LOG_DEBUG2(4,"Int mask=0x%02x, status=0x%02x\n", int_mask1, int_status1);				/* Handle various int sources */				if ( int_status1 == 0 )				{					WLAN_LOG_DEBUG0(1,"in ISR, int_status1 == 0\n");				}				do {					handled++;					if ( SUCS_INT_IS_RX(int_status1) )					{						#if (WLAN_OS == WLAN_LWOS)							LED_Blink( WIRELESS_DATA_LED, 1);						#endif						am930hw_onint_rx(hw);					}							if ( SUCS_INT_IS_TX(int_status1) )					{						#if (WLAN_OS == WLAN_LWOS)							LED_Blink( WIRELESS_DATA_LED, 1);						#endif						am930hw_onint_tx(hw);					}					if ( SUCS_INT_IS_SCANCMPLT(int_status1) )					{						am930hw_onint_scancomplete(hw);					}							if ( SUCS_INT_IS_CMD(int_status1) )					{						am930hw_onint_cmdcomplete(hw);					}					/* Check the int status again, to see if more int events */					/*   have occurred */							if ( am930hw_lockint(hw) != 0 )					{						WLAN_LOG_DEBUG0(2,"Unable to lockout f/w, 2nd time\n");						int_status1 = 0;					}					else					{						int_status1 = read8(hw, hw->cs + CS_OFF_INT_STATUS);						int_status2 = read8(hw, hw->cs + CS_OFF_INT_STATUS2);						if ( int_status1 != 0 ) /* are we handling again? */						{							write8(hw, hw->cs + CS_OFF_INT_STATUS, 0);							write8(hw, hw->cs + CS_OFF_INT_STATUS2, 0);						}						else						{							/* reset the int_mask to the setting it had on ISR entry */							write8(hw, hw->cs + CS_OFF_INT_MASK, int_mask1);							write8(hw, hw->cs + CS_OFF_INT_MASK2, int_mask2);						}						am930hw_unlockint(hw);					}				}				while ( int_status1 != 0 );				if ( handled > 1 )				{					WLAN_LOG_DEBUG1(3, "hw_ISR: handled=%d\n", handled);				}				/* 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;			} /* endif lockint */		} /* endif !overlapped */	} /* hw OK, card in slot */	else	{		WLAN_LOG_WARNING0("ISR called when hw is NULL, not CONFIG or "					"no card in slot, future ints may be lost!\n");	}	DBFEXIT;	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, 						UINT8 *bssid, wlan_ie_ssid_t *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 */		memcpy( mm_mib.current_essid, ssid, ssid->len + 2);		/* set the beaconrate */		mm_mib.beacon_period = host2amd16(bcn_int);		/* save the mib */		if ( am930hw_mibset(hw, SUMIB_MGMT, 0, 					sizeof(mm_mib), &mm_mib) != AM930HW_SUCCESS )		{			result = AM930HW_FAILURE;		}		else		{			/* send the sync command */			if ( am930hw_sync( hw, 								ch, 								newBSS, 								(newBSS == 0) ? ts : NULL, 								sutro_ref_time ) != AM930HW_CMD_SUCCESS )			{				result = AM930HW_FAILURE;			}			else			{				/* Set the driver state */				if (hw->mac->mode == AM930_MACMODE_ESS_AP)				{					write8( hw, hw->cs + CS_OFF_DRIVER_STATE, SUCS_DS_AP_NO_ASSOC);				}			}		}	}	DBFEXIT;	return result;}/*----------------------------------------------------------------*	am930hw_onint_cmdcomplete**	ISR helper for f/w generated command complete interrupts**	returns: nothing----------------------------------------------------------------*/void am930hw_onint_cmdcomplete( am930hw_t *hw ){	DBFENTER;	WLAN_LOG_DEBUG1(3,"cmd complete int, last_cmd= 0x%x\n", hw->last_cmd);	hw->last_cmd = 0;	DBFEXIT;}/*----------------------------------------------------------------*	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;	am930rxstats_t	*stats;	wlan_pb_t		*pb;	UINT			nhandled = 0;	UINT			frm_rxd = 0;	UINT			payloadlen;	DBFENTER;	/* 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;		nhandled++;		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 */			/*  first, get rid of the old one */			old_state |= SURXD_ST_FWOWN;			write8( hw, old_head + RXD_OFF_STATE, old_state);			if ( SURXD_ST_IS_CONSUMED(state) )			{				/* it's a dummy, do nothing */				WLAN_LOG_DEBUG0(1, "We got a dummy!\n");			}			if ( SURXD_ST_IS_RXERR(state) )			{				if ( SURXD_ST_IS_CRC_ERR(state) )				{					WLAN_LOG_WARNING0( "RX int, desc err=CRC\n");					hw->stats.rx_crcerr++;				}				if ( SURXD_ST_IS_BUF_OFLOW(state) )				{					WLAN_LOG_WARNING0( "RX int, desc err=BUF_OFLOW\n");					hw->stats.rx_buf_oflow++;				}				state |= SURXD_ST_CONSUMED;				write8(hw, hw->rx_head+RXD_OFF_STATE, state);				am930mac_rxframe_err(hw->mac);			}			else if ( !SURXD_ST_IS_CONSUMED(state) )			{				/* hey! we've actually got something! */				/*  copy the frame to host memory and pass it up */				len = read16(hw, hw->rx_head + RXD_OFF_LEN);				/* Make a packet buffer */				pb = am930shim_pballoc();				if ( pb == NULL )				{					WLAN_LOG_DEBUG0(2,"pballoc failed.\n");					state |= SURXD_ST_CONSUMED;					write8(hw, hw->rx_head+RXD_OFF_STATE, state);				}				else				{					am930shim_pballoc_p80211(pb, len);					if ( pb->p80211hostbuf == NULL )					{						WLAN_LOG_DEBUG0(2,"pballoc_p80211 failed!\n");						state |= SURXD_ST_CONSUMED;						write8(hw, hw->rx_head+RXD_OFF_STATE, state);					}					else					{						data_off = read32(hw, hw->rx_head + RXD_OFF_START_FRAME);						data_off &= 0x0000ffff;						payloadlen = len;						readcard(hw, data_off, pb->p80211buf, WLAN_HDR_A3_LEN);						data_off += WLAN_HDR_A3_LEN;						payloadlen -= (WLAN_HDR_A3_LEN + WLAN_CRC_LEN);						if ( WLAN_GET_FC_ISWEP(ieee2host16(pb->p80211_hdr->a3.fc)))						{							/* read the encrypted frame into the pb fields */							payloadlen -= (WLAN_WEP_IV_LEN + WLAN_WEP_ICV_LEN);							/* wep iv */							readcard(hw, 								data_off, 								&(pb->wep_iv), 								WLAN_WEP_IV_LEN); 							data_off += WLAN_WEP_IV_LEN;							/* wep icv */							readcard(hw, 								data_off + payloadlen,								&(pb->wep_icv), 								WLAN_WEP_ICV_LEN);							/* payload */							readcard(hw, 								data_off,								pb->p80211buf + WLAN_HDR_A3_LEN, 								payloadlen);							/* wlan crc */							readcard(hw, 								data_off + payloadlen + WLAN_WEP_ICV_LEN,								pb->p80211buf + WLAN_HDR_A3_LEN + payloadlen,								WLAN_CRC_LEN );							/* adjust the pb len fields and mark as encrypted */							pb->p80211frmlen = 								WLAN_HDR_A3_LEN + payloadlen + WLAN_CRC_LEN;							pb->p80211_payloadlen = payloadlen;							pb->wep_iscrypt = 1;						}						else						{							readcard( hw, 								data_off,								pb->p80211buf + WLAN_HDR_A3_LEN, 								len - WLAN_HDR_A3_LEN);						}						stats = (am930rxstats_t*)kmalloc(sizeof(am930rxstats_t), GFP_ATOMIC);						if ( stats == NULL )						{							WLAN_LOG_DEBUG0(2,"rxstats alloc_p80211 failed!\n");							state |= SURXD_ST_CONSUMED;							write8(hw, hw->rx_head+RXD_OFF_STATE, state);						}						else						{							stats->rssi = read8(hw, hw->rx_head + RXD_OFF_RSSI);							stats->ch = read8(hw, hw->rx_head + RXD_OFF_INDEX_OR_CH);							stats->local_time = read32(hw, hw->rx_head + RXD_OFF_LOCAL_TIME);							stats->rate = read8(hw, hw->rx_head + RXD_OFF_RATE);							state |= SURXD_ST_CONSUMED;							write8(hw, hw->rx_head+RXD_OFF_STATE, state);							WLAN_HEX_DUMP(3,"hwrxf",pb->p80211buf,pb->p80211frmlen);							am930mac_rxenqueue( hw->mac, pb, stats);							frm_rxd = 1;							#ifdef WLAN_INCLUDE_SNIF							if ( hw->mac->snifflags & SNIFFLAG_SNIFRX )							{								am930mac_snifframe(hw->mac, pb, stats);							}							#endif						}					}				}			}		}		/* read the state and next fields from the head */		state = read8(hw, hw->rx_head + RXD_OFF_STATE);		next = am930hw_read_rxnext(hw);	}	if ( nhandled > 1 )	{		WLAN_LOG_DEBUG1(2, "onint_rx handled %d\n", nhandled);	}	#if (WLAN_OS == WLAN_LINUX_KERNEL)	if ( frm_rxd )	{		am930mac_rxframe(hw->mac);/*		am930hw_txkick(hw); */	}	#endif	DBFEXIT;}/*----------------------------------------------------------------*	am930hw_read_rxnext**	Repeated read of the rxnext field to make _sure_ we have real*	data.  Very paranoid.**	returns: nothing----------------------------------------------------------------*/static UINT32 am930hw_read_rxnext(am930hw_t *hw){	UINT32 result = 0;	UINT32 old = 0;	result = read32( hw, hw->rx_head + RXD_OFF_NEXT);	while ( result != old )	{		old = result;		result = read32( hw, hw->rx_head + RXD_OFF_NEXT);		if ( old != result )		{			WLAN_LOG_DEBUG1(1, "reread of rxnext:0x%04lx didn't match!\n",				hw->rx_head + RXD_OFF_NEXT);		}	}	return result;}/*----------------------------------------------------------------*	am930hw_onint_tx**	ISR helper for f/w generated tx complete interrupts**	returns: nothing----------------------------------------------------------------*/void am930hw_onint_tx( am930hw_t *hw ){	UINT32	last;	UINT32	back;	UINT8	state;	UINT32	host;	UINT32	txresult = 0;	UINT32	nhandled = 0;	DBFENTER;	last = reread32(hw, hw->txcmplt + TXCMPLT_OFF_DATA);	state = read8(hw, last + TXD_OFF_STATE);	host = read32(hw, last + TXD_OFF_HOST);	/* backwalk the queue to find last unserviced desc */	back = last;	while ( !(state & SUTXD_ST_FWOWN) && host != 0 )	{		last = back;		write32(hw, back + TXD_OFF_HOST, 0);		back = reread32(hw, back + TXD_OFF_PREV);		state = read8(hw, back + TXD_OFF_STATE);		host = read32(hw, back + TXD_OFF_HOST);	}	state = read8(hw, last + TXD_OFF_STATE);	host = read32(hw, last + TXD_OFF_HOST);	while ( !(state & SUTXD_ST_FWOWN) && 			(state & SUTXD_ST_DONE) ) 	{		write8(hw, last + TXD_OFF_STATE, 0);		write32(hw, last + TXD_OFF_HOST, 0);		if ( state & SUTXD_ST_TXERR )		{			WLAN_LOG_DEBUG0(2, "TX err:\n");			if ( state & SUTXD_ST_REJECTED )			{				WLAN_LOG_DEBUG0(2, "TX err=frame rejected by f/w.\n");				hw->stats.tx_rejected++;			}			if ( state & SUTXD_ST_MSDU_TMOUT )			{				WLAN_LOG_DEBUG0(2, "TX err=msdu timeout.\n");				hw->stats.tx_tmout++;			}			if ( state & SUTXD_ST_ABRT )			{				WLAN_LOG_DEBUG0(2, "TX err=frame aborted, after >1 tx attempt.\n");			}			if ( state & SUTXD_ST_ABRT_NOTX )			{				WLAN_LOG_DEBUG0(2, "TX err=frame aborted, no tx attempts.\n");			}

⌨️ 快捷键说明

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