Re: how to get supported channels from iwi firmware

From: YAMAMOTO Shigeru <shigeru_at_iij.ad.jp>
Date: Thu, 07 Dec 2006 21:23:08 +0900 (JST)
>>>>> "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>

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
_at__at_ -395,6 +395,32 _at__at_
 	    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;
_at__at_ -410,12 +436,40 _at__at_
 		/* 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);
_at__at_ -428,6 +482,28 _at__at_
 	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);
_at__at_ -435,6 +511,7 _at__at_
 		    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
_at__at_ -476,9 +476,19 _at__at_
 #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
_at__at_ -209,6 +209,11 _at__at_
 	}			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;
 };
 
 /*
Received on Thu Dec 07 2006 - 11:28:17 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:03 UTC