Hi tech@,
Here is a patch that implement the phy_mode == IEEE80211_MODE_11A
part of bwi_rf_set_chan(). It is based on the linux b43/phy_a.c
switch_channel code.
It does not break my BCM4306. It would be awesome if someone could
try it with a card that have a 11A phy.
Comments/OK/NOK ?
Cheers,
Index: bwi.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/bwi.c,v
retrieving revision 1.97
diff -u -p -u -p -r1.97 bwi.c
--- bwi.c 31 Dec 2012 10:07:51 -0000 1.97
+++ bwi.c 9 Sep 2013 08:42:08 -0000
@@ -214,6 +214,7 @@ int bwi_rf_lo_isused(struct bwi_mac *,
void bwi_rf_write(struct bwi_mac *, uint16_t, uint16_t);
uint16_t bwi_rf_read(struct bwi_mac *, uint16_t);
int bwi_rf_attach(struct bwi_mac *);
+uint16_t bwi_rf_freq_r3a_value(uint16_t);
void bwi_rf_set_chan(struct bwi_mac *, uint, int);
void bwi_rf_get_gains(struct bwi_mac *);
void bwi_rf_init(struct bwi_mac *);
@@ -3875,10 +3876,34 @@ bwi_rf_attach(struct bwi_mac *mac)
return (0);
}
+uint16_t
+bwi_rf_freq_r3a_value(uint16_t freq)
+{
+ if (freq < 5091)
+ return (0x40);
+ else if (freq < 5321)
+ return (0x0);
+ else if (freq < 5806)
+ return (0x80);
+
+ return (0x40);
+}
+
void
bwi_rf_set_chan(struct bwi_mac *mac, uint chan, int work_around)
{
+#define SET_CHAN_DATAH_MAX 5
+#define SET_CHAN_DATAL_MAX 5
struct bwi_softc *sc = mac->mac_sc;
+ struct bwi_phy *phy = &mac->mac_phy;
+ uint16_t freq;
+ uint16_t r8;
+ int i, j;
+
+ static const uint8_t datah[SET_CHAN_DATAH_MAX] =
+ { 0x0, 0x40, 0x80, 0x90, 0xd0 };
+ static const uint8_t datal[SET_CHAN_DATAL_MAX] =
+ { 0x0, 0x1, 0x5, 0x6, 0xa };
if (chan == IEEE80211_CHAN_ANY)
return;
@@ -3886,23 +3911,69 @@ bwi_rf_set_chan(struct bwi_mac *mac, uin
MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_CHAN, chan);
/* TODO: 11A */
+ switch (phy->phy_mode) {
+ case IEEE80211_MODE_11A:
+ freq = BWI_RF_2GHZ_CHAN(chan);
+ CSR_WRITE_2(sc, BWI_RF_CHAN, freq);
- if (work_around)
- bwi_rf_workaround(mac, chan);
+ r8 = CSR_READ_2(sc, 0x8);
+ RF_WRITE(mac, 0x8, r8);
+ RF_SETBITS(mac, 0x2e, 0x0080);
- CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan));
+ /*
+ * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0f
+ * = freq * 0.025862
+ */
+ if (freq >= 4920 && freq <= 5500)
+ r8 = 3 * freq / 116; /* is equal to r8 = freq *
0.025862 */
- if (chan == 14) {
- if (sc->sc_locale == BWI_SPROM_LOCALE_JAPAN)
- HFLAGS_CLRBITS(mac, BWI_HFLAG_NOT_JAPAN);
- else
- HFLAGS_SETBITS(mac, BWI_HFLAG_NOT_JAPAN);
- CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, (1 << 11)); /* XXX */
- } else {
- CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0x840); /* XXX */
- }
- DELAY(8000); /* DELAY(2000); */
+ RF_WRITE(mac, 0x7, (r8 << 4) | r8);
+ RF_WRITE(mac, 0x20, (r8 << 4) | r8);
+ RF_WRITE(mac, 0x21, (r8 << 4) | r8);
+ RF_FILT_SETBITS(mac, 0x22, 0x000f, (r8 << 4));
+ RF_WRITE(mac, 0x2a, (r8 << 4));
+ RF_WRITE(mac, 0x2b, (r8 << 4));
+ RF_FILT_SETBITS(mac, 0x8, 0x00f0, r8 << 4);
+ RF_FILT_SETBITS(mac, 0x29, 0xff0f, 0x00b0);
+ RF_WRITE(mac, 0x35, 0xaa);
+ RF_WRITE(mac, 0x36, 0x85);
+ RF_FILT_SETBITS(mac, 0x3a, 0xff20, bwi_rf_freq_r3a_value(freq));
+ RF_CLRBITS(mac, 0x3d, 0xff00);
+ RF_FILT_SETBITS(mac, 0x81, 0xff7f, 0x0080);
+ RF_CLRBITS(mac, 0x35, 0x0010);
+ RF_FILT_SETBITS(mac, 0x35, 0xffef, 0x0010);
+
+ r8 = RF_READ(mac, 0x1e);
+ for (i = 0 ; i < 5 ; i++)
+ for (j = 0 ; j < 5 ; j++)
+ if (r8 == (datah[i] << 4 | datal[j])) {
+ CSR_WRITE_2(sc, 0x0069, (i - j) << 8 |
0x00c0);
+ goto end;
+ }
+ break;
+ case IEEE80211_MODE_11B:
+ case IEEE80211_MODE_11G:
+ if (work_around)
+ bwi_rf_workaround(mac, chan);
+ CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan));
+
+ if (chan == 14) {
+ if (sc->sc_locale == BWI_SPROM_LOCALE_JAPAN)
+ HFLAGS_CLRBITS(mac, BWI_HFLAG_NOT_JAPAN);
+ else
+ HFLAGS_SETBITS(mac, BWI_HFLAG_NOT_JAPAN);
+ CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, (1 << 11)); /* XXX */
+ } else {
+ CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0x840); /* XXX */
+ }
+ DELAY(8000); /* DELAY(2000); */
+ break;
+ default:
+ printf("%s: unsupported PHY mode\n", sc->sc_dev.dv_xname);
+ break;
+ }
+end:
mac->mac_rf.rf_curchan = chan;
}