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

📄 if_an.c

📁 访问基于802.1x认证方式的网络
💻 C
📖 第 1 页 / 共 4 页
字号:
		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;		/* Read Ethenet encapsulated packet */#ifdef ANCACHE		/* Read NIC frame header */		if (an_read_data(sc, id, 0, (caddr_t) & rx_frame, sizeof(rx_frame))) {			ifp->if_ierrors++;			return;		}#endif		/* Read in the 802_3 frame header */		if (an_read_data(sc, id, 0x34, (caddr_t) & rx_frame_802_3,				 sizeof(rx_frame_802_3))) {			ifp->if_ierrors++;			return;		}		if (rx_frame_802_3.an_rx_802_3_status != 0) {			ifp->if_ierrors++;			return;		}		/* Check for insane frame length */		if (rx_frame_802_3.an_rx_802_3_payload_len > MCLBYTES) {			ifp->if_ierrors++;			return;		}		m->m_pkthdr.len = m->m_len =			rx_frame_802_3.an_rx_802_3_payload_len + 12;		eh = mtod(m, struct ether_header *);		bcopy((char *)&rx_frame_802_3.an_rx_dst_addr,		      (char *)&eh->ether_dhost, ETHER_ADDR_LEN);		bcopy((char *)&rx_frame_802_3.an_rx_src_addr,		      (char *)&eh->ether_shost, ETHER_ADDR_LEN);		/* in mbuf header type is just before payload */		error = an_read_data(sc, id, 0x44, (caddr_t)&(eh->ether_type),				     rx_frame_802_3.an_rx_802_3_payload_len);		if (error) {			m_freem(m);			ifp->if_ierrors++;			return;		}		ifp->if_ipackets++;		/* Receive packet. */		m_adj(m, sizeof(struct ether_header));#ifdef ANCACHE		an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength);#endif		ether_input(ifp, eh, m);	}}static voidan_txeof(sc, status)	struct an_softc		*sc;	int			status;{	struct ifnet		*ifp;	int			id, i;	ifp = &sc->arpcom.ac_if;	ifp->if_timer = 0;	ifp->if_flags &= ~IFF_OACTIVE;	id = CSR_READ_2(sc, AN_TX_CMP_FID);	if (status & AN_EV_TX_EXC) {		ifp->if_oerrors++;	} else		ifp->if_opackets++;	for (i = 0; i < AN_TX_RING_CNT; i++) {		if (id == sc->an_rdata.an_tx_ring[i]) {			sc->an_rdata.an_tx_ring[i] = 0;			break;		}	}	AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT);	return;}/* * We abuse the stats updater to check the current NIC status. This * is important because we don't want to allow transmissions until * the NIC has synchronized to the current cell (either as the master * in an ad-hoc group, or as a station connected to an access point). */voidan_stats_update(xsc)	void			*xsc;{	struct an_softc		*sc;	struct ifnet		*ifp;	int			s;	s = splimp();	sc = xsc;	ifp = &sc->arpcom.ac_if;	sc->an_status.an_type = AN_RID_STATUS;	sc->an_status.an_len = sizeof(struct an_ltv_status);	an_read_record(sc, (struct an_ltv_gen *)&sc->an_status);	if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC)		sc->an_associated = 1;	else		sc->an_associated = 0;	/* Don't do this while we're transmitting */	if (ifp->if_flags & IFF_OACTIVE) {		sc->an_stat_ch = timeout(an_stats_update, sc, hz);		splx(s);		return;	}	sc->an_stats.an_len = sizeof(struct an_ltv_stats);	sc->an_stats.an_type = AN_RID_32BITS_CUM;	an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len);	sc->an_stat_ch = timeout(an_stats_update, sc, hz);	splx(s);	return;}voidan_intr(xsc)	void			*xsc;{	struct an_softc		*sc;	struct ifnet		*ifp;	u_int16_t		status;	sc = (struct an_softc*)xsc;	if (sc->an_gone)		return;	ifp = &sc->arpcom.ac_if;	/* Disable interrupts. */	CSR_WRITE_2(sc, AN_INT_EN, 0);	status = CSR_READ_2(sc, AN_EVENT_STAT);	CSR_WRITE_2(sc, AN_EVENT_ACK, ~AN_INTRS);	if (status & AN_EV_AWAKE) {		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_AWAKE);	}	if (status & AN_EV_LINKSTAT) {		if (CSR_READ_2(sc, AN_LINKSTAT) == AN_LINKSTAT_ASSOCIATED)			sc->an_associated = 1;		else			sc->an_associated = 0;		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT);	}	if (status & AN_EV_RX) {		an_rxeof(sc);		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);	}	if (status & AN_EV_TX) {		an_txeof(sc, status);		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX);	}	if (status & AN_EV_TX_EXC) {		an_txeof(sc, status);		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX_EXC);	}	if (status & AN_EV_ALLOC)		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);	/* Re-enable interrupts. */	CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);	if ((ifp->if_flags & IFF_UP) && (ifp->if_snd.ifq_head != NULL))		an_start(ifp);	return;}static intan_cmd(sc, cmd, val)	struct an_softc		*sc;	int			cmd;	int			val;{	int			i, s = 0;	CSR_WRITE_2(sc, AN_PARAM0, val);	CSR_WRITE_2(sc, AN_PARAM1, 0);	CSR_WRITE_2(sc, AN_PARAM2, 0);	CSR_WRITE_2(sc, AN_COMMAND, cmd);	for (i = 0; i < AN_TIMEOUT; i++) {		if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD)			break;		else {			if (CSR_READ_2(sc, AN_COMMAND) == cmd)				CSR_WRITE_2(sc, AN_COMMAND, cmd);		}	}	for (i = 0; i < AN_TIMEOUT; i++) {		CSR_READ_2(sc, AN_RESP0);		CSR_READ_2(sc, AN_RESP1);		CSR_READ_2(sc, AN_RESP2);		s = CSR_READ_2(sc, AN_STATUS);		if ((s & AN_STAT_CMD_CODE) == (cmd & AN_STAT_CMD_CODE))			break;	}	/* Ack the command */	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);	if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY)		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);	if (i == AN_TIMEOUT)		return(ETIMEDOUT);	return(0);}/* * This reset sequence may look a little strange, but this is the * most reliable method I've found to really kick the NIC in the * head and force it to reboot correctly. */static voidan_reset(sc)	struct an_softc		*sc;{	if (sc->an_gone)		return;	an_cmd(sc, AN_CMD_ENABLE, 0);	an_cmd(sc, AN_CMD_FW_RESTART, 0);	an_cmd(sc, AN_CMD_NOOP2, 0);	if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT)		printf("an%d: reset failed\n", sc->an_unit);	an_cmd(sc, AN_CMD_DISABLE, 0);	return;}/* * Read an LTV record from the NIC. */static intan_read_record(sc, ltv)	struct an_softc		*sc;	struct an_ltv_gen	*ltv;{	u_int16_t		*ptr;	u_int8_t		*ptr2;	int			i, len;	if (ltv->an_len < 4 || ltv->an_type == 0)		return(EINVAL);	/* Tell the NIC to enter record read mode. */	if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) {		printf("an%d: RID access failed\n", sc->an_unit);		return(EIO);	}	/* Seek to the record. */	if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) {		printf("an%d: seek to record failed\n", sc->an_unit);		return(EIO);	}	/*	 * Read the length and record type and make sure they	 * match what we expect (this verifies that we have enough	 * room to hold all of the returned data).	 * Length includes type but not length.	 */	len = CSR_READ_2(sc, AN_DATA1);	if (len > (ltv->an_len - 2)) {		printf("an%d: record length mismatch -- expected %d, "		    "got %d for Rid %x\n", sc->an_unit,		    ltv->an_len - 2, len, ltv->an_type);		len = ltv->an_len - 2;	} else {		ltv->an_len = len + 2;	}	/* Now read the data. */	len -= 2;	/* skip the type */	ptr = &ltv->an_val;	for (i = len; i > 1; i -= 2)		*ptr++ = CSR_READ_2(sc, AN_DATA1);	if (i) {		ptr2 = (u_int8_t *)ptr;		*ptr2 = CSR_READ_1(sc, AN_DATA1);	}	if (an_dump)		an_dump_record(sc, ltv, "Read");	return(0);}/* * Same as read, except we inject data instead of reading it. */static intan_write_record(sc, ltv)	struct an_softc		*sc;	struct an_ltv_gen	*ltv;{	u_int16_t		*ptr;	u_int8_t		*ptr2;	int			i, len;	if (an_dump)		an_dump_record(sc, ltv, "Write");	if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type))		return(EIO);	if (an_seek(sc, ltv->an_type, 0, AN_BAP1))		return(EIO);	/*	 * Length includes type but not length.	 */	len = ltv->an_len - 2;	CSR_WRITE_2(sc, AN_DATA1, len);	len -= 2;	/* skip the type */	ptr = &ltv->an_val;	for (i = len; i > 1; i -= 2)		CSR_WRITE_2(sc, AN_DATA1, *ptr++);	if (i) {		ptr2 = (u_int8_t *)ptr;		CSR_WRITE_1(sc, AN_DATA0, *ptr2);	}	if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type))		return(EIO);	return(0);}static voidan_dump_record(sc, ltv, string)	struct an_softc		*sc;	struct an_ltv_gen	*ltv;	char			*string;{	u_int8_t		*ptr2;	int			len;	int			i;	int			count = 0;	char			buf[17], temp;	len = ltv->an_len - 4;	printf("an%d: RID %4x, Length %4d, Mode %s\n",		sc->an_unit, ltv->an_type, ltv->an_len - 4, string);	if (an_dump == 1 || (an_dump == ltv->an_type)) {		printf("an%d:\t", sc->an_unit);		bzero(buf,sizeof(buf));		ptr2 = (u_int8_t *)&ltv->an_val;		for (i = len; i > 0; i--) {			printf("%02x ", *ptr2);			temp = *ptr2++;			if (temp >= ' ' && temp <= '~')				buf[count] = temp;			else if (temp >= 'A' && temp <= 'Z')				buf[count] = temp;			else				buf[count] = '.';			if (++count == 16) {				count = 0;				printf("%s\n",buf);				printf("an%d:\t", sc->an_unit);				bzero(buf,sizeof(buf));			}		}		for (; count != 16; count++) {			printf("   ");		}		printf(" %s\n",buf);	}}static intan_seek(sc, id, off, chan)	struct an_softc		*sc;	int			id, off, chan;{	int			i;	int			selreg, offreg;	switch (chan) {	case AN_BAP0:		selreg = AN_SEL0;		offreg = AN_OFF0;		break;	case AN_BAP1:		selreg = AN_SEL1;		offreg = AN_OFF1;		break;	default:		printf("an%d: invalid data path: %x\n", sc->an_unit, chan);		return(EIO);	}	CSR_WRITE_2(sc, selreg, id);	CSR_WRITE_2(sc, offreg, off);	for (i = 0; i < AN_TIMEOUT; i++) {		if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR)))			break;	}	if (i == AN_TIMEOUT)		return(ETIMEDOUT);	return(0);}static intan_read_data(sc, id, off, buf, len)	struct an_softc		*sc;	int			id, off;	caddr_t			buf;	int			len;{	int			i;	u_int16_t		*ptr;	u_int8_t		*ptr2;	if (off != -1) {		if (an_seek(sc, id, off, AN_BAP1))			return(EIO);	}	ptr = (u_int16_t *)buf;	for (i = len; i > 1; i -= 2)		*ptr++ = CSR_READ_2(sc, AN_DATA1);	if (i) {		ptr2 = (u_int8_t *)ptr;		*ptr2 = CSR_READ_1(sc, AN_DATA1);	}	return(0);}static intan_write_data(sc, id, off, buf, len)	struct an_softc		*sc;	int			id, off;	caddr_t			buf;	int			len;{	int			i;	u_int16_t		*ptr;	u_int8_t		*ptr2;	if (off != -1) {		if (an_seek(sc, id, off, AN_BAP0))			return(EIO);	}	ptr = (u_int16_t *)buf;	for (i = len; i > 1; i -= 2)		CSR_WRITE_2(sc, AN_DATA0, *ptr++);	if (i) {	        ptr2 = (u_int8_t *)ptr;	        CSR_WRITE_1(sc, AN_DATA0, *ptr2);	}	return(0);}/* * Allocate a region of memory inside the NIC and zero * it out. */static intan_alloc_nicmem(sc, len, id)	struct an_softc		*sc;	int			len;	int			*id;{	int			i;	if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) {		printf("an%d: failed to allocate %d bytes on NIC\n",		    sc->an_unit, len);		return(ENOMEM);	}	for (i = 0; i < AN_TIMEOUT; i++) {		if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC)			break;	}	if (i == AN_TIMEOUT)		return(ETIMEDOUT);	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);	*id = CSR_READ_2(sc, AN_ALLOC_FID);	if (an_seek(sc, *id, 0, AN_BAP0))		return(EIO);	for (i = 0; i < len / 2; i++)		CSR_WRITE_2(sc, AN_DATA0, 0);	return(0);}static voidan_setdef(sc, areq)	struct an_softc		*sc;	struct an_req		*areq;{	struct sockaddr_dl	*sdl;	struct ifaddr		*ifa;	struct ifnet		*ifp;	struct an_ltv_genconfig	*cfg;	struct an_ltv_ssidlist	*ssid;	struct an_ltv_aplist	*ap;	struct an_ltv_gen	*sp;	ifp = &sc->arpcom.ac_if;	switch (areq->an_type) {	case AN_RID_GENCONFIG:		cfg = (struct an_ltv_genconfig *)areq;		ifa = ifnet_addrs[ifp->if_index - 1];		sdl = (struct sockaddr_dl *)ifa->ifa_addr;		bcopy((char *)&cfg->an_macaddr, (char *)&sc->arpcom.ac_enaddr,		    ETHER_ADDR_LEN);		bcopy((char *)&cfg->an_macaddr, LLADDR(sdl), ETHER_ADDR_LEN);		bcopy((char *)cfg, (char *)&sc->an_config,			sizeof(struct an_ltv_genconfig));		break;

⌨️ 快捷键说明

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