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

📄 if_wi.c

📁 一个学习SNMP项目:tmoerlan.
💻 C
📖 第 1 页 / 共 5 页
字号:
	CSR_WRITE_2(sc, WI_PARAM2, val2);	CSR_WRITE_2(sc, WI_COMMAND, cmd);	for (i = 0; i < WI_TIMEOUT; i++) {		/*		 * Wait for 'command complete' bit to be		 * set in the event status register.		 */		s = CSR_READ_2(sc, WI_EVENT_STAT);		if (s & WI_EV_CMD) {			/* Ack the event and read result code. */			s = CSR_READ_2(sc, WI_STATUS);			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);#ifdef foo			if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK))				return(EIO);#endif			if (s & WI_STAT_CMD_RESULT) {				count--;				return(EIO);			}			break;		}		DELAY(WI_DELAY);	}	count--;	if (i == WI_TIMEOUT) {		device_printf(sc->dev,		    "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);		return(ETIMEDOUT);	}	return(0);}static voidwi_reset(sc)	struct wi_softc		*sc;{#define WI_INIT_TRIES 3	int i;	int tries;		/* Symbol firmware cannot be initialized more than once */	if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_enabled)		return;	if (sc->sc_firmware_type == WI_SYMBOL)		tries = 1;	else		tries = WI_INIT_TRIES;	for (i = 0; i < tries; i++) {		if (wi_cmd(sc, WI_CMD_INI, 0, 0, 0) == 0)			break;		DELAY(WI_DELAY * 1000);	}	sc->sc_enabled = 1;	if (i == tries) {		device_printf(sc->dev, "init failed\n");		return;	}	CSR_WRITE_2(sc, WI_INT_EN, 0);	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);	/* Calibrate timer. */	WI_SETVAL(WI_RID_TICK_TIME, 8);	return;}/* * Read an LTV record from the NIC. */static intwi_read_record(sc, ltv)	struct wi_softc		*sc;	struct wi_ltv_gen	*ltv;{	u_int16_t		*ptr;	int			i, len, code;	struct wi_ltv_gen	*oltv, p2ltv;	oltv = ltv;	if (sc->sc_firmware_type != WI_LUCENT) {		switch (ltv->wi_type) {		case WI_RID_ENCRYPTION:			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;			p2ltv.wi_len = 2;			ltv = &p2ltv;			break;		case WI_RID_TX_CRYPT_KEY:			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;			p2ltv.wi_len = 2;			ltv = &p2ltv;			break;		case WI_RID_ROAMING_MODE:			if (sc->sc_firmware_type == WI_INTERSIL)				break;			/* not supported */			ltv->wi_len = 1;			return 0;		case WI_RID_MICROWAVE_OVEN:			/* not supported */			ltv->wi_len = 1;			return 0;		}	}	/* Tell the NIC to enter record read mode. */	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0))		return(EIO);	/* Seek to the record. */	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))		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).	 */	len = CSR_READ_2(sc, WI_DATA1);	if (len > ltv->wi_len)		return(ENOSPC);	code = CSR_READ_2(sc, WI_DATA1);	if (code != ltv->wi_type)		return(EIO);	ltv->wi_len = len;	ltv->wi_type = code;	/* Now read the data. */	ptr = &ltv->wi_val;	for (i = 0; i < ltv->wi_len - 1; i++)		ptr[i] = CSR_READ_2(sc, WI_DATA1);	if (ltv->wi_type == WI_RID_PORTTYPE && sc->wi_ptype == WI_PORTTYPE_IBSS	    && ltv->wi_val == sc->wi_ibss_port) {		/*		 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.		 * Since Lucent uses port type 1 for BSS *and* IBSS we		 * have to rely on wi_ptype to distinguish this for us.		 */		ltv->wi_val = htole16(WI_PORTTYPE_IBSS);	} else if (sc->sc_firmware_type != WI_LUCENT) {		switch (oltv->wi_type) {		case WI_RID_TX_RATE:		case WI_RID_CUR_TX_RATE:			switch (ltv->wi_val) {			case 1: oltv->wi_val = 1; break;			case 2: oltv->wi_val = 2; break;			case 3:	oltv->wi_val = 6; break;			case 4: oltv->wi_val = 5; break;			case 7: oltv->wi_val = 7; break;			case 8: oltv->wi_val = 11; break;			case 15: oltv->wi_val = 3; break;			default: oltv->wi_val = 0x100 + ltv->wi_val; break;			}			break;		case WI_RID_ENCRYPTION:			oltv->wi_len = 2;			if (ltv->wi_val & 0x01)				oltv->wi_val = 1;			else				oltv->wi_val = 0;			break;		case WI_RID_TX_CRYPT_KEY:			oltv->wi_len = 2;			oltv->wi_val = ltv->wi_val;			break;		case WI_RID_CNFAUTHMODE:                        oltv->wi_len = 2;			if (le16toh(ltv->wi_val) & 0x01)				oltv->wi_val = htole16(1);			else if (le16toh(ltv->wi_val) & 0x02)				oltv->wi_val = htole16(2);			break;		}	}	return(0);}/* * Same as read, except we inject data instead of reading it. */static intwi_write_record(sc, ltv)	struct wi_softc		*sc;	struct wi_ltv_gen	*ltv;{	uint16_t		*ptr;	uint16_t		val;	int			i;	struct wi_ltv_gen	p2ltv;	if (ltv->wi_type == WI_RID_PORTTYPE &&	    le16toh(ltv->wi_val) == WI_PORTTYPE_IBSS) {		/* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */		p2ltv.wi_type = WI_RID_PORTTYPE;		p2ltv.wi_len = 2;		p2ltv.wi_val = sc->wi_ibss_port;		ltv = &p2ltv;	} else if (sc->sc_firmware_type != WI_LUCENT) {		switch (ltv->wi_type) {		case WI_RID_TX_RATE:			p2ltv.wi_type = WI_RID_TX_RATE;			p2ltv.wi_len = 2;			switch (ltv->wi_val) {			case 1: p2ltv.wi_val = 1; break;			case 2: p2ltv.wi_val = 2; break;			case 3:	p2ltv.wi_val = 15; break;			case 5: p2ltv.wi_val = 4; break;			case 6: p2ltv.wi_val = 3; break;			case 7: p2ltv.wi_val = 7; break;			case 11: p2ltv.wi_val = 8; break;			default: return EINVAL;			}			p2ltv.wi_val = htole16(p2ltv.wi_val);			ltv = &p2ltv;			break;		case WI_RID_ENCRYPTION:			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;			p2ltv.wi_len = 2;			if (ltv->wi_val & htole16(0x01)) {				val = PRIVACY_INVOKED;				/*				 * If using shared key WEP we must set the				 * EXCLUDE_UNENCRYPTED bit.  Symbol cards				 * need this bit set even when not using				 * shared key. We can't just test for				 * IEEE80211_AUTH_SHARED since Symbol cards				 * have 2 shared key modes.				 */				if (sc->wi_authtype != IEEE80211_AUTH_OPEN ||				    sc->sc_firmware_type == WI_SYMBOL)					val |= EXCLUDE_UNENCRYPTED;				/* TX encryption is broken in Host AP mode. */				if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)					val |= HOST_ENCRYPT;			} else				val = HOST_ENCRYPT | HOST_DECRYPT;			p2ltv.wi_val = htole16(val);			ltv = &p2ltv;			break;		case WI_RID_TX_CRYPT_KEY:			if (ltv->wi_val > WI_NLTV_KEYS)				return (EINVAL);			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;			p2ltv.wi_len = 2;			p2ltv.wi_val = ltv->wi_val;			ltv = &p2ltv;			break;		case WI_RID_DEFLT_CRYPT_KEYS:		    {			int error;			int keylen;			struct wi_ltv_str	ws;			struct wi_ltv_keys	*wk =			    (struct wi_ltv_keys *)ltv;			keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;			for (i = 0; i < 4; i++) {				bzero(&ws, sizeof(ws));				ws.wi_len = (keylen > 5) ? 8 : 4;				ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;				memcpy(ws.wi_str,				    &wk->wi_keys[i].wi_keydat, keylen);				error = wi_write_record(sc,				    (struct wi_ltv_gen *)&ws);				if (error)					return error;			}			return 0;		    }		case WI_RID_CNFAUTHMODE:			p2ltv.wi_type = WI_RID_CNFAUTHMODE;			p2ltv.wi_len = 2;			if (le16toh(ltv->wi_val) == 1)				p2ltv.wi_val = htole16(0x01);			else if (le16toh(ltv->wi_val) == 2)				p2ltv.wi_val = htole16(0x02);			ltv = &p2ltv;			break;		case WI_RID_ROAMING_MODE:			if (sc->sc_firmware_type == WI_INTERSIL)				break;			/* not supported */			return 0;		case WI_RID_MICROWAVE_OVEN:			/* not supported */			return 0;		}	} else {		/* LUCENT */		switch (ltv->wi_type) {  		case WI_RID_TX_RATE:			switch (ltv->wi_val) {			case 1: ltv->wi_val = 1; break;  /* 1Mb/s fixed */			case 2: ltv->wi_val = 2; break;  /* 2Mb/s fixed */			case 3: ltv->wi_val = 3; break;  /* 11Mb/s auto */			case 5: ltv->wi_val = 4; break;  /* 5.5Mb/s fixed */			case 6: ltv->wi_val = 6; break;  /* 2Mb/s auto */			case 7: ltv->wi_val = 7; break;  /* 5.5Mb/s auto */			case 11: ltv->wi_val = 5; break; /* 11Mb/s fixed */			default: return EINVAL;			}		case WI_RID_TX_CRYPT_KEY:			if (ltv->wi_val > WI_NLTV_KEYS)				return (EINVAL);			break;		}	}	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))		return(EIO);	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);	ptr = &ltv->wi_val;	for (i = 0; i < ltv->wi_len - 1; i++)		CSR_WRITE_2(sc, WI_DATA1, ptr[i]);	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))		return(EIO);	return(0);}static intwi_seek(sc, id, off, chan)	struct wi_softc		*sc;	int			id, off, chan;{	int			i;	int			selreg, offreg;	int			status;	switch (chan) {	case WI_BAP0:		selreg = WI_SEL0;		offreg = WI_OFF0;		break;	case WI_BAP1:		selreg = WI_SEL1;		offreg = WI_OFF1;		break;	default:		device_printf(sc->dev, "invalid data path: %x\n", chan);		return(EIO);	}	CSR_WRITE_2(sc, selreg, id);	CSR_WRITE_2(sc, offreg, off);	for (i = 0; i < WI_TIMEOUT; i++) {		status = CSR_READ_2(sc, offreg);		if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))			break;		DELAY(WI_DELAY);	}	if (i == WI_TIMEOUT) {		device_printf(sc->dev, "timeout in wi_seek to %x/%x; last status %x\n",			id, off, status);		return(ETIMEDOUT);	}	return(0);}static intwi_read_data(sc, id, off, buf, len)	struct wi_softc		*sc;	int			id, off;	caddr_t			buf;	int			len;{	int			i;	u_int16_t		*ptr;	if (wi_seek(sc, id, off, WI_BAP1))		return(EIO);	ptr = (u_int16_t *)buf;	for (i = 0; i < len / 2; i++)		ptr[i] = CSR_READ_2(sc, WI_DATA1);	return(0);}/* * According to the comments in the HCF Light code, there is a bug in * the Hermes (or possibly in certain Hermes firmware revisions) where * the chip's internal autoincrement counter gets thrown off during * data writes: the autoincrement is missed, causing one data word to * be overwritten and subsequent words to be written to the wrong memory * locations. The end result is that we could end up transmitting bogus * frames without realizing it. The workaround for this is to write a * couple of extra guard words after the end of the transfer, then * attempt to read then back. If we fail to locate the guard words where * we expect them, we preform the transfer over again. */static intwi_write_data(sc, id, off, buf, len)	struct wi_softc		*sc;	int			id, off;	caddr_t			buf;	int			len;{	int			i;	u_int16_t		*ptr;#ifdef WI_HERMES_AUTOINC_WAR	int			retries;	retries = 512;again:#endif#ifdef WICACHE/*	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) {		device_printf(sc->dev, "off=%d, len=%d\t", off, len);	}*/	long msglen;	if (off == 0) {		struct wi_frame *tx_frame = (struct wi_frame *) buf;/*		printf("addr1 = %6D addr2 = %6D addr3 = %6D\n",			tx_frame->wi_addr1, ":", tx_frame->wi_addr2, ":",			tx_frame->wi_addr3, ":");		printf("addrd = %6D addrs = %6D\n",			tx_frame->wi_dst_addr, ":", tx_frame->wi_src_addr, ":");*/		char wrongaddr1[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

⌨️ 快捷键说明

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