Hi John,

Please apply this to wireless-dev.

--

This patch adds AP mode support to the bcm43xx-d80211 driver.

Initial patch from Alexander Tsvyashchenko. Thanks a lot!

Signed-off-by: Michael Buesch <[EMAIL PROTECTED]>
Cc: "Francois Barre" <[EMAIL PROTECTED]>
Cc: "Alexander Tsvyashchenko" <[EMAIL PROTECTED]>

Index: 
wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
===================================================================
--- 
wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
    2006-06-17 21:26:10.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c 
2006-06-19 11:25:02.000000000 +0200
@@ -151,8 +151,10 @@
 {
        u32 status;
 
+       assert(offset % 4 == 0);
+
        status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-       if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP))
+       if (status & BCM43xx_SBF_XFER_REG_BYTESWAP)
                val = swab32(val);
 
        bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset);
@@ -312,7 +314,7 @@
        }
 }
 
-void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
+static void bcm43xx_time_lock(struct bcm43xx_private *bcm)
 {
        u32 status;
 
@@ -320,7 +322,19 @@
        status |= BCM43xx_SBF_TIME_UPDATE;
        bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
        mmiowb();
+}
+
+static void bcm43xx_time_unlock(struct bcm43xx_private *bcm)
+{
+       u32 status;
+
+       status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+       status &= ~BCM43xx_SBF_TIME_UPDATE;
+       bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+}
 
+static void bcm43xx_tsf_write_locked(struct bcm43xx_private *bcm, u64 tsf)
+{
        /* Be careful with the in-progress timer.
         * First zero out the low register, so we have a full
         * register-overflow duration to complete the operation.
@@ -350,10 +364,13 @@
                mmiowb();
                bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0);
        }
+}
 
-       status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-       status &= ~BCM43xx_SBF_TIME_UPDATE;
-       bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
+{
+       bcm43xx_time_lock(bcm);
+       bcm43xx_tsf_write_locked(bcm, tsf);
+       bcm43xx_time_unlock(bcm);
 }
 
 static void bcm43xx_measure_channel_change_time(struct bcm43xx_private *bcm)
@@ -415,10 +432,11 @@
 static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm)
 {
        static const u8 zero_addr[ETH_ALEN] = { 0 };
-       const u8 *mac = NULL;
-       const u8 *bssid = NULL;
+       const u8 *mac;
+       const u8 *bssid;
        u8 mac_bssid[ETH_ALEN * 2];
        int i;
+       u32 tmp;
 
        bssid = bcm->interface.bssid;
        if (!bssid)
@@ -431,12 +449,13 @@
        memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
 
        /* Write our MAC address and BSSID to template ram */
-       for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
-               bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i)));
-       for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
-               bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i)));
-       for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
-               bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i)));
+       for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) {
+               tmp =  (u32)(mac_bssid[i + 0]);
+               tmp |= (u32)(mac_bssid[i + 1]) << 8;
+               tmp |= (u32)(mac_bssid[i + 2]) << 16;
+               tmp |= (u32)(mac_bssid[i + 3]) << 24;
+               bcm43xx_ram_write(bcm, 0x20 + i, tmp);
+       }
 }
 
 static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time)
@@ -460,49 +479,6 @@
        bcm->short_slot = 0;
 }
 
-/* FIXME: To get the MAC-filter working, we need to implement the
- *        following functions (and rename them :)
- */
-#if 0
-static void bcm43xx_disassociate(struct bcm43xx_private *bcm)
-{
-       bcm43xx_mac_suspend(bcm);
-       bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
-
-       bcm43xx_ram_write(bcm, 0x0026, 0x0000);
-       bcm43xx_ram_write(bcm, 0x0028, 0x0000);
-       bcm43xx_ram_write(bcm, 0x007E, 0x0000);
-       bcm43xx_ram_write(bcm, 0x0080, 0x0000);
-       bcm43xx_ram_write(bcm, 0x047E, 0x0000);
-       bcm43xx_ram_write(bcm, 0x0480, 0x0000);
-
-       if (bcm->current_core->rev < 3) {
-               bcm43xx_write16(bcm, 0x0610, 0x8000);
-               bcm43xx_write16(bcm, 0x060E, 0x0000);
-       } else
-               bcm43xx_write32(bcm, 0x0188, 0x80000000);
-
-       bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
-
-#if 0
-       if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G &&
-           ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate))
-               bcm43xx_short_slot_timing_enable(bcm);
-#endif
-
-       bcm43xx_mac_enable(bcm);
-}
-
-static void bcm43xx_associate(struct bcm43xx_private *bcm,
-                             const u8 *mac)
-{
-       bcm43xx_mac_suspend(bcm);
-       bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac);
-       bcm43xx_write_mac_bssid_templates(bcm);
-       bcm43xx_mac_enable(bcm);
-}
-#endif
-
 /* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
  * Returns the _previously_ enabled IRQ mask.
  */
@@ -758,12 +734,29 @@
        return -ENODEV;
 }
 
+#ifdef CONFIG_BCM947XX
+static void bcm43xx_aton(const char *str, char *dest)
+{
+       int i = 0;
+       u16 *d = (u16 *)dest;
+
+       for (;;) {
+               dest[i++] = (char)simple_strtoul(str, NULL, 16);
+               str += 2;
+               if (!*str++ || i == 6)
+                       break;
+       }
+       for (i = 0; i < 3; i++)
+               d[i] = be16_to_cpu(d[i]);
+}
+#endif
+
 static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
 {
        u16 value;
        u16 *sprom;
 #ifdef CONFIG_BCM947XX
-       char *c;
+       const char *c;
 #endif
 
        sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
@@ -772,27 +765,46 @@
                printk(KERN_ERR PFX "sprom_extract OOM\n");
                return -ENOMEM;
        }
-#ifdef CONFIG_BCM947XX
-       sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2"));
-       sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags"));
-
-       if ((c = nvram_get("il0macaddr")) != NULL)
-               e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR]));
-
-       if ((c = nvram_get("et1macaddr")) != NULL)
-               e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR]));
-
-       sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0"));
-       sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1"));
-       sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2"));
 
-       sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0"));
-       sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1"));
-       sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2"));
-
-       sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev"));
-#else
        bcm43xx_sprom_read(bcm, sprom);
+
+#ifdef CONFIG_BCM947XX
+       /* In the case some settings are found in nvram, use them
+        * to override those read from sprom.
+        */
+       c = nvram_get("boardflags2");
+       if (c)
+               sprom[BCM43xx_SPROM_BOARDFLAGS2] = simple_strtoul(c, NULL, 0);
+        c = nvram_get("boardflags");
+       if (c)
+               sprom[BCM43xx_SPROM_BOARDFLAGS] = simple_strtoul(c, NULL, 0);
+       c = nvram_get("il0macaddr");
+       if (c)
+               bcm43xx_aton(c, (char *)&(sprom[BCM43xx_SPROM_IL0MACADDR]));
+       c = nvram_get("et1macaddr");
+       if (c)
+               bcm43xx_aton(c, (char *)&(sprom[BCM43xx_SPROM_ET1MACADDR]));
+       c = nvram_get("pa0b0");
+       if (c)
+               sprom[BCM43xx_SPROM_PA0B0] = simple_strtoul(c, NULL, 0);
+       c = nvram_get("pa0b1");
+       if (c)
+               sprom[BCM43xx_SPROM_PA0B1] = simple_strtoul(c, NULL, 0);
+       c = nvram_get("pa0b2");
+       if (c)
+               sprom[BCM43xx_SPROM_PA0B2] = simple_strtoul(c, NULL, 0);
+       c = nvram_get("pa1b0");
+       if (c)
+               sprom[BCM43xx_SPROM_PA1B0] = simple_strtoul(c, NULL, 0);
+       c = nvram_get("pa1b1");
+       if (c)
+               sprom[BCM43xx_SPROM_PA1B1] = simple_strtoul(c, NULL, 0);
+       c = nvram_get("pa1b2");
+       if (c)
+               sprom[BCM43xx_SPROM_PA1B2] = simple_strtoul(c, NULL, 0);
+       c = nvram_get("boardrev");
+       if (c)
+               sprom[BCM43xx_SPROM_BOARDREV] = simple_strtoul(c, NULL, 0);
 #endif
 
        /* boardflags2 */
@@ -914,21 +926,21 @@
        u16 value = 0;
        u32 buffer[5] = {
                0x00000000,
-               0x0000D400,
+               0x00D40000,
                0x00000000,
-               0x00000001,
+               0x01000000,
                0x00000000,
        };
 
        switch (phy->type) {
        case BCM43xx_PHYTYPE_A:
                max_loop = 0x1E;
-               buffer[0] = 0xCC010200;
+               buffer[0] = 0x000201CC;
                break;
        case BCM43xx_PHYTYPE_B:
        case BCM43xx_PHYTYPE_G:
                max_loop = 0xFA;
-               buffer[0] = 0x6E840B00; 
+               buffer[0] = 0x000B846E;
                break;
        default:
                assert(0);
@@ -1521,48 +1533,274 @@
        bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002);
 }
 
+static void bcm43xx_write_template_common(struct bcm43xx_private *bcm,
+                                         const u8* data, u16 size,
+                                         u16 ram_offset,
+                                         u16 shm_size_offset, u8 rate)
+{
+       u32 i, tmp;
+       struct bcm43xx_plcp_hdr4 plcp;
+
+       plcp.data = 0;
+       bcm43xx_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
+       bcm43xx_ram_write(bcm, ram_offset, le32_to_cpu(plcp.data));
+       ram_offset += sizeof(u32);
+       /* The PLCP is 6 bytes long, but we only wrote 4 bytes, yet.
+        * So leave the first two bytes of the next write blank.
+        */
+       tmp = (u32)(data[0]) << 16;
+       tmp |= (u32)(data[1]) << 24;
+       bcm43xx_ram_write(bcm, ram_offset, tmp);
+       ram_offset += sizeof(u32);
+       for (i = 2; i < size; i += sizeof(u32)) {
+               tmp = (u32)(data[i + 0]);
+               if (i + 1 < size)
+                       tmp |= (u32)(data[i + 1]) << 8;
+               if (i + 2 < size)
+                       tmp |= (u32)(data[i + 2]) << 16;
+               if (i + 3 < size)
+                       tmp |= (u32)(data[i + 3]) << 24;
+               bcm43xx_ram_write(bcm, ram_offset + i - 2, tmp);
+       }
+       bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset,
+                           size + sizeof(struct bcm43xx_plcp_hdr6));
+}
+
 static void bcm43xx_write_beacon_template(struct bcm43xx_private *bcm,
                                          u16 ram_offset,
-                                         u16 shm_size_offset)
+                                         u16 shm_size_offset, u8 rate)
 {
-       u32 tmp;
-       u16 i, size;
+       int len;
        const u8 *data;
 
+       assert(bcm->cached_beacon);
+       len = min((size_t)bcm->cached_beacon->len,
+                 0x200 - sizeof(struct bcm43xx_plcp_hdr6));
        data = (const u8 *)(bcm->cached_beacon->data);
-       size = min(bcm->cached_beacon->len, (unsigned int)17);
+       bcm43xx_write_template_common(bcm, data,
+                                     len, ram_offset,
+                                     shm_size_offset, rate);
+}
 
-       for (i = 0; i < size; i += sizeof(u32)) {
-               tmp = (u32)((data + i)[0]);
-               tmp |= (u32)((data + i)[1]) << 8;
-               tmp |= (u32)((data + i)[2]) << 16;
-               tmp |= (u32)((data + i)[3]) << 24;
-               bcm43xx_ram_write(bcm, ram_offset + i, tmp);
+static void bcm43xx_write_probe_resp_plcp(struct bcm43xx_private *bcm,
+                                         u16 shm_offset, u16 size, u8 rate)
+{
+       struct bcm43xx_plcp_hdr4 plcp;
+       u32 tmp;
+       u16 packet_time;
+
+       plcp.data = 0;
+       bcm43xx_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
+       /*
+        * 144 + 48 + 10 = preamble + PLCP + SIFS,
+        * taken from d80211 timings calculation.
+        *
+        * FIXME: long preamble assumed!
+        *
+        */
+       packet_time = 202 + (size + FCS_LEN) * 16 / rate;
+       if ((size + FCS_LEN) * 16 % rate >= rate / 2)
+               ++packet_time;
+
+       /* Write PLCP in two parts and timing for packet transfer */
+       tmp = le32_to_cpu(plcp.data);
+       bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_offset,
+                           tmp & 0xFFFF);
+       bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_offset + 2,
+                           tmp >> 16);
+       bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_offset + 6,
+                           packet_time);
+}
+
+/* Instead of using custom probe response template, this function
+ * just patches custom beacon template by:
+ * 1) Changing packet type
+ * 2) Patching duration field
+ * 3) Stripping TIM
+ */
+static u8 * bcm43xx_generate_probe_resp(struct bcm43xx_private *bcm,
+                                       u16* dest_size, u8 rate)
+{
+       const u8 *src_data;
+       u8 *dest_data;
+       u16 src_size, elem_size, src_pos, dest_pos, tmp;
+
+       assert(bcm->cached_beacon);
+       src_size = bcm->cached_beacon->len;
+       src_data = (const u8*)bcm->cached_beacon->data;
+
+       if (unlikely(src_size < 0x24)) {
+               dprintk(KERN_ERR PFX "bcm43xx_generate_probe_resp: "
+                                    "invalid beacon\n");
+               return NULL;
+       }
+
+       dest_data = kmalloc(src_size, GFP_ATOMIC);
+       if (unlikely(!dest_data))
+               return NULL;
+
+       /* 0x24 is offset of first variable-len Information-Element
+        * in beacon frame.
+        */
+       memcpy(dest_data, src_data, 0x24);
+       src_pos = dest_pos = 0x24;
+       for ( ; src_pos < src_size - 2; src_pos += elem_size) {
+               elem_size = src_data[src_pos + 1] + 2;
+               if (src_data[src_pos] != 0x05) { /* TIM */
+                       memcpy(dest_data + dest_pos, src_data + src_pos,
+                              elem_size);
+                       dest_pos += elem_size;
+               }
+       }
+       *dest_size = dest_pos;
+
+       /* Set the frame control. */
+       dest_data[0] = ((WLAN_FC_TYPE_MGMT << 2) |
+                       (WLAN_FC_STYPE_PROBE_RESP << 4));
+       dest_data[1] = 0;
+
+       /* Set the duration field.
+        *
+        * 144 + 48 + 10 = preamble + PLCP + SIFS,
+        * taken from d80211 timings calculation.
+        *
+        * FIXME: long preamble assumed!
+        *
+        */
+       tmp = 202 + (14 + FCS_LEN) * 16 / rate;
+       if ((14 + FCS_LEN) * 16 % rate >= rate / 2)
+               ++tmp;
+
+       dest_data[2] = tmp & 0xFF;
+       dest_data[3] = (tmp >> 8) & 0xFF;
+
+       return dest_data;
+}
+
+static void bcm43xx_write_probe_resp_template(struct bcm43xx_private *bcm,
+                                             u16 ram_offset,
+                                             u16 shm_size_offset, u8 rate)
+{
+       u8* probe_resp_data;
+       u16 size;
+
+       assert(bcm->cached_beacon);
+       size = bcm->cached_beacon->len;
+       probe_resp_data = bcm43xx_generate_probe_resp(bcm, &size, rate);
+       if (unlikely(!probe_resp_data))
+               return;
+
+       /* Looks like PLCP headers plus packet timings are stored for
+        * all possible basic rates
+        */
+       bcm43xx_write_probe_resp_plcp(bcm, 0x31A, size,
+                                     BCM43xx_CCK_RATE_1MB);
+       bcm43xx_write_probe_resp_plcp(bcm, 0x32C, size,
+                                     BCM43xx_CCK_RATE_2MB);
+       bcm43xx_write_probe_resp_plcp(bcm, 0x33E, size,
+                                     BCM43xx_CCK_RATE_5MB);
+       bcm43xx_write_probe_resp_plcp(bcm, 0x350, size,
+                                     BCM43xx_CCK_RATE_11MB);
+
+       size = min((size_t)size,
+                  0x200 - sizeof(struct bcm43xx_plcp_hdr6));
+       bcm43xx_write_template_common(bcm, probe_resp_data,
+                                     size, ram_offset,
+                                     shm_size_offset, rate);
+       kfree(probe_resp_data);
+}
+
+static int bcm43xx_refresh_cached_beacon(struct bcm43xx_private *bcm)
+{
+       struct ieee80211_tx_control control;
+
+       if (bcm->cached_beacon)
+               kfree_skb(bcm->cached_beacon);
+       bcm->cached_beacon = ieee80211_beacon_get(bcm->net_dev,
+                                                 bcm->interface.if_id,
+                                                 &control);
+       if (unlikely(!bcm->cached_beacon))
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void bcm43xx_update_templates(struct bcm43xx_private *bcm)
+{
+       u32 status;
+
+       assert(bcm->cached_beacon);
+
+       bcm43xx_write_beacon_template(bcm, 0x68, 0x18,
+                                     BCM43xx_CCK_RATE_1MB);
+       bcm43xx_write_beacon_template(bcm, 0x468, 0x1A,
+                                     BCM43xx_CCK_RATE_1MB);
+       bcm43xx_write_probe_resp_template(bcm, 0x268, 0x4A,
+                                         BCM43xx_CCK_RATE_11MB);
+
+       status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD);
+       status |= 0x03;
+       bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
+}
+
+static void bcm43xx_refresh_templates(struct bcm43xx_private *bcm)
+{
+       int err;
+
+       err = bcm43xx_refresh_cached_beacon(bcm);
+       if (unlikely(err))
+               return;
+       bcm43xx_update_templates(bcm);
+       kfree_skb(bcm->cached_beacon);
+       bcm->cached_beacon = NULL;
+}
+
+static void bcm43xx_set_ssid(struct bcm43xx_private *bcm,
+                            const u8 *ssid, u8 ssid_len)
+{
+       u32 tmp;
+       u16 i, len;
+
+       len = min((u16)ssid_len, (u16)0x100);
+       for (i = 0; i < len; i += sizeof(u32)) {
+               tmp = (u32)(ssid[i + 0]);
+               if (i + 1 < len)
+                       tmp |= (u32)(ssid[i + 1]) << 8;
+               if (i + 2 < len)
+                       tmp |= (u32)(ssid[i + 2]) << 16;
+               if (i + 3 < len)
+                       tmp |= (u32)(ssid[i + 3]) << 24;
+               bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+                                   0x380 + i, tmp);
+       }
+       bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+                           0x48, len);
+}
+
+static void bcm43xx_set_beacon_int(struct bcm43xx_private *bcm, u16 beacon_int)
+{
+       bcm43xx_time_lock(bcm);
+       if (bcm->current_core->rev >= 3) {
+               bcm43xx_write32(bcm, 0x188, (beacon_int << 16));
+       } else {
+               bcm43xx_write16(bcm, 0x606, (beacon_int >> 6));
+               bcm43xx_write16(bcm, 0x610, beacon_int);
        }
-       bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size);
+       bcm43xx_time_unlock(bcm);
 }
 
 static void handle_irq_beacon(struct bcm43xx_private *bcm)
 {
        u32 status;
+       int err;
 
        bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON;
        status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD);
 
        if (!bcm->cached_beacon) {
-               struct ieee80211_tx_control control;
-
-               /* No cached template available, yet.
-                * Request the 80211 subsystem to generate a new beacon
-                * frame and use it as template.
-                */
-               bcm->cached_beacon = ieee80211_beacon_get(bcm->net_dev,
-                                                         bcm->interface.if_id,
-                                                         &control);
-               if (unlikely(!bcm->cached_beacon)) {
-                       dprintkl(KERN_WARNING PFX "Could not generate beacon 
template.\n");
+               err = bcm43xx_refresh_cached_beacon(bcm);
+               if (unlikely(err))
                        goto ack;
-               }
        }
 
        if ((status & 0x1) && (status & 0x2)) {
@@ -1571,18 +1809,20 @@
                bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON,
                                BCM43xx_IRQ_BEACON);
                bcm->irq_savedstate |= BCM43xx_IRQ_BEACON;
-               if (likely(bcm->cached_beacon))
+               if (bcm->cached_beacon)
                        kfree_skb(bcm->cached_beacon);
                bcm->cached_beacon = NULL;
                return;
        }
        if (!(status & 0x1)) {
-               bcm43xx_write_beacon_template(bcm, 0x68, 0x18);
+               bcm43xx_write_beacon_template(bcm, 0x68, 0x18,
+                                             BCM43xx_CCK_RATE_1MB);
                status |= 0x1;
                bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
        }
        if (!(status & 0x2)) {
-               bcm43xx_write_beacon_template(bcm, 0x468, 0x1A);
+               bcm43xx_write_beacon_template(bcm, 0x468, 0x1A,
+                                             BCM43xx_CCK_RATE_1MB);
                status |= 0x2;
                bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
        }
@@ -4114,6 +4354,17 @@
                radio->power_level = conf->power_level;
                bcm43xx_phy_xmitpower(bcm);
        }
+
+       if (conf->ssid_hidden) {
+               bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+                               bcm43xx_read32(bcm, 
BCM43xx_MMIO_STATUS_BITFIELD)
+                               | BCM43xx_SBF_NO_SSID_BCAST);
+       } else {
+               bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+                               bcm43xx_read32(bcm, 
BCM43xx_MMIO_STATUS_BITFIELD)
+                               & ~BCM43xx_SBF_NO_SSID_BCAST);
+       }
+
 //FIXME: This does not seem to wake up:
 #if 0
        if (conf->power_level == 0) {
@@ -4128,6 +4379,11 @@
        //TODO: phymode
        //TODO: antennas
 
+       if (bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_AP)) {
+               bcm43xx_set_beacon_int(bcm, conf->beacon_int);
+               bcm43xx_refresh_templates(bcm);
+       }
+
        bcm43xx_unlock_irqonly(bcm, flags);
 
        return 0;
@@ -4293,8 +4549,11 @@
                bcm->interface.mac_addr = conf->mac_addr;
                bcm->interface.type = conf->type;
        }
-       if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
+       if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
                bcm43xx_select_opmode(bcm);
+               if (bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_AP))
+                       bcm43xx_refresh_templates(bcm);
+       }
        err = 0;
 
        dprintk(KERN_INFO PFX "Virtual interface added "
@@ -4343,6 +4602,11 @@
        if (conf->type != IEEE80211_IF_TYPE_MNTR) {
                assert(bcm->interface.if_id == if_id);
                bcm->interface.bssid = conf->bssid;
+               if (bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_AP)) {
+                       assert(conf->type == IEEE80211_IF_TYPE_AP);
+                       bcm43xx_set_ssid(bcm, conf->ssid, conf->ssid_len);
+                       bcm43xx_refresh_templates(bcm);
+               }
        }
        bcm43xx_unlock_irqsafe(bcm, flags);
 
Index: 
wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c
===================================================================
--- 
wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c
    2006-06-13 21:06:01.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c 
2006-06-18 18:43:12.000000000 +0200
@@ -112,14 +112,13 @@
        return 0;
 }
 
-static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
-                                     const u16 octets, const u8 bitrate,
-                                     const int ofdm_modulation)
+void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
+                              const u16 octets, const u8 bitrate)
 {
        __le32 *data = &(plcp->data);
        __u8 *raw = plcp->raw;
 
-       if (ofdm_modulation) {
+       if (bcm43xx_is_ofdm_rate(bitrate)) {
                *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
                assert(!(octets & 0xF000));
                *data |= (octets << 5);
@@ -224,11 +223,9 @@
 
        flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + FCS_LEN,
        bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 
*)(&txhdr->rts_cts_plcp),
-                                 flen, bitrate,
-                                 !bcm43xx_is_cck_rate(bitrate));
+                                 flen, bitrate);
        bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 
*)(&txhdr->rts_cts_fallback_plcp),
-                                 flen, fallback_bitrate,
-                                 !bcm43xx_is_cck_rate(fallback_bitrate));
+                                 flen, fallback_bitrate);
        fctl = WLAN_FC_TYPE_CTRL << 2;
        fctl |= WLAN_FC_STYPE_RTS << 4;
        dur = le16_to_cpu(wlhdr->duration_id);
@@ -332,10 +329,9 @@
        }
        /* Generate the PLCP header and the fallback PLCP header. */
        bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
-                                 plcp_fragment_len,
-                                 bitrate, ofdm_modulation);
+                                 plcp_fragment_len, bitrate);
        bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len,
-                                 fallback_bitrate, fallback_ofdm_modulation);
+                                 fallback_bitrate);
 
        /* Set the CONTROL field */
        if (ofdm_modulation)
Index: 
wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.h
===================================================================
--- 
wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.h
    2006-06-13 14:43:08.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.h 
2006-06-18 18:41:27.000000000 +0200
@@ -154,4 +154,7 @@
                struct sk_buff *skb,
                struct bcm43xx_rxhdr *rxhdr);
 
+void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
+                              const u16 octets, const u8 bitrate);
+
 #endif /* BCM43xx_XMIT_H_ */
Index: 
wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h
===================================================================
--- 
wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h
    2006-06-13 14:43:08.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h 
2006-06-18 18:41:03.000000000 +0200
@@ -33,24 +33,6 @@
 
 #include "bcm43xx.h"
 
-#ifdef CONFIG_BCM947XX
-#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
-
-static inline void e_aton(char *str, char *dest)
-{
-       int i = 0;
-       u16 *d = (u16 *) dest;
-
-       for (;;) {
-               dest[i++] = (char) simple_strtoul(str, NULL, 16);
-               str += 2;
-               if (!*str++ || i == 6)
-                       break;
-       }
-       for (i = 0; i < 3; i++)
-               d[i] = cpu_to_be16(d[i]);
-}
-#endif
 
 #define P4D_BYT3S(magic, nr_bytes)     u8 __p4dding##magic[nr_bytes]
 #define P4D_BYTES(line, nr_bytes)      P4D_BYT3S(line, nr_bytes)
@@ -143,6 +125,12 @@
                rate == BCM43xx_CCK_RATE_11MB);
 }
 
+static inline
+int bcm43xx_is_ofdm_rate(int rate)
+{
+       return !bcm43xx_is_cck_rate(rate);
+}
+
 void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf);
 void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);
 

-- 
Greetings Michael.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to