diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2004-07-25 13:36:09 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2004-07-25 13:36:09 +0000 |
commit | 053a9c8642782d31af3b5c24e7e6e52ffc34cae1 (patch) | |
tree | f3aa0bd3b7c46fb8a4cfad49d9300a4c35453bc2 /sys/dev/ic | |
parent | b3a821e85ea1b15274b731efe7d4d22158c5c27e (diff) |
Begin conditioning device configuration on revision number. Three types
are known: ADM8211A (1.1/1.5), ADM8211B (2.0), ADM8211C (3.0). The B and
C parts, while not yet supported, have AP capability. From NetBSD (dyoung).
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/atw.c | 139 | ||||
-rw-r--r-- | sys/dev/ic/atwvar.h | 15 |
2 files changed, 124 insertions, 30 deletions
diff --git a/sys/dev/ic/atw.c b/sys/dev/ic/atw.c index 5e6d49bdc07..9a8c1f41127 100644 --- a/sys/dev/ic/atw.c +++ b/sys/dev/ic/atw.c @@ -1,5 +1,5 @@ -/* $OpenBSD: atw.c,v 1.25 2004/07/25 00:30:48 millert Exp $ */ -/* $NetBSD: atw.c,v 1.68 2004/07/23 06:57:50 dyoung Exp $ */ +/* $OpenBSD: atw.c,v 1.26 2004/07/25 13:36:08 millert Exp $ */ +/* $NetBSD: atw.c,v 1.69 2004/07/23 07:07:55 dyoung Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc. @@ -43,7 +43,7 @@ #include <sys/cdefs.h> #if defined(__NetBSD__) -__KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.68 2004/07/23 06:57:50 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.69 2004/07/23 07:07:55 dyoung Exp $"); #endif #include "bpfilter.h" @@ -369,22 +369,27 @@ int atw_read_srom(struct atw_softc *sc) { struct seeprom_descriptor sd; - u_int32_t reg; + u_int32_t test0, fail_bits; (void)memset(&sd, 0, sizeof(sd)); - reg = ATW_READ(sc, ATW_TEST0); + test0 = ATW_READ(sc, ATW_TEST0); - if (reg & ATW_TEST0_EPNE) { - printf("%s: SROM not detected\n", sc->sc_dev.dv_xname); + switch (sc->sc_rev) { + case ATW_REVISION_BA: + case ATW_REVISION_CA: + fail_bits = ATW_TEST0_EPNE; + break; + default: + fail_bits = ATW_TEST0_EPNE|ATW_TEST0_EPSNM; + break; + } + if ((test0 & fail_bits) != 0) { + printf("%s: bad or missing/bad SROM\n", sc->sc_dev.dv_xname); return -1; } -#ifdef ATW_DEBUG - if (reg & ATW_TEST0_EPSNM) - printf("%s: bad SROM signature\n", sc->sc_dev.dv_xname); -#endif - switch (reg & ATW_TEST0_EPTYP_MASK) { + switch (test0 & ATW_TEST0_EPTYP_MASK) { case ATW_TEST0_EPTYP_93c66: ATW_DPRINTF(("%s: 93c66 SROM\n", sc->sc_dev.dv_xname)); sc->sc_sromsz = 512; @@ -397,7 +402,7 @@ atw_read_srom(struct atw_softc *sc) break; default: printf("%s: unknown SROM type %d\n", sc->sc_dev.dv_xname, - MASK_AND_RSHIFT(reg, ATW_TEST0_EPTYP_MASK)); + MASK_AND_RSHIFT(test0, ATW_TEST0_EPTYP_MASK)); return -1; } @@ -541,7 +546,7 @@ atw_attach(struct atw_softc *sc) }; struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; - int country_code, error, i, nrate; + int country_code, error, i, nrate, srom_major; u_int32_t reg; static const char *type_strings[] = {"Intersil (not supported)", "RFMD", "Marvel (not supported)"}; @@ -620,6 +625,17 @@ atw_attach(struct atw_softc *sc) sc->sc_rxsoft[i].rxs_mbuf = NULL; } + switch (sc->sc_rev) { + case ATW_REVISION_AB: + case ATW_REVISION_AF: + sc->sc_sramlen = ATW_SRAM_A_SIZE; + break; + case ATW_REVISION_BA: + case ATW_REVISION_CA: + sc->sc_sramlen = ATW_SRAM_B_SIZE; + break; + } + /* Reset the chip to a known state. */ atw_reset(sc); @@ -697,6 +713,21 @@ atw_attach(struct atw_softc *sc) htole16(sc->sc_srom[ATW_SR_MAC01]), htole16(sc->sc_srom[ATW_SR_MAC10]))); + srom_major = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_FORMAT_VERSION], + ATW_SR_MAJOR_MASK); + + if (srom_major < 2) + sc->sc_rf3000_options1 = 0; + else if (sc->sc_rev == ATW_REVISION_BA) { + sc->sc_rf3000_options1 = + MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CR28_CR03], + ATW_SR_CR28_MASK); + } else + sc->sc_rf3000_options1 = 0; + + sc->sc_rf3000_options2 = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CTRY_CR29], + ATW_SR_CR29_MASK); + country_code = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CTRY_CR29], ATW_SR_CTRY_MASK); @@ -884,6 +915,24 @@ atw_node_free(struct ieee80211com *ic, struct ieee80211_node *ni) (*sc->sc_node_free)(ic, ni); } + +static void +atw_test1_reset(struct atw_softc *sc) +{ + switch (sc->sc_rev) { + case ATW_REVISION_BA: + if (1 /* XXX condition on transceiver type */) { + ATW_SET(sc, ATW_TEST1, ATW_TEST1_TESTMODE_MONITOR); + } + break; + case ATW_REVISION_CA: + ATW_CLR(sc, ATW_TEST1, ATW_TEST1_TESTMODE_MASK); + break; + default: + break; + } +} + /* * atw_reset: * @@ -919,6 +968,7 @@ atw_reset(struct atw_softc *sc) if (ATW_ISSET(sc, ATW_PAR, ATW_PAR_SWR)) printf("%s: reset failed to complete\n", sc->sc_dev.dv_xname); + atw_test1_reset(sc); /* * Initialize the PCI Access Register. */ @@ -959,7 +1009,7 @@ atw_clear_sram(struct atw_softc *sc) { memset(sc->sc_sram, 0, sizeof(sc->sc_sram)); /* XXX not for revision 0x20. */ - atw_write_sram(sc, 0, sc->sc_sram, sizeof(sc->sc_sram)); + atw_write_sram(sc, 0, sc->sc_sram, sc->sc_sramlen); } /* TBD atw_init @@ -1130,11 +1180,28 @@ atw_response_times_init(struct atw_softc *sc) void atw_bbp_io_init(struct atw_softc *sc) { + uint32_t mmiraddr2; + + /* XXX The reference driver does this, but is it *really* + * necessary? + */ + switch (sc->sc_rev) { + case ATW_REVISION_AB: + case ATW_REVISION_AF: + mmiraddr2 = 0x0; + break; + default: + mmiraddr2 = ATW_READ(sc, ATW_MMIRADDR2); + mmiraddr2 &= + ~(ATW_MMIRADDR2_PROREXT|ATW_MMIRADDR2_PRORLEN_MASK); + break; + } + switch (sc->sc_bbptype) { case ATW_BBPTYPE_INTERSIL: ATW_WRITE(sc, ATW_MMIWADDR, ATW_MMIWADDR_INTERSIL); ATW_WRITE(sc, ATW_MMIRADDR1, ATW_MMIRADDR1_INTERSIL); - ATW_WRITE(sc, ATW_MMIRADDR2, ATW_MMIRADDR2_INTERSIL); + mmiraddr2 |= ATW_MMIRADDR2_INTERSIL; break; case ATW_BBPTYPE_MARVEL: /* TBD find out the Marvel settings. */ @@ -1143,9 +1210,10 @@ atw_bbp_io_init(struct atw_softc *sc) default: ATW_WRITE(sc, ATW_MMIWADDR, ATW_MMIWADDR_RFMD); ATW_WRITE(sc, ATW_MMIRADDR1, ATW_MMIRADDR1_RFMD); - ATW_WRITE(sc, ATW_MMIRADDR2, ATW_MMIRADDR2_RFMD); + mmiraddr2 |= ATW_MMIRADDR2_RFMD; break; } + ATW_WRITE(sc, ATW_MMIRADDR2, mmiraddr2); ATW_WRITE(sc, ATW_MACTEST, ATW_MACTEST_MMI_USETXCLK); } @@ -1626,15 +1694,13 @@ atw_rf3000_init(struct atw_softc *sc) /* XXX Reference driver remarks that Abocom sets this to 50. * Meaning 0x50, I think.... 50 = 0x32, which would set a bit * in the "reserved" area of register RF3000_OPTIONS1. - * - * EEPROMs for the ADM8211B contain a setting for this register. */ - rc = atw_rf3000_write(sc, RF3000_OPTIONS1, 0x0); + rc = atw_rf3000_write(sc, RF3000_OPTIONS1, sc->sc_rf3000_options1); if (rc != 0) goto out; - rc = atw_rf3000_write(sc, RF3000_OPTIONS2, RF3000_OPTIONS2_LNAGS_DELAY); + rc = atw_rf3000_write(sc, RF3000_OPTIONS2, sc->sc_rf3000_options2); if (rc != 0) goto out; @@ -2028,7 +2094,7 @@ atw_write_sram(struct atw_softc *sc, u_int ofs, u_int8_t *buf, u_int buflen) KASSERT(ofs % 2 == 0 && buflen % 2 == 0); - KASSERT(buflen + ofs <= ATW_SRAM_A_SIZE); + KASSERT(buflen + ofs <= sc->sc_sramlen); ptr = &sc->sc_sram[ofs]; @@ -2096,12 +2162,17 @@ atw_write_wep(struct atw_softc *sc) reg |= LSHIFT(ic->ic_wep_txkey, ATW_MACTEST_KEYID_MASK); ATW_WRITE(sc, ATW_MACTEST, reg); - /* RX bypass WEP if revision != 0x20. (I assume revision != 0x20 - * throughout.) - */ - sc->sc_wepctl = ATW_WEPCTL_WEPENABLE | ATW_WEPCTL_WEPRXBYP; - if (sc->sc_if.if_flags & IFF_LINK2) - sc->sc_wepctl &= ~ATW_WEPCTL_WEPRXBYP; + sc->sc_wepctl = ATW_WEPCTL_WEPENABLE; + + switch (sc->sc_rev) { + case ATW_REVISION_AB: + case ATW_REVISION_AF: + /* Bypass WEP on Rx. */ + sc->sc_wepctl |= ATW_WEPCTL_WEPRXBYP; + break; + default: + break; + } atw_write_sram(sc, ATW_SRAM_ADDR_SHARED_KEY, (u_int8_t*)&buf[0][0], sizeof(buf)); @@ -3007,6 +3078,16 @@ atw_linkintr(struct atw_softc *sc, u_int32_t linkstatus) } } +static __inline int +atw_hw_decrypted(struct atw_softc *sc, struct ieee80211_frame *wh) +{ + if ((sc->sc_ic.ic_flags & IEEE80211_F_WEPON) == 0) + return 0; + if ((wh->i_fc[1] & IEEE80211_FC1_WEP) == 0) + return 0; + return (sc->sc_wepctl & ATW_WEPCTL_WEPRXBYP) == 0; +} + /* * atw_rxintr: * @@ -3164,6 +3245,8 @@ atw_rxintr(struct atw_softc *sc) wh = mtod(m, struct ieee80211_frame *); ni = ieee80211_find_rxnode(ic, wh); + if (atw_hw_decrypted(sc, wh)) + wh->i_fc[1] &= ~IEEE80211_FC1_WEP; ieee80211_input(ifp, m, ni, (int)rssi, 0); /* * The frame may have caused the node to be marked for diff --git a/sys/dev/ic/atwvar.h b/sys/dev/ic/atwvar.h index 4e5a31998ea..e9c1596438c 100644 --- a/sys/dev/ic/atwvar.h +++ b/sys/dev/ic/atwvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: atwvar.h,v 1.6 2004/07/25 00:16:35 millert Exp $ */ -/* $NetBSD: atwvar.h,v 1.12 2004/07/23 05:06:26 dyoung Exp $ */ +/* $OpenBSD: atwvar.h,v 1.7 2004/07/25 13:36:08 millert Exp $ */ +/* $NetBSD: atwvar.h,v 1.13 2004/07/23 07:07:55 dyoung Exp $ */ /* * Copyright (c) 2003, 2004 The NetBSD Foundation, Inc. All rights reserved. @@ -177,6 +177,13 @@ struct atw_tx_radiotap_header { u_int16_t at_chan_flags; } __attribute__((__packed__)); +enum atw_revision { + ATW_REVISION_AB = 0x11, /* ADM8211A */ + ATW_REVISION_AF = 0x15, /* ADM8211A? */ + ATW_REVISION_BA = 0x20, /* ADM8211B */ + ATW_REVISION_CA = 0x30 /* ADM8211C/CR */ +}; + struct atw_softc { struct device sc_dev; struct ieee80211com sc_ic; @@ -268,7 +275,11 @@ struct atw_softc { /* ADM8211 state variables. */ u_int8_t sc_sram[ATW_SRAM_MAXSIZE]; + u_int sc_sramlen; u_int8_t sc_bssid[IEEE80211_ADDR_LEN]; + u_int8_t sc_rev;; + u_int8_t sc_rf3000_options1; + u_int8_t sc_rf3000_options2; struct timeval sc_last_beacon; struct timeout sc_scan_to; |