how to get supported channels from iwi firmware
YAMAMOTO Shigeru
shigeru at iij.ad.jp
Thu Dec 7 04:28:17 PST 2006
>>>>> "Sam" == Sam Leffler <sam at errno.com> writes:
>> I'm using iwi(Intel(R) PRO/Wireless 2915ABG). iwi driver does not
>> support 802.11j channels (34, 38, 42, 46) which channles are used in
>> Japan. # a channel set, 34, 38, 42, 46 is called 'J52' in Japan.
>>
>> So, I fix iwi to support 802.11j channels. But it is no good fix.
>>
>> I think it is better to get supported channels list from iwi firmware.
>> Does anybody know how to get supported channels list from iwi firmware?
Sam> It's in the EEPROM. I don't recall if the linux driver even does that
Sam> but maybe a recent version does so check there.
I check Linux driver code at http://ipw2200.sourceforge.net/
I create new patch to get channel information from EEPROM.
I test it at on my NotePC.
Currently, I hove no trouble.
But I don't to know my patch is right or not.
Because, Linux driver does not use channel information. ;-(
Linux driver only uses country code in EEPROM.
So default setting in my patch is using only country code.
If set 'USE_IWI_EEPROM_CHANNELS', my patch uses channel information in EEPROM.
Please try my patch if you have interest my patch.
Thanks,
-------
YAMAMOTO Shigeru <shigeru at iij.ad.jp>
-------------- next part --------------
Index: sys/dev/iwi/if_iwi.c
===================================================================
RCS file: /share/cvsup/FreeBSD/current/usr/src/sys/dev/iwi/if_iwi.c,v
retrieving revision 1.43
diff -u -r1.43 if_iwi.c
--- sys/dev/iwi/if_iwi.c 6 Dec 2006 21:23:51 -0000 1.43
+++ sys/dev/iwi/if_iwi.c 7 Dec 2006 02:27:34 -0000
@@ -395,6 +395,32 @@
IEEE80211_C_WPA | /* 802.11i */
IEEE80211_C_WME; /* 802.11e */
+ /* read EEPROM */
+ for (i = 0; i < IWI_EEPROM_SIZE/2; i ++) {
+ sc->sc_eeprom.eeprom16[i] = iwi_read_prom_word(sc, i);
+ }
+ device_printf(dev, "IWI_EEPROM:\n");
+ for (i = 0; i < IWI_EEPROM_SIZE/2; i ++) {
+ if (i % 16 == 0) {
+ printf("\n");
+ }
+ printf(" %04x", sc->sc_eeprom.eeprom16[i]);
+ }
+ printf("\n");
+ device_printf(dev, "IWI_EEPROM_VERSION: %d\n", sc->sc_eeprom.eeprom8[IWI_EEPROM_VERSION*2 + 1]);
+ device_printf(dev, "IWI_EEPROM_HW_VERSION: 0x%04x\n", sc->sc_eeprom.eeprom16[IWI_EEPROM_HW_VERSION]);
+ device_printf(dev, "IWI_EEPROM_COUNTRY_CODE: %c%c%c\n", sc->sc_eeprom.eeprom8[IWI_EEPROM_COUNTRY_CODE*2], sc->sc_eeprom.eeprom8[IWI_EEPROM_COUNTRY_CODE*2 + 1] , sc->sc_eeprom.eeprom8[IWI_EEPROM_COUNTRY_CODE*2 + 2]);
+ device_printf(dev, "IWI_EEPROM_BSS_CHANNELS_BG:");
+ for (i = 0; i < 2; i ++) {
+ printf(" %02x", sc->sc_eeprom.eeprom8[IWI_EEPROM_BSS_CHANNELS_BG*2 + i]);
+ }
+ printf("\n");
+ device_printf(dev, "IWI_EEPROM_BSS_CHANNELS_A:");
+ for (i = 0; i < 5; i ++) {
+ printf(" %02x", sc->sc_eeprom.eeprom8[IWI_EEPROM_BSS_CHANNELS_A*2 + i]);
+ }
+ printf("\n");
+
/* read MAC address from EEPROM */
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0);
ic->ic_myaddr[0] = val & 0xff;
@@ -410,12 +436,40 @@
/* set supported .11a rates (2915ABG only) */
ic->ic_sup_rates[IEEE80211_MODE_11A] = iwi_rateset_11a;
+#if defined(USE_IWI_EEPROM_CHANNELS)
+ for (i = 0; i < 5*8; i ++) {
+ if ((sc->sc_eeprom.eeprom8[IWI_EEPROM_IBSS_CHANNELS_A*2 + i/8] >> (i % 8)) & 0x01) {
+ int ch = (i+1)*2;
+
+ ic->ic_channels[ch].ic_freq =
+ ieee80211_ieee2mhz(ch, IEEE80211_CHAN_5GHZ);
+ ic->ic_channels[ch].ic_flags = IEEE80211_CHAN_A;
+ }
+ if ((sc->sc_eeprom.eeprom8[IWI_EEPROM_BSS_CHANNELS_A*2 + i/8] >> (i % 8)) & 0x01) {
+ int ch = (i+1)*2;
+
+ ic->ic_channels[ch].ic_freq =
+ ieee80211_ieee2mhz(ch, IEEE80211_CHAN_5GHZ);
+ ic->ic_channels[ch].ic_flags = IEEE80211_CHAN_A;
+ }
+ }
+#else
+ if (memcmp(&(sc->sc_eeprom.eeprom8[IWI_EEPROM_COUNTRY_CODE*2]), "ZZJ", 3) == 0) {
+ /* set supported .11a(802.11j) channels, which is used in Japan */
+ for (i = 34; i <= 46; i += 4) {
+ ic->ic_channels[i].ic_freq =
+ ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
+ ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
+ }
+ }
+
/* set supported .11a channels */
for (i = 36; i <= 64; i += 4) {
ic->ic_channels[i].ic_freq =
ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
}
+#endif
for (i = 149; i <= 165; i += 4) {
ic->ic_channels[i].ic_freq =
ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
@@ -428,6 +482,28 @@
ic->ic_sup_rates[IEEE80211_MODE_11G] = iwi_rateset_11g;
/* set supported .11b and .11g channels (1 through 14) */
+#if defined(USE_IWI_EEPROM_CHANNELS)
+ for (i = 0; i < 2*8 - 1; i ++) {
+ if ((sc->sc_eeprom.eeprom8[IWI_EEPROM_IBSS_CHANNELS_BG*2 + i/8] >> (i % 8)) & 0x01) {
+ int ch = (i+1);
+
+ ic->ic_channels[ch].ic_freq =
+ ieee80211_ieee2mhz(ch, IEEE80211_CHAN_2GHZ);
+ ic->ic_channels[ch].ic_flags =
+ IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
+ IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
+ }
+ if ((sc->sc_eeprom.eeprom8[IWI_EEPROM_BSS_CHANNELS_BG*2 + i/8] >> (i % 8)) & 0x01) {
+ int ch = (i+1);
+
+ ic->ic_channels[ch].ic_freq =
+ ieee80211_ieee2mhz(ch, IEEE80211_CHAN_2GHZ);
+ ic->ic_channels[ch].ic_flags =
+ IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
+ IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
+ }
+ }
+#else
for (i = 1; i <= 14; i++) {
ic->ic_channels[i].ic_freq =
ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
@@ -435,6 +511,7 @@
IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
}
+#endif
ieee80211_ifattach(ic);
ic->ic_bmissthreshold = 10; /* override default */
Index: sys/dev/iwi/if_iwireg.h
===================================================================
RCS file: /share/cvsup/FreeBSD/current/usr/src/sys/dev/iwi/if_iwireg.h,v
retrieving revision 1.13
diff -u -r1.13 if_iwireg.h
--- sys/dev/iwi/if_iwireg.h 23 Oct 2006 00:34:07 -0000 1.13
+++ sys/dev/iwi/if_iwireg.h 21 Nov 2006 08:31:51 -0000
@@ -476,9 +476,19 @@
#define IWI_MEM_EEPROM_EVENT 0x00300004
#define IWI_MEM_EEPROM_CTL 0x00300040
+#define IWI_EEPROM_SIZE (256)
+
+#define IWI_EEPROM_PME_CAPABILITY 0x09 /* 1 octet (msb) */
#define IWI_EEPROM_MAC 0x21
+#define IWI_EEPROM_VERSION 0x24 /* 1 octet (msb) */
#define IWI_EEPROM_NIC 0x25 /* nic type (lsb) */
#define IWI_EEPROM_SKU 0x25 /* nic type (msb) */
+#define IWI_EEPROM_COUNTRY_CODE 0x26 /* 3 octets (lsb) */
+#define IWI_EEPROM_IBSS_CHANNELS_BG 0x28 /* 2 octets (lsb) */
+#define IWI_EEPROM_IBSS_CHANNELS_A 0x29 /* 5 octets (msb) */
+#define IWI_EEPROM_BSS_CHANNELS_BG 0x2c /* 2 octets (lsb) */
+#define IWI_EEPROM_BSS_CHANNELS_A 0x2d /* 5 octets (msb) */
+#define IWI_EEPROM_HW_VERSION 0x72 /* 2 octets (lsb) */
#define IWI_EEPROM_DELAY 1 /* minimum hold time (microsecond) */
Index: sys/dev/iwi/if_iwivar.h
===================================================================
RCS file: /share/cvsup/FreeBSD/current/usr/src/sys/dev/iwi/if_iwivar.h,v
retrieving revision 1.11
diff -u -r1.11 if_iwivar.h
--- sys/dev/iwi/if_iwivar.h 27 Apr 2006 21:43:37 -0000 1.11
+++ sys/dev/iwi/if_iwivar.h 21 Nov 2006 08:54:48 -0000
@@ -209,6 +209,11 @@
} sc_txtapu;
#define sc_txtap sc_txtapu.th
int sc_txtap_len;
+
+ union {
+ uint8_t eeprom8[IWI_EEPROM_SIZE];
+ uint16_t eeprom16[IWI_EEPROM_SIZE/2];
+ } sc_eeprom;
};
/*
More information about the freebsd-current
mailing list