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

📄 if_wi.c

📁 一个学习SNMP项目:tmoerlan.
💻 C
📖 第 1 页 / 共 5 页
字号:
	id = CSR_READ_2(sc, WI_RX_FID);	/*	 * if we have the procframe flag set, disregard all this and just	 * read the data from the device.	 */	if (sc->wi_procframe || sc->wi_debug.wi_monitor) {		struct wi_frame		*rx_frame;		int			datlen, hdrlen;		/* first allocate mbuf for packet storage */		MGETHDR(m, M_DONTWAIT, MT_DATA);		if (m == NULL) {			ifp->if_ierrors++;			return;		}		MCLGET(m, M_DONTWAIT);		if (!(m->m_flags & M_EXT)) {			m_freem(m);			ifp->if_ierrors++;			return;		}		m->m_pkthdr.rcvif = ifp;		/* now read wi_frame first so we know how much data to read */		if (wi_read_data(sc, id, 0, mtod(m, caddr_t),		    sizeof(struct wi_frame))) {			m_freem(m);			ifp->if_ierrors++;			return;		}		rx_frame = mtod(m, struct wi_frame *);		switch ((rx_frame->wi_status & WI_STAT_MAC_PORT) >> 8) {		case 7:			switch (rx_frame->wi_frame_ctl & WI_FCTL_FTYPE) {			case WI_FTYPE_DATA:				hdrlen = WI_DATA_HDRLEN;				datlen = rx_frame->wi_dat_len + WI_FCS_LEN;				break;			case WI_FTYPE_MGMT:				hdrlen = WI_MGMT_HDRLEN;				datlen = rx_frame->wi_dat_len + WI_FCS_LEN;				break;			case WI_FTYPE_CTL:				/*				 * prism2 cards don't pass control packets				 * down properly or consistently, so we'll only				 * pass down the header.				 */				hdrlen = WI_CTL_HDRLEN;				datlen = 0;				break;			default:				device_printf(sc->dev, "received packet of "				    "unknown type on port 7\n");				m_freem(m);				ifp->if_ierrors++;				return;			}			break;		case 0:			hdrlen = WI_DATA_HDRLEN;			datlen = rx_frame->wi_dat_len + WI_FCS_LEN;			break;		default:			device_printf(sc->dev, "received packet on invalid "			    "port (wi_status=0x%x)\n", rx_frame->wi_status);			m_freem(m);			ifp->if_ierrors++;			return;		}		if ((hdrlen + datlen + 2) > MCLBYTES) {			device_printf(sc->dev, "oversized packet received "			    "(wi_dat_len=%d, wi_status=0x%x)\n",			    datlen, rx_frame->wi_status);			m_freem(m);			ifp->if_ierrors++;			return;		}		if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen,		    datlen + 2)) {			m_freem(m);			ifp->if_ierrors++;			return;		}		m->m_pkthdr.len = m->m_len = hdrlen + datlen;		ifp->if_ipackets++;		/* Handle BPF listeners. */		BPF_MTAP(ifp, m);		m_freem(m);	} else {		struct wi_frame		rx_frame;		/* First read in the frame header */		if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,		    sizeof(rx_frame))) {			ifp->if_ierrors++;			return;		}		if (rx_frame.wi_status & WI_STAT_ERRSTAT) {			ifp->if_ierrors++;			return;		}		MGETHDR(m, M_DONTWAIT, MT_DATA);		if (m == NULL) {			ifp->if_ierrors++;			return;		}		MCLGET(m, M_DONTWAIT);		if (!(m->m_flags & M_EXT)) {			m_freem(m);			ifp->if_ierrors++;			return;		}		eh = mtod(m, struct ether_header *);		m->m_pkthdr.rcvif = ifp;		if (rx_frame.wi_status == WI_STAT_MGMT &&		    sc->wi_ptype == WI_PORTTYPE_HOSTAP) {			if ((WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len + 2) >			    MCLBYTES) {				device_printf(sc->dev, "oversized mgmt packet "				    "received in hostap mode " 				    "(wi_dat_len=%d, wi_status=0x%x)\n",				    rx_frame.wi_dat_len, rx_frame.wi_status);				m_freem(m);				ifp->if_ierrors++;				return;			}			/* Put the whole header in there. */			bcopy(&rx_frame, mtod(m, void *),			    sizeof(struct wi_frame));			if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW, 			    mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,			    rx_frame.wi_dat_len + 2)) {				m_freem(m);				ifp->if_ierrors++;				return;			}			m->m_pkthdr.len = m->m_len =			    WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len;			/* XXX: consider giving packet to bhp? */			wihap_mgmt_input(sc, &rx_frame, m);			return;		}		if (rx_frame.wi_status == WI_STAT_1042 ||		    rx_frame.wi_status == WI_STAT_TUNNEL ||		    rx_frame.wi_status == WI_STAT_WMP_MSG) {			if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) {				device_printf(sc->dev,				    "oversized packet received "				    "(wi_dat_len=%d, wi_status=0x%x)\n",				    rx_frame.wi_dat_len, rx_frame.wi_status);				m_freem(m);				ifp->if_ierrors++;				return;			}			m->m_pkthdr.len = m->m_len =			    rx_frame.wi_dat_len + WI_SNAPHDR_LEN;#if 0			bcopy((char *)&rx_frame.wi_addr1,			    (char *)&eh->ether_dhost, ETHER_ADDR_LEN);			if (sc->wi_ptype == WI_PORTTYPE_ADHOC) {				bcopy((char *)&rx_frame.wi_addr2,				    (char *)&eh->ether_shost, ETHER_ADDR_LEN);			} else {				bcopy((char *)&rx_frame.wi_addr3,				    (char *)&eh->ether_shost, ETHER_ADDR_LEN);			}#else			bcopy((char *)&rx_frame.wi_dst_addr,				(char *)&eh->ether_dhost, ETHER_ADDR_LEN);			bcopy((char *)&rx_frame.wi_src_addr,				(char *)&eh->ether_shost, ETHER_ADDR_LEN);#endif			bcopy((char *)&rx_frame.wi_type,			    (char *)&eh->ether_type, ETHER_TYPE_LEN);			if (wi_read_data(sc, id, WI_802_11_OFFSET,			    mtod(m, caddr_t) + sizeof(struct ether_header),			    m->m_len + 2)) {				m_freem(m);				ifp->if_ierrors++;				return;			}		} else {			if((rx_frame.wi_dat_len +			    sizeof(struct ether_header)) > MCLBYTES) {				device_printf(sc->dev,				    "oversized packet received "				    "(wi_dat_len=%d, wi_status=0x%x)\n",				    rx_frame.wi_dat_len, rx_frame.wi_status);				m_freem(m);				ifp->if_ierrors++;				return;			}			m->m_pkthdr.len = m->m_len =			    rx_frame.wi_dat_len + sizeof(struct ether_header);			if (wi_read_data(sc, id, WI_802_3_OFFSET,			    mtod(m, caddr_t), m->m_len + 2)) {				m_freem(m);				ifp->if_ierrors++;				return;			}		}		ifp->if_ipackets++;		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {			/* 			 * Give host AP code first crack at data			 * packets.  If it decides to handle it (or			 * drop it), it will return a non-zero.			 * Otherwise, it is destined for this host.			 */			if (wihap_data_input(sc, &rx_frame, m))				return;		}		/* Receive packet. */#ifdef WICACHE		wi_cache_store(sc, eh, m, rx_frame.wi_q_info);#endif  		(*ifp->if_input)(ifp, m);	}}static voidwi_txeof(sc, status)	struct wi_softc		*sc;	int			status;{	struct ifnet		*ifp;	ifp = &sc->arpcom.ac_if;	ifp->if_timer = 0;	ifp->if_flags &= ~IFF_OACTIVE;	if (status & WI_EV_TX_EXC)		ifp->if_oerrors++;	else		ifp->if_opackets++;	return;}static voidwi_inquire(xsc)	void			*xsc;{	struct wi_softc		*sc;	struct ifnet		*ifp;	int			s;	sc = xsc;	ifp = &sc->arpcom.ac_if;	sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);	/* Don't do this while we're transmitting */	if (ifp->if_flags & IFF_OACTIVE)		return;	WI_LOCK(sc, s);	wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0);	WI_UNLOCK(sc, s);	return;}static voidwi_update_stats(sc)	struct wi_softc		*sc;{	struct wi_ltv_gen	gen;	u_int16_t		id;	struct ifnet		*ifp;	u_int32_t		*ptr;	int			len, i;	u_int16_t		t;	ifp = &sc->arpcom.ac_if;	id = CSR_READ_2(sc, WI_INFO_FID);	wi_read_data(sc, id, 0, (char *)&gen, 4);	/*	 * if we just got our scan results, copy it over into the scan buffer	 * so we can return it to anyone that asks for it. (add a little	 * compatibility with the prism2 scanning mechanism)	 */	if (gen.wi_type == WI_INFO_SCAN_RESULTS)	{		sc->wi_scanbuf_len = gen.wi_len;		wi_read_data(sc, id, 4, (char *)sc->wi_scanbuf,		    sc->wi_scanbuf_len * 2);		return;	}	else if (gen.wi_type != WI_INFO_COUNTERS)		return;	len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?		gen.wi_len - 1 : sizeof(sc->wi_stats) / 4;	ptr = (u_int32_t *)&sc->wi_stats;	for (i = 0; i < len - 1; i++) {		t = CSR_READ_2(sc, WI_DATA1);#ifdef WI_HERMES_STATS_WAR		if (t > 0xF000)			t = ~t & 0xFFFF;#endif		ptr[i] += t;	}	ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +	    sc->wi_stats.wi_tx_multi_retries +	    sc->wi_stats.wi_tx_retry_limit;	return;}static voidwi_intr(xsc)	void		*xsc;{	struct wi_softc		*sc = xsc;	struct ifnet		*ifp;	u_int16_t		status;	int			s;	WI_LOCK(sc, s);	ifp = &sc->arpcom.ac_if;	if (sc->wi_gone || !(ifp->if_flags & IFF_UP)) {		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);		CSR_WRITE_2(sc, WI_INT_EN, 0);		WI_UNLOCK(sc, s);		return;	}	/* Disable interrupts. */	CSR_WRITE_2(sc, WI_INT_EN, 0);	status = CSR_READ_2(sc, WI_EVENT_STAT);	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);	if (status & WI_EV_RX) {		wi_rxeof(sc);		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);	}	if (status & WI_EV_TX) {		wi_txeof(sc, status);		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);	}	if (status & WI_EV_ALLOC) {		int			id;		id = CSR_READ_2(sc, WI_ALLOC_FID);		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);		if (id == sc->wi_tx_data_id)			wi_txeof(sc, status);	}	if (status & WI_EV_INFO) {		wi_update_stats(sc);		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);	}	if (status & WI_EV_TX_EXC) {		wi_txeof(sc, status);		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);	}	if (status & WI_EV_INFO_DROP) {		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);	}	/* Re-enable interrupts. */	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);	if (ifp->if_snd.ifq_head != NULL) {		wi_start(ifp);	}	WI_UNLOCK(sc, s);	return;}static intwi_cmd(sc, cmd, val0, val1, val2)	struct wi_softc		*sc;	int			cmd;	int			val0;	int			val1;	int			val2;{	int			i, s = 0;	static volatile int count  = 0;		if (count > 1)		panic("Hey partner, hold on there!");	count++;	/* wait for the busy bit to clear */	for (i = 500; i > 0; i--) {	/* 5s */		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) {			break;		}		DELAY(10*1000);	/* 10 m sec */	}	if (i == 0) {		device_printf(sc->dev, "wi_cmd: busy bit won't clear.\n" );		count--;		return(ETIMEDOUT);	}	CSR_WRITE_2(sc, WI_PARAM0, val0);	CSR_WRITE_2(sc, WI_PARAM1, val1);

⌨️ 快捷键说明

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