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;
 }
 

Reply via email to