Date: Tue, 20 Nov 2007 06:42:42 GMT From: Kevin Lo <kevlo@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 129271 for review Message-ID: <200711200642.lAK6gg38016958@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=129271 Change 129271 by kevlo@kevlo_rtsl on 2007/11/20 06:42:32 Rework LED support Obtained from: DragonFlyBSD Affected files ... .. //depot/projects/wifi/sys/dev/bwi/if_bwi.c#9 edit .. //depot/projects/wifi/sys/dev/bwi/if_bwireg.h#4 edit .. //depot/projects/wifi/sys/dev/bwi/if_bwivar.h#5 edit Differences ... ==== //depot/projects/wifi/sys/dev/bwi/if_bwi.c#9 (text+ko) ==== @@ -111,8 +111,8 @@ static int bwi_calc_rssi(struct bwi_softc *, const struct bwi_rxbuf_hdr *); static __inline uint8_t bwi_ofdm_plcp2rate(const uint32_t *); static __inline uint8_t bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *); -static void bwi_rx_radiotap(struct bwi_softc *, struct mbuf *, - struct bwi_rxbuf_hdr *, const void *, int); +static void bwi_rx_radiotap(struct bwi_softc *, struct mbuf *, + struct bwi_rxbuf_hdr *, const void *, int, int); static void bwi_stop(struct bwi_softc *); static int bwi_newbuf(struct bwi_softc *, int, int); @@ -132,7 +132,7 @@ static void bwi_setup_rx_desc32(struct bwi_softc *, int, bus_addr_t, int); static void bwi_setup_tx_desc32(struct bwi_softc *, struct bwi_ring_data *, int, bus_addr_t, int); -static void bwi_rxeof32(struct bwi_softc *); +static int bwi_rxeof32(struct bwi_softc *); static void bwi_start_tx32(struct bwi_softc *, uint32_t, int); static void bwi_txeof_status32(struct bwi_softc *); @@ -145,11 +145,11 @@ static void bwi_setup_rx_desc64(struct bwi_softc *, int, bus_addr_t, int); static void bwi_setup_tx_desc64(struct bwi_softc *, struct bwi_ring_data *, int, bus_addr_t, int); -static void bwi_rxeof64(struct bwi_softc *); +static int bwi_rxeof64(struct bwi_softc *); static void bwi_start_tx64(struct bwi_softc *, uint32_t, int); static void bwi_txeof_status64(struct bwi_softc *); -static void bwi_rxeof(struct bwi_softc *, int); +static int bwi_rxeof(struct bwi_softc *, int); static void _bwi_txeof(struct bwi_softc *, uint16_t, int, int); static void bwi_txeof(struct bwi_softc *); static void bwi_txeof_status(struct bwi_softc *, int); @@ -195,6 +195,10 @@ static void bwi_led_attach(struct bwi_softc *); static void bwi_led_newstate(struct bwi_softc *, enum ieee80211_state); +static void bwi_led_event(struct bwi_softc *, int); +static void bwi_led_blink_start(struct bwi_softc *, int, int); +static void bwi_led_blink_next(void *); +static void bwi_led_blink_end(void *); static const struct { uint16_t did_min; @@ -242,6 +246,48 @@ #undef CLKSRC +#define VENDOR_LED_ACT(vendor) \ +{ \ + .vid = PCI_VENDOR_##vendor, \ + .led_act = { BWI_VENDOR_LED_ACT_##vendor } \ +} + +static const struct { +#define PCI_VENDOR_COMPAQ 0x0e11 +#define PCI_VENDOR_LINKSYS 0x1737 + uint16_t vid; + uint8_t led_act[BWI_LED_MAX]; +} bwi_vendor_led_act[] = { + VENDOR_LED_ACT(COMPAQ), + VENDOR_LED_ACT(LINKSYS) +#undef PCI_VENDOR_LINKSYS +#undef PCI_VENDOR_COMPAQ +}; + +static const uint8_t bwi_default_led_act[BWI_LED_MAX] = + { BWI_VENDOR_LED_ACT_DEFAULT }; + +#undef VENDOR_LED_ACT + +static const struct { + int on_dur; + int off_dur; +} bwi_led_duration[109] = { + [0] = { 400, 100 }, + [2] = { 150, 75 }, + [4] = { 90, 45 }, + [11] = { 66, 34 }, + [12] = { 53, 26 }, + [18] = { 42, 21 }, + [22] = { 35, 17 }, + [24] = { 32, 16 }, + [36] = { 21, 10 }, + [48] = { 16, 8 }, + [72] = { 11, 5 }, + [96] = { 9, 4 }, + [108] = { 7, 3 } +}; + static const uint8_t bwi_zero_addr[IEEE80211_ADDR_LEN]; uint16_t @@ -417,6 +463,10 @@ sc->sc_fw_version = BWI_FW_VERSION3; + /* Initialize LED vars */ + sc->sc_led_idle = (2350 * hz) / 1000; + sc->sc_led_blink = 1; + ic->ic_ifp = ifp; ic->ic_caps = IEEE80211_C_SHSLOT | IEEE80211_C_SHPREAMBLE | @@ -1385,7 +1435,7 @@ struct ifnet *ifp = sc->sc_ic.ic_ifp; uint32_t intr_status; uint32_t txrx_intr_status[BWI_TXRX_NRING]; - int i, txrx_error; + int i, txrx_error, tx = 0, rx_data = -1; BWI_LOCK(sc); @@ -1480,18 +1530,41 @@ if_printf(ifp, "intr noise\n"); if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) - sc->sc_rxeof(sc); + rx_data = sc->sc_rxeof(sc); - if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) + if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) { sc->sc_txeof_status(sc); + tx = 1; + } - if (intr_status & BWI_INTR_TX_DONE) + if (intr_status & BWI_INTR_TX_DONE) { bwi_txeof(sc); + tx = 1; + } - /* TODO:LED */ - /* Re-enable interrupts */ bwi_enable_intrs(sc, BWI_INIT_INTRS); + + if (sc->sc_blink_led != NULL && sc->sc_led_blink) { + int evt = BWI_LED_EVENT_NONE; + + if (tx && rx_data > 0) { + if (sc->sc_rx_rate > sc->sc_tx_rate) + evt = BWI_LED_EVENT_RX; + else + evt = BWI_LED_EVENT_TX; + } else if (tx) { + evt = BWI_LED_EVENT_TX; + } else if (rx_data > 0) { + evt = BWI_LED_EVENT_RX; + } else if (rx_data == 0) { + evt = BWI_LED_EVENT_POLL; + } + + if (evt != BWI_LED_EVENT_NONE) + bwi_led_event(sc, evt); + } + BWI_UNLOCK(sc); } @@ -2454,14 +2527,14 @@ return 0; } -static void +static int bwi_rxeof(struct bwi_softc *sc, int end_idx) { struct bwi_ring_data *rd = &sc->sc_rx_rdata; struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = ic->ic_ifp; - int idx; + int idx, rx_data = 0; idx = rbd->rbd_idx; while (idx != end_idx) { @@ -2470,9 +2543,9 @@ struct ieee80211_frame_min *wh; struct ieee80211_node *ni; struct mbuf *m; - const uint8_t *plcp; + const void *plcp; uint16_t flags2; - int buflen, wh_ofs, hdr_extra, rssi; + int buflen, wh_ofs, hdr_extra, rssi, type, rate; m = rb->rb_mbuf; bus_dmamap_sync(sc->sc_buf_dtag, rb->rb_dmap, @@ -2507,18 +2580,27 @@ m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr); m_adj(m, sizeof(*hdr) + wh_ofs); + if (htole16(hdr->rxh_flags1) & BWI_RXH_F1_OFDM) + rate = bwi_ofdm_plcp2rate(plcp); + else + rate = bwi_ds_plcp2rate(plcp); + /* RX radio tap */ if (sc->sc_drvbpf != NULL) - bwi_rx_radiotap(sc, m, hdr, plcp, rssi); + bwi_rx_radiotap(sc, m, hdr, plcp, rate, rssi); m_adj(m, -IEEE80211_CRC_LEN); wh = mtod(m, struct ieee80211_frame_min *); ni = ieee80211_find_rxnode(ic, wh); - ieee80211_input(ic, m, ni, rssi - BWI_NOISE_FLOOR, + type = ieee80211_input(ic, m, ni, rssi - BWI_NOISE_FLOOR, BWI_NOISE_FLOOR, le16toh(hdr->rxh_tsf)); ieee80211_free_node(ni); + if (type == IEEE80211_FC0_TYPE_DATA) { + rx_data = 1; + sc->sc_rx_rate = rate; + } next: idx = (idx + 1) % BWI_RX_NDESC; } @@ -2526,13 +2608,15 @@ rbd->rbd_idx = idx; bus_dmamap_sync(sc->sc_rxring_dtag, rd->rdata_dmap, BUS_DMASYNC_PREWRITE); + + return rx_data; } -static void +static int bwi_rxeof32(struct bwi_softc *sc) { uint32_t val, rx_ctrl; - int end_idx; + int end_idx, rx_data; rx_ctrl = sc->sc_rx_rdata.rdata_txrx_ctrl; @@ -2540,16 +2624,19 @@ end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) / sizeof(struct bwi_desc32); - bwi_rxeof(sc, end_idx); + rx_data = bwi_rxeof(sc, end_idx); CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX, end_idx * sizeof(struct bwi_desc32)); + + return rx_data; } -static void +static int bwi_rxeof64(struct bwi_softc *sc) { /* TODO:64 */ + return 0; } static void @@ -2816,12 +2903,16 @@ if (IEEE80211_IS_MULTICAST(wh->i_addr1)) rate = rate_fb = ic->ic_mcast_rate; else if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { - rate = ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL; + rate = ni->ni_rates.rs_rates[ni->ni_txrate] & + IEEE80211_RATE_VAL; rate_fb = (ni->ni_txrate > 0) ? - ni->ni_rates.rs_rates[ni->ni_txrate-1] & IEEE80211_RATE_VAL : rate; + ni->ni_rates.rs_rates[ni->ni_txrate-1] & + IEEE80211_RATE_VAL : rate; } else rate = rate_fb = ic->ic_fixed_rate; + sc->sc_tx_rate = rate; + /* * TX radio tap */ @@ -3460,20 +3551,12 @@ static void bwi_rx_radiotap(struct bwi_softc *sc, struct mbuf *m, - struct bwi_rxbuf_hdr *hdr, const void *plcp, int rssi) + struct bwi_rxbuf_hdr *hdr, const void *plcp, int rate, int rssi) { const struct ieee80211_frame_min *wh; - uint16_t flags1; - uint8_t rate; - flags1 = htole16(hdr->rxh_flags1); - if (flags1 & BWI_RXH_F1_OFDM) - rate = bwi_ofdm_plcp2rate(plcp); - else - rate = bwi_ds_plcp2rate(plcp); - sc->sc_rx_th.wr_flags = IEEE80211_RADIOTAP_F_FCS; - if (flags1 & BWI_RXH_F1_SHPREAMBLE) + if (htole16(hdr->rxh_flags1) & BWI_RXH_F1_SHPREAMBLE) sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; wh = mtod(m, const struct ieee80211_frame_min *); @@ -3491,17 +3574,23 @@ static void bwi_led_attach(struct bwi_softc *sc) { -#define PCI_VENDOR_COMPAQ 0x0e11 - const static uint8_t led_default_act[BWI_LED_MAX] = { - BWI_LED_ACT_ACTIVE, - BWI_LED_ACT_2GHZ, - BWI_LED_ACT_5GHZ, - BWI_LED_ACT_OFF - }; - + const uint8_t *led_act = NULL; uint16_t gpio, val[BWI_LED_MAX]; int i; +#define N(arr) (int)(sizeof(arr) / sizeof(arr[0])) + + for (i = 0; i < N(bwi_vendor_led_act); ++i) { + if (sc->sc_pci_subvid == bwi_vendor_led_act[i].vid) { + led_act = bwi_vendor_led_act[i].led_act; + break; + } + } + if (led_act == NULL) + led_act = bwi_default_led_act; + +#undef N + gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO01); val[0] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_0); val[1] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_1); @@ -3514,19 +3603,46 @@ struct bwi_led *led = &sc->sc_leds[i]; if (val[i] == 0xff) { - led->l_act = led_default_act[i]; - if (i == 0 && sc->sc_pci_subvid == PCI_VENDOR_COMPAQ) - led->l_act = BWI_LED_ACT_RFEN; + led->l_act = led_act[i]; } else { if (val[i] & BWI_LED_ACT_LOW) led->l_flags |= BWI_LED_F_ACTLOW; led->l_act = __SHIFTOUT(val[i], BWI_LED_ACT_MASK); } + led->l_mask = (1 << i); + + if (led->l_act == BWI_LED_ACT_BLINK_SLOW || + led->l_act == BWI_LED_ACT_BLINK_POLL || + led->l_act == BWI_LED_ACT_BLINK) { + led->l_flags |= BWI_LED_F_BLINK; + if (led->l_act == BWI_LED_ACT_BLINK_POLL) + led->l_flags |= BWI_LED_F_POLLABLE; + else if (led->l_act == BWI_LED_ACT_BLINK_SLOW) + led->l_flags |= BWI_LED_F_SLOW; + + if (sc->sc_blink_led == NULL) { + sc->sc_blink_led = led; + if (led->l_flags & BWI_LED_F_SLOW) + BWI_LED_SLOWDOWN(sc->sc_led_idle); + } + } DPRINTF(sc, "%dth led, act %d, lowact %d\n", i, led->l_act, led->l_flags & BWI_LED_F_ACTLOW); } -#undef PCI_VENDOR_COMPAQ + callout_init(&sc->sc_led_blink_ch, CALLOUT_MPSAFE); +} + +static __inline uint16_t +bwi_led_onoff(const struct bwi_led *led, uint16_t val, int on) +{ + if (led->l_flags & BWI_LED_F_ACTLOW) + on = !on; + if (on) + val |= led->l_mask; + else + val &= ~led->l_mask; + return val; } static void @@ -3536,6 +3652,11 @@ uint16_t val; int i; + if (nstate == IEEE80211_S_INIT) { + callout_stop(&sc->sc_led_blink_ch); + sc->sc_led_blinking = 0; + } + if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) return; @@ -3545,10 +3666,12 @@ int on; if (led->l_act == BWI_LED_ACT_UNKN || - led->l_act == BWI_LED_ACT_NULL) { - /* Don't touch it */ + led->l_act == BWI_LED_ACT_NULL) continue; - } + + if ((led->l_flags & BWI_LED_F_BLINK) && + nstate != IEEE80211_S_INIT) + continue; switch (led->l_act) { case BWI_LED_ACT_ON: /* Always on */ @@ -3556,8 +3679,6 @@ break; case BWI_LED_ACT_OFF: /* Always off */ case BWI_LED_ACT_5GHZ: /* TODO: 11A */ - case BWI_LED_ACT_MID: /* Blinking ones */ - case BWI_LED_ACT_FAST: on = 0; break; default: @@ -3572,23 +3693,92 @@ on = 0; break; default: - if (led->l_act == BWI_LED_ACT_RUN || - led->l_act == BWI_LED_ACT_ACTIVE) + if (led->l_act == BWI_LED_ACT_ASSOC) on = 0; break; } break; } - if (led->l_flags & BWI_LED_F_ACTLOW) - on = !on; + val = bwi_led_onoff(led, val, on); + } + CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val); +} +static void +bwi_led_event(struct bwi_softc *sc, int event) +{ + struct bwi_led *led = sc->sc_blink_led; + int rate; + + if (event == BWI_LED_EVENT_POLL) { + if ((led->l_flags & BWI_LED_F_POLLABLE) == 0) + return; + if (ticks - sc->sc_led_ticks < sc->sc_led_idle) + return; + } + + sc->sc_led_ticks = ticks; + if (sc->sc_led_blinking) + return; + + switch (event) { + case BWI_LED_EVENT_RX: + rate = sc->sc_rx_rate; + break; + case BWI_LED_EVENT_TX: + rate = sc->sc_tx_rate; + break; + case BWI_LED_EVENT_POLL: + rate = 0; + break; + default: + panic("unknown LED event %d\n", event); + break; + } + bwi_led_blink_start(sc, bwi_led_duration[rate].on_dur, + bwi_led_duration[rate].off_dur); +} + +static void +bwi_led_blink_start(struct bwi_softc *sc, int on_dur, int off_dur) +{ + struct bwi_led *led = sc->sc_blink_led; + uint16_t val; + + val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL); + val = bwi_led_onoff(led, val, 1); + CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val); - if (on) - val |= (1 << i); - else - val &= ~(1 << i); + if (led->l_flags & BWI_LED_F_SLOW) { + BWI_LED_SLOWDOWN(on_dur); + BWI_LED_SLOWDOWN(off_dur); } + + sc->sc_led_blinking = 1; + sc->sc_led_blink_offdur = off_dur; + + callout_reset(&sc->sc_led_blink_ch, on_dur, bwi_led_blink_next, sc); +} + +static void +bwi_led_blink_next(void *xsc) +{ + struct bwi_softc *sc = xsc; + uint16_t val; + + val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL); + val = bwi_led_onoff(sc->sc_blink_led, val, 0); CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val); + + callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur, + bwi_led_blink_end, sc); +} + +static void +bwi_led_blink_end(void *xsc) +{ + struct bwi_softc *sc = xsc; + sc->sc_led_blinking = 0; } /* ==== //depot/projects/wifi/sys/dev/bwi/if_bwireg.h#4 (text+ko) ==== @@ -412,17 +412,35 @@ #define BWI_LED_ACT_MASK __BITS(6, 0) #define BWI_LED_ACT_OFF 0 #define BWI_LED_ACT_ON 1 -#define BWI_LED_ACT_ACTIVE 2 -#define BWI_LED_ACT_RFEN 3 +#define BWI_LED_ACT_BLINK 2 +#define BWI_LED_ACT_RF_ENABLED 3 #define BWI_LED_ACT_5GHZ 4 #define BWI_LED_ACT_2GHZ 5 #define BWI_LED_ACT_11G 6 -#define BWI_LED_ACT_MID 7 -#define BWI_LED_ACT_FAST 8 +#define BWI_LED_ACT_BLINK_SLOW 7 +#define BWI_LED_ACT_BLINK_POLL 8 #define BWI_LED_ACT_UNKN 9 -#define BWI_LED_ACT_RUN 10 +#define BWI_LED_ACT_ASSOC 10 #define BWI_LED_ACT_NULL 11 +#define BWI_VENDOR_LED_ACT_COMPAQ \ + BWI_LED_ACT_RF_ENABLED, \ + BWI_LED_ACT_2GHZ, \ + BWI_LED_ACT_5GHZ, \ + BWI_LED_ACT_OFF + +#define BWI_VENDOR_LED_ACT_LINKSYS \ + BWI_LED_ACT_ASSOC, \ + BWI_LED_ACT_2GHZ, \ + BWI_LED_ACT_5GHZ, \ + BWI_LED_ACT_OFF + +#define BWI_VENDOR_LED_ACT_DEFAULT \ + BWI_LED_ACT_BLINK, \ + BWI_LED_ACT_2GHZ, \ + BWI_LED_ACT_5GHZ, \ + BWI_LED_ACT_OFF + /* * BBP IDs */ ==== //depot/projects/wifi/sys/dev/bwi/if_bwivar.h#5 (text+ko) ==== @@ -55,6 +55,12 @@ #define BWI_SHRETRY_FB 3 #define BWI_LGRETRY_FB 2 +#define BWI_LED_EVENT_NONE -1 +#define BWI_LED_EVENT_POLL 0 +#define BWI_LED_EVENT_TX 1 +#define BWI_LED_EVENT_RX 2 +#define BWI_LED_SLOWDOWN(dur) (dur) = (((dur) * 3) / 2) + #define BWI_NOISE_FLOOR -95 /* TODO: noise floor calc */ #define BWI_FRAME_MIN_LEN(hdr) \ ((hdr) + sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN) @@ -284,9 +290,13 @@ struct bwi_led { uint8_t l_flags; /* BWI_LED_F_ */ uint8_t l_act; /* BWI_LED_ACT_ */ + uint8_t l_mask; }; #define BWI_LED_F_ACTLOW 0x1 +#define BWI_LED_F_BLINK 0x2 +#define BWI_LED_F_POLLABLE 0x4 +#define BWI_LED_F_SLOW 0x8 enum bwi_clock_mode { BWI_CLOCK_MODE_SLOW, @@ -543,6 +553,14 @@ int sc_nmac; struct bwi_mac sc_mac[BWI_MAC_MAX]; + int sc_rx_rate; + int sc_tx_rate; + + int sc_led_blinking; + int sc_led_ticks; + struct bwi_led *sc_blink_led; + struct callout sc_led_blink_ch; + int sc_led_blink_offdur; struct bwi_led sc_leds[BWI_LED_MAX]; enum bwi_bus_space sc_bus_space; @@ -582,7 +600,7 @@ void (*sc_setup_rxdesc) (struct bwi_softc *, int, bus_addr_t, int); - void (*sc_rxeof)(struct bwi_softc *); + int (*sc_rxeof)(struct bwi_softc *); void (*sc_setup_txdesc) (struct bwi_softc *, struct bwi_ring_data *, @@ -595,6 +613,8 @@ /* Sysctl variables */ int sc_fw_version; /* BWI_FW_VERSION[34] */ int sc_dwell_time; /* milliseconds */ + int sc_led_idle; + int sc_led_blink; }; #define BWI_F_BUS_INITED 0x1
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200711200642.lAK6gg38016958>