📄 wlandrv.c
字号:
}/************************************************************//* wi_read_nicid *//************************************************************/static void wi_read_nicid(struct wi_softc *sc){ struct wi_card_ident *id; char *p; int len; u_int16_t ver[4]; /* * getting chip identity */ memset(ver, 0, sizeof(ver)); len = sizeof(ver); wi_read_rid(sc, WI_RID_CARD_ID, ver, &len); Debug(("using ")); sc->sc_firmware_type = WI_NOTYPE; for (id = wi_card_ident; id->card_name != NULL; id++) { if (le16toh(ver[0]) == id->card_id) { Debug(("%s", id->card_name)); sc->sc_firmware_type = id->firm_type; break; } } if (sc->sc_firmware_type == WI_NOTYPE) { if (le16toh(ver[0]) & 0x8000) { Debug(("Unknown PRISM2 chip")); sc->sc_firmware_type = WI_INTERSIL; } else { Debug(("Unknown Lucent chip")); sc->sc_firmware_type = WI_LUCENT; } } /* * get primary firmware version (Only Prism chips) */ if (sc->sc_firmware_type != WI_LUCENT) { memset(ver, 0, sizeof(ver)); len = sizeof(ver); wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len); sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 + le16toh(ver[3]) * 100 + le16toh(ver[1]); } /* * get station firmware version */ memset(ver, 0, sizeof(ver)); len = sizeof(ver); wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len); sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 + le16toh(ver[3]) * 100 + le16toh(ver[1]); if (sc->sc_firmware_type == WI_INTERSIL && (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) { char ident[12]; memset(ident, 0, sizeof(ident)); len = sizeof(ident); /* * value should be the format like "V2.00-11" */ if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 && *(p = (char *) ident) >= 'A' && p[2] == '.' && p[5] == '-' && p[8] == '\0') { sc->sc_firmware_type = WI_SYMBOL; sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 + (p[3] - '0') * 1000 + (p[4] - '0') * 100 + (p[6] - '0') * 10 + (p[7] - '0'); } } Debug(("\n")); Debug(("%s Firmware: ", sc->sc_firmware_type == WI_LUCENT ? "Lucent" : (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"))); if (sc->sc_firmware_type != WI_LUCENT) { /* XXX */ Debug(("Primary (%ld.%ld.%ld), ", sc->sc_pri_firmware_ver / 10000, (sc->sc_pri_firmware_ver % 10000) / 100, sc->sc_pri_firmware_ver % 100)); } Debug(("Station (%ld.%ld.%ld)\n", sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100, sc->sc_sta_firmware_ver % 100));}/************************************************************//* wi_write_wep *//************************************************************/static int wi_write_wep(struct wi_softc *sc){ struct ieee80211com *ic = &sc->sc_ic; int error = 0; int i, keylen; u_int16_t val; struct wi_key wkey[IEEE80211_WEP_NKID]; switch (sc->sc_firmware_type) {#if (WLAN_SUPPORT_LUCENT >= 1) case WI_LUCENT: val = (ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0; error = wi_write_val(sc, WI_RID_ENCRYPTION, val); if (error) break; error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_wep_txkey); if (error) break; memset(wkey, 0, sizeof(wkey)); for (i = 0; i < IEEE80211_WEP_NKID; i++) { keylen = ic->ic_nw_keys[i].wk_len; wkey[i].wi_keylen = htole16(keylen); memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key, keylen); } error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS, wkey, sizeof(wkey)); break;#endif /* (WLAN_SUPPORT_LUCENT >= 1) */#if ((WLAN_SUPPORT_INTERSIL >= 1) || (WLAN_SUPPORT_SYMBOL >= 1)) case WI_INTERSIL: case WI_SYMBOL: if (ic->ic_flags & IEEE80211_F_WEPON) { /* * ONLY HWB3163 EVAL-CARD Firmware version * less than 0.8 variant2 * * If promiscuous mode disable, Prism2 chip * does not work with WEP . * It is under investigation for details. * (ichiro@netbsd.org) */ if (sc->sc_firmware_type == WI_INTERSIL && sc->sc_sta_firmware_ver < 802) { /* * firm ver < 0.8 variant 2 */ wi_write_val(sc, WI_RID_PROMISC, 1); } wi_write_val(sc, WI_RID_CNFAUTHMODE, sc->sc_cnfauthmode); val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED; /* * Encryption firmware has a bug for HostAP mode. */ if (sc->sc_firmware_type == WI_INTERSIL && ic->ic_opmode == IEEE80211_M_HOSTAP) { val |= HOST_ENCRYPT; } } else { wi_write_val(sc, WI_RID_CNFAUTHMODE, IEEE80211_AUTH_OPEN); val = HOST_ENCRYPT | HOST_DECRYPT; } error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val); if (error) { break; } error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY, ic->ic_wep_txkey); if (error) { break; } /* * It seems that the firmware accept 104bit key only if * all the keys have 104bit length. We get the length of * the transmit key and use it for all other keys. * Perhaps we should use software WEP for such situation. */ keylen = ic->ic_nw_keys[ic->ic_wep_txkey].wk_len; if (keylen > IEEE80211_WEP_KEYLEN) { keylen = 13; /* 104bit keys */ } else { keylen = IEEE80211_WEP_KEYLEN; } for (i = 0; i < IEEE80211_WEP_NKID; i++) { error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i, ic->ic_nw_keys[i].wk_key, keylen); if (error) { break; } } break;#endif /* ((WLAN_SUPPORT_INTERSIL >= 1) || (WLAN_SUPPORT_SYMBOL >= 1)) */ } return error;}/*==========================================================*//* DEFINE: All code exported *//*==========================================================*//************************************************************//* wlandrv_ProbeDevice *//* *//* Make a HW-Reset and test if a card is available. *//* *//* Return: ERROR, OK *//************************************************************/int wlandrv_ProbeDevice(void){ int error = -1; u_int16_t Value; /* * Set RESET */ RESET_EN_PORT |= RESET_BIT; RESET_PORT |= RESET_BIT; NutSleep(100); /* * Remove RESET */ RESET_PORT &= ~RESET_BIT; NutSleep(500); /* * Set the MAC into I/O mode */ pcmcia_WriteMem(WI_COR_OFFSET, WI_COR_VALUE); NutSleep(100); /* * Test if we can found a card */ pcmcia_WriteReg(WI_HFA384X_SWSUPPORT0_OFF, WI_PRISM2STA_MAGIC); Value = pcmcia_ReadReg(WI_HFA384X_SWSUPPORT0_OFF); if (Value == WI_PRISM2STA_MAGIC) { /* * We found a card :-) */ error = 0; } return (error);}/************************************************************//* wlandrv_Attach *//* *//* Catch all information about the card which *//* could be found. And set some default parameter *//* *//* Return: ERROR, OK *//************************************************************/int wlandrv_Attach(device_t dev){ struct wi_softc *sc = device_get_softc(dev); struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_rateset *rs; int i, nrates, buflen; u_int16_t val; u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE]; //u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = { // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 //}; /* Harald: This is unused */ int error; bDebugState = 2; sc->wi_cmd_count = 500; ic->ic_fixed_rate = -1; /* auto */ /* * Reset the NIC. */ if (wi_reset(sc) != 0) { return ENXIO; /* XXX */ } /* * Read the station address. * And do it twice. I've seen PRISM-based cards that return * an error when trying to read it the first time, which causes * the probe to fail. */ buflen = IEEE80211_ADDR_LEN; error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen); if (error != 0) { buflen = IEEE80211_ADDR_LEN; error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen); } if (error != 0) { Debug(("mac read failed %d\n", error)); return (error); } Debug(("802.11 address: %02X-%02X-%02X-%02X-%02X-%02X\n", ic->ic_myaddr[0], ic->ic_myaddr[1], ic->ic_myaddr[2], ic->ic_myaddr[3], ic->ic_myaddr[4], ic->ic_myaddr[5])); /* * Read NIC identification */ wi_read_nicid(sc); ic->ic_opmode = IEEE80211_M_STA; ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_AHDEMO; ic->ic_state = IEEE80211_S_INIT; /* * Query the card for available channels. */ buflen = sizeof(val); if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &val, &buflen) != 0) { val = htole16(0x1fff); /* assume 1-13 */ } if (val == 0) { Debug(("wi_attach: no available channels listed!")); } ic->ChannelList = (val << 1); /* * Read the default channel from the NIC. This may vary * depending on the country where the NIC was purchased, so * we can't hard-code a default and expect it to work for * everyone. * * If no channel is specified, let the 802.11 code select. */ buflen = sizeof(val); if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0) { val = le16toh(val); i = (1 << val); if ((val > 16) || ((ic->ChannelList & i) == 0)) { Debug(("wi_attach: invalid own channel %d!", val)); } ic->ic_ibss_chan = val; } else { Debug(("WI_RID_OWN_CHNL failed, using first channel!\n")); ic->ic_ibss_chan = 1; } /* * Set flags based on firmware version. */ switch (sc->sc_firmware_type) {#if (WLAN_SUPPORT_LUCENT >= 1) case WI_LUCENT: sc->sc_ntxbuf = 1; sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;#ifdef WI_HERMES_AUTOINC_WAR /* * XXX: not confirmed, but never seen for recent firmware */ if (sc->sc_sta_firmware_ver < 40000) { sc->sc_flags |= WI_FLAGS_BUG_AUTOINC; }#endif if (sc->sc_sta_firmware_ver >= 60000) { sc->sc_flags |= WI_FLAGS_HAS_MOR; } if (sc->sc_sta_firmware_ver >= 60006) { ic->ic_caps |= IEEE80211_C_IBSS; ic->ic_caps |= IEEE80211_C_MONITOR; } sc->sc_ibss_port = htole16(1); sc->sc_min_rssi = WI_LUCENT_MIN_RSSI; sc->sc_max_rssi = WI_LUCENT_MAX_RSSI; sc->sc_dbm_offset = WI_LUCENT_DBM_OFFSET; break;#endif /* (WLAN_SUPPORT_LUCENT >= 1) */#if (WLAN_SUPPORT_INTERSIL >= 1) case WI_INTERSIL: sc->sc_ntxbuf = WI_NTXBUF; sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR; sc->sc_flags |= WI_FLAGS_HAS_ROAMING; sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE; /* * Old firmware are slow, so give peace a chance. */ if (sc->sc_sta_firmware_ver < 10000) { sc->wi_cmd_count = 5000; } if (sc->sc_sta_firmware_ver > 10101) { sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST; } if (sc->sc_sta_firmware_ver >= 800) { ic->ic_caps |= IEEE80211_C_IBSS; ic->ic_caps |= IEEE80211_C_MONITOR; } /* * version 0.8.3 and newer are the only ones that are known * to currently work. Earlier versions can be made to work, * at least according to the Linux driver. */ if (sc->sc_sta_firmware_ver >= 803) { ic->ic_caps |= IEEE80211_C_HOSTAP; } sc->sc_ibss_port = htole16(0); sc->sc_min_rssi = WI_PRISM_MIN_RSSI; sc->sc_max_rssi = WI_PRISM_MAX_RSSI; sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET; break;#endif /* (WLAN_SUPPORT_INTERSIL >= 1) */#if (WLAN_SUPPORT_SYMBOL >= 1) case WI_SYMBOL: sc->sc_ntxbuf = 1; sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY; if (sc->sc_sta_firmware_ver >= 25000) { ic->ic_caps |= IEEE80211_C_IBSS; } sc->sc_ibss_port = htole16(4); sc->sc_min_rssi = WI_PRISM_MIN_RSSI; sc->sc_max_rssi = WI_PRISM_MAX_RSSI; sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -