Index: src/sys/dev/usb/if_zyd.c =================================================================== RCS file: /home/ncvs/src/sys/dev/usb/if_zyd.c,v retrieving revision 1.8 diff -u -r1.8 if_zyd.c --- src/sys/dev/usb/if_zyd.c 6 Nov 2007 07:30:12 -0000 1.8 +++ src/sys/dev/usb/if_zyd.c 6 Nov 2007 16:30:40 -0000 @@ -204,6 +204,7 @@ static int zyd_set_bssid(struct zyd_softc *, const uint8_t *); static int zyd_switch_radio(struct zyd_softc *, int); static void zyd_set_led(struct zyd_softc *, int, int); +static void zyd_set_multi(struct zyd_softc *); static int zyd_set_rxfilter(struct zyd_softc *); static void zyd_set_chan(struct zyd_softc *, struct ieee80211_channel *); static int zyd_set_beacon_interval(struct zyd_softc *, int); @@ -1494,6 +1495,7 @@ { struct zyd_rf *rf = &sc->sc_rf; const struct zyd_phy_pair *phyp; + uint32_t tmp; int error; /* specify that the plug and play is finished */ @@ -1518,6 +1520,10 @@ if ((error = zyd_write16(sc, phyp->reg, phyp->val)) != 0) goto fail; } + if (sc->fix_cr157) { + if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0) + (void)zyd_write32(sc, ZYD_CR157, tmp >> 8); + } zyd_unlock_phy(sc); /* HMAC init */ @@ -1533,7 +1539,7 @@ zyd_write32(sc, ZYD_MACB_TXPWR_CTL2, 0x003f001f); zyd_write32(sc, ZYD_MACB_TXPWR_CTL1, 0x001f000f); zyd_write32(sc, ZYD_MACB_AIFS_CTL1, 0x00280028); - zyd_write32(sc, ZYD_MACB_AIFS_CTL2, 0x008C003C); + zyd_write32(sc, ZYD_MACB_AIFS_CTL2, 0x008C003c); zyd_write32(sc, ZYD_MACB_TXOP, 0x01800824); } @@ -1591,8 +1597,10 @@ ic->ic_myaddr[5] = tmp >> 8; (void)zyd_read32(sc, ZYD_EEPROM_POD, &tmp); - sc->rf_rev = tmp & 0x0f; - sc->pa_rev = (tmp >> 16) & 0x0f; + sc->rf_rev = tmp & 0x0f; + sc->fix_cr47 = (tmp >> 8 ) & 0x01; + sc->fix_cr157 = (tmp >> 13) & 0x01; + sc->pa_rev = (tmp >> 16) & 0x0f; /* read regulatory domain (currently unused) */ (void)zyd_read32(sc, ZYD_EEPROM_SUBID, &tmp); @@ -1677,6 +1685,47 @@ (void)zyd_write32(sc, ZYD_MAC_TX_PE_CONTROL, tmp); } +static void +zyd_set_multi(struct zyd_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = ic->ic_ifp; + struct ifmultiaddr *ifma; + uint32_t low, high, tmp; + uint8_t v; + + if (!(ifp->if_flags & IFF_UP)) + return; + + low = 0x00000000; + high = 0x80000000; + + if (ic->ic_opmode == IEEE80211_M_MONITOR || + (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { + low = 0xffffffff; + high = 0xffffffff; + } else { + IF_ADDR_LOCK(ifp); + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + v = ((uint8_t *)LLADDR((struct sockaddr_dl *) + ifma->ifma_addr))[5] >> 2; + if (v < 32) + low |= 1 << v; + else + high |= 1 << (v - 32); + } + IF_ADDR_UNLOCK(ifp); + } + + /* reprogram multicast global hash table, if necessary. */ + if (zyd_read32(sc, ZYD_MAC_GHTBL, &tmp) == 0 && tmp != low) + (void)zyd_write32(sc, ZYD_MAC_GHTBL, low); + if (zyd_read32(sc, ZYD_MAC_GHTBH, &tmp) == 0 && tmp != high) + (void)zyd_write32(sc, ZYD_MAC_GHTBH, high); +} + static int zyd_set_rxfilter(struct zyd_softc *sc) { @@ -1705,6 +1754,7 @@ { struct ieee80211com *ic = &sc->sc_ic; struct zyd_rf *rf = &sc->sc_rf; + uint32_t tmp; u_int chan; chan = ieee80211_chan2ieee(ic, c); @@ -1720,18 +1770,27 @@ (*rf->set_channel)(rf, chan); /* update Tx power */ - (void)zyd_write32(sc, ZYD_CR31, sc->pwr_int[chan - 1]); - (void)zyd_write32(sc, ZYD_CR68, sc->pwr_cal[chan - 1]); + (void)zyd_write16(sc, ZYD_CR31, sc->pwr_int[chan - 1]); if (sc->mac_rev == ZYD_ZD1211B) { - (void)zyd_write32(sc, ZYD_CR67, sc->ofdm36_cal[chan - 1]); - (void)zyd_write32(sc, ZYD_CR66, sc->ofdm48_cal[chan - 1]); - (void)zyd_write32(sc, ZYD_CR65, sc->ofdm54_cal[chan - 1]); + (void)zyd_write16(sc, ZYD_CR67, sc->ofdm36_cal[chan - 1]); + (void)zyd_write16(sc, ZYD_CR66, sc->ofdm48_cal[chan - 1]); + (void)zyd_write16(sc, ZYD_CR65, sc->ofdm54_cal[chan - 1]); + + (void)zyd_write16(sc, ZYD_CR68, sc->pwr_cal[chan - 1]); + + (void)zyd_write16(sc, ZYD_CR69, 0x28); + (void)zyd_write16(sc, ZYD_CR69, 0x2a); + } - (void)zyd_write32(sc, ZYD_CR69, 0x28); - (void)zyd_write32(sc, ZYD_CR69, 0x2a); + if (sc->fix_cr47) { + /* set CCK baseband gain from EEPROM */ + if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0) + (void)zyd_write16(sc, ZYD_CR47, tmp & 0xff); } + (void)zyd_write32(sc, ZYD_CR_CONFIG_PHILIPS, 0); + zyd_unlock_phy(sc); sc->sc_rxtap.wr_chan_freq = sc->sc_txtap.wt_chan_freq = @@ -2389,7 +2448,9 @@ switch (cmd) { case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + zyd_set_multi(sc); + else zyd_init(sc); } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) @@ -2397,6 +2458,12 @@ } break; + case SIOCADDMULTI: + case SIOCDELMULTI: + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + zyd_set_multi(sc); + break; + default: error = ieee80211_ioctl(ic, cmd, data); } @@ -2439,6 +2506,9 @@ (void)zyd_write32(sc, ZYD_MAC_SNIFFER, (ic->ic_opmode == IEEE80211_M_MONITOR) ? 1 : 0); + /* multicast setup */ + (void)zyd_set_multi(sc); + (void)zyd_set_rxfilter(sc); /* switch radio transmitter ON */ Index: src/sys/dev/usb/if_zydreg.h =================================================================== RCS file: /home/ncvs/src/sys/dev/usb/if_zydreg.h,v retrieving revision 1.2 diff -u -r1.2 if_zydreg.h --- src/sys/dev/usb/if_zydreg.h 15 Oct 2007 17:39:47 -0000 1.2 +++ src/sys/dev/usb/if_zydreg.h 6 Nov 2007 16:30:40 -0000 @@ -1084,8 +1084,10 @@ sizeof(struct zyd_rx_stat)) #define ZYD_MIN_RXBUFSZ ZYD_MIN_FRAGSZ #define ZYX_MAX_RXBUFSZ \ - ((sizeof(struct zyd_plcphdr) + MCLBYTES + \ - sizeof(struct zyd_rx_desc)) * 3) + ((sizeof (struct zyd_plcphdr) + IEEE80211_MAX_LEN + \ + sizeof (struct zyd_rx_stat)) * ZYD_MAX_RXFRAMECNT + \ + sizeof (struct zyd_rx_desc)) + #define ZYD_CMD_FLAG_READ (1 << 0) @@ -1208,6 +1210,8 @@ uint16_t fw_rev; uint8_t rf_rev; uint8_t pa_rev; + uint8_t fix_cr47; + uint8_t fix_cr157; uint8_t pwr_cal[14]; uint8_t pwr_int[14]; uint8_t ofdm36_cal[14];