summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2005-02-19 03:33:31 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2005-02-19 03:33:31 +0000
commit924bcd37fe1f89f620fc36af9830d1d9d9ed4d32 (patch)
tree2b5e52cbe93be9144351bb0dcbb26e43a027bd9d
parentd83e263bc47f2aa624f23538c9a430a934d6aa46 (diff)
From part of NetBSD rtw.c rev 1.42:
log message: Program the LEDs based on operating state and packet activity. * On a Revision F RTL8180, blink LED1 at 1Hz to indicate scan/authenticate/associate states. In the run state, turn LED1 on. In every state, blink LED1 at 5Hz to indicate non-beacon tx/rx activity. I would like to use two LEDs, but in all my Rev. F instances, LED0 is not wired to an LED; instead, the first LED is wired to indicate that the card's power is on. * On a Revision D RTL8180, program the LEDs so that LED0 indicates Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if there are beacons in the air, but at least the Tx LED is useful. * Store the hardware revision in the softc to support my futile attempt at programming LEDs for both Rev. D and Rev. F parts; I never did get Rev. D LEDs to work right. * Add a debug flag RTW_DEBUG_LED for the LED transitions.
-rw-r--r--sys/dev/ic/rtw.c177
-rw-r--r--sys/dev/ic/rtwvar.h44
2 files changed, 205 insertions, 16 deletions
diff --git a/sys/dev/ic/rtw.c b/sys/dev/ic/rtw.c
index de567dacc1a..57e2f15c6d6 100644
--- a/sys/dev/ic/rtw.c
+++ b/sys/dev/ic/rtw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtw.c,v 1.17 2005/02/17 18:28:05 reyk Exp $ */
+/* $OpenBSD: rtw.c,v 1.18 2005/02/19 03:33:30 jsg Exp $ */
/* $NetBSD: rtw.c,v 1.29 2004/12/27 19:49:16 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
@@ -211,6 +211,12 @@ struct mbuf *rtw_80211_dequeue(struct rtw_softc *, struct ifqueue *, int,
void rtw_recv_beacon(struct rtw_softc *, struct mbuf *,
struct ieee80211_node *, int, int, uint32_t);
+void rtw_led_attach(struct rtw_softc *);
+void rtw_led_init(struct rtw_regs *);
+void rtw_led_slowblink(void *);
+void rtw_led_fastblink(void *);
+void rtw_led_set(struct rtw_led_state *, struct rtw_regs *, int);
+void rtw_led_newstate(struct rtw_softc *, enum ieee80211_state);
#ifdef RTW_DEBUG
void rtw_print_txdesc(struct rtw_softc *, const char *,
@@ -1378,6 +1384,9 @@ rtw_intr_rx(struct rtw_softc *sc, u_int16_t isr)
m->m_flags |= M_HASFCS;
wh = mtod(m, struct ieee80211_frame *);
+
+ if (!IS_BEACON(wh->i_fc[0]))
+ sc->sc_led_state.ls_event |= RTW_LED_S_RX;
/* TBD use _MAR, _BAR, _PAR flags as hints to _find_rxnode? */
ni = ieee80211_find_rxnode(&sc->sc_ic, wh);
@@ -2525,6 +2534,167 @@ out:
return rc;
}
+void
+rtw_led_init(struct rtw_regs *regs)
+{
+ u_int8_t cfg0, cfg1;
+
+ rtw_set_access(regs, RTW_ACCESS_CONFIG);
+
+ cfg0 = RTW_READ8(regs, RTW_CONFIG0);
+ cfg0 |= RTW_CONFIG0_LEDGPOEN;
+ RTW_WRITE8(regs, RTW_CONFIG0, cfg0);
+
+ cfg1 = RTW_READ8(regs, RTW_CONFIG1);
+ RTW_DPRINTF(RTW_DEBUG_LED,
+ ("%s: read %" PRIx8 " from reg[CONFIG1]\n", __func__, cfg1));
+
+ cfg1 &= ~RTW_CONFIG1_LEDS_MASK;
+ cfg1 |= RTW_CONFIG1_LEDS_TX_RX;
+ RTW_WRITE8(regs, RTW_CONFIG1, cfg1);
+
+ rtw_set_access(regs, RTW_ACCESS_NONE);
+}
+
+/*
+ * IEEE80211_S_INIT: LED1 off
+ *
+ * IEEE80211_S_AUTH,
+ * IEEE80211_S_ASSOC,
+ * IEEE80211_S_SCAN: LED1 blinks @ 1 Hz, blinks at 5Hz for tx/rx
+ *
+ * IEEE80211_S_RUN: LED1 on, blinks @ 5Hz for tx/rx
+ */
+void
+rtw_led_newstate(struct rtw_softc *sc, enum ieee80211_state nstate)
+{
+ struct rtw_led_state *ls;
+
+ ls = &sc->sc_led_state;
+
+ switch (nstate) {
+ case IEEE80211_S_INIT:
+ rtw_led_init(&sc->sc_regs);
+ timeout_del(&ls->ls_slow_ch);
+ timeout_del(&ls->ls_fast_ch);
+ ls->ls_slowblink = 0;
+ ls->ls_actblink = 0;
+ ls->ls_default = 0;
+ break;
+ case IEEE80211_S_SCAN:
+ timeout_add(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS);
+ timeout_add(&ls->ls_fast_ch, RTW_LED_FAST_TICKS);
+ /*FALLTHROUGH*/
+ case IEEE80211_S_AUTH:
+ case IEEE80211_S_ASSOC:
+ ls->ls_default = RTW_LED1;
+ ls->ls_actblink = RTW_LED1;
+ ls->ls_slowblink = RTW_LED1;
+ break;
+ case IEEE80211_S_RUN:
+ ls->ls_slowblink = 0;
+ break;
+ }
+ rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
+}
+
+void
+rtw_led_set(struct rtw_led_state *ls, struct rtw_regs *regs, int hwverid)
+{
+ u_int8_t led_condition;
+ bus_size_t ofs;
+ u_int8_t mask, newval, val;
+
+ led_condition = ls->ls_default;
+
+ if (ls->ls_state & RTW_LED_S_SLOW)
+ led_condition ^= ls->ls_slowblink;
+ if (ls->ls_state & (RTW_LED_S_RX|RTW_LED_S_TX))
+ led_condition ^= ls->ls_actblink;
+
+ RTW_DPRINTF(RTW_DEBUG_LED,
+ ("%s: LED condition %" PRIx8 "\n", __func__, led_condition));
+
+ switch (hwverid) {
+ default:
+ case 'F':
+ ofs = RTW_PSR;
+ newval = mask = RTW_PSR_LEDGPO0 | RTW_PSR_LEDGPO1;
+ if (led_condition & RTW_LED0)
+ newval &= ~RTW_PSR_LEDGPO0;
+ if (led_condition & RTW_LED1)
+ newval &= ~RTW_PSR_LEDGPO1;
+ break;
+ case 'D':
+ ofs = RTW_9346CR;
+ mask = RTW_9346CR_EEM_MASK | RTW_9346CR_EEDI | RTW_9346CR_EECS;
+ newval = RTW_9346CR_EEM_PROGRAM;
+ if (led_condition & RTW_LED0)
+ newval |= RTW_9346CR_EEDI;
+ if (led_condition & RTW_LED1)
+ newval |= RTW_9346CR_EECS;
+ break;
+ }
+ val = RTW_READ8(regs, ofs);
+ RTW_DPRINTF(RTW_DEBUG_LED,
+ ("%s: read %" PRIx8 " from reg[%#02x]\n", __func__, val, ofs));
+ val &= ~mask;
+ val |= newval;
+ RTW_WRITE8(regs, ofs, val);
+ RTW_DPRINTF(RTW_DEBUG_LED,
+ ("%s: wrote %" PRIx8 " to reg[%#02x]\n", __func__, val, ofs));
+ RTW_SYNC(regs, ofs, ofs);
+}
+
+void
+rtw_led_fastblink(void *arg)
+{
+ int ostate, s;
+ struct rtw_softc *sc = (struct rtw_softc *)arg;
+ struct rtw_led_state *ls = &sc->sc_led_state;
+
+ s = splnet();
+ ostate = ls->ls_state;
+ ls->ls_state ^= ls->ls_event;
+
+ if ((ls->ls_event & RTW_LED_S_TX) == 0)
+ ls->ls_state &= ~RTW_LED_S_TX;
+
+ if ((ls->ls_event & RTW_LED_S_RX) == 0)
+ ls->ls_state &= ~RTW_LED_S_RX;
+
+ ls->ls_event = 0;
+
+ if (ostate != ls->ls_state)
+ rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
+ splx(s);
+
+ timeout_add(&ls->ls_fast_ch, RTW_LED_FAST_TICKS);
+}
+
+void
+rtw_led_slowblink(void *arg)
+{
+ int s;
+ struct rtw_softc *sc = (struct rtw_softc *)arg;
+ struct rtw_led_state *ls = &sc->sc_led_state;
+
+ s = splnet();
+ ls->ls_state ^= RTW_LED_S_SLOW;
+ rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
+ splx(s);
+ timeout_add(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS);
+}
+
+void
+rtw_led_attach(struct rtw_softc *sc)
+{
+ struct rtw_led_state *ls = &sc->sc_led_state;
+
+ timeout_set(&ls->ls_fast_ch, rtw_led_fastblink, sc);
+ timeout_set(&ls->ls_slow_ch, rtw_led_slowblink, sc);
+}
+
int
rtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
@@ -2980,6 +3150,7 @@ rtw_start(struct ifnet *ifp)
SIMPLEQ_INSERT_TAIL(&tsb->tsb_dirtyq, ts, ts_q);
if (tsb != &sc->sc_txsoft_blk[RTW_TXPRIBCN]) {
+ sc->sc_led_state.ls_event |= RTW_LED_S_TX;
tsb->tsb_tx_timer = 5;
ifp->if_timer = 1;
}
@@ -3115,6 +3286,8 @@ rtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
ostate = ic->ic_state;
+ rtw_led_newstate(sc, nstate);
+
if (nstate == IEEE80211_S_INIT) {
timeout_del(&sc->sc_scan_to);
sc->sc_cur_chan = IEEE80211_CHAN_ANY;
@@ -3714,6 +3887,8 @@ rtw_attach(struct rtw_softc *sc)
rtw_set80211props(&sc->sc_ic);
+ rtw_led_attach(sc);
+
/*
* Call MI attach routines.
*/
diff --git a/sys/dev/ic/rtwvar.h b/sys/dev/ic/rtwvar.h
index ff45b26f9e1..48f78a1af98 100644
--- a/sys/dev/ic/rtwvar.h
+++ b/sys/dev/ic/rtwvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtwvar.h,v 1.6 2005/02/14 12:49:29 jsg Exp $ */
+/* $OpenBSD: rtwvar.h,v 1.7 2005/02/19 03:33:30 jsg Exp $ */
/* $NetBSD: rtwvar.h,v 1.10 2004/12/26 22:37:57 mycroft Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
@@ -59,8 +59,9 @@
#define RTW_DEBUG_PHYBITIO 0x040000
#define RTW_DEBUG_TIMEOUT 0x080000
#define RTW_DEBUG_BUGS 0x100000
-#define RTW_DEBUG_BEACON 0x200000
-#define RTW_DEBUG_MAX 0x3fffff
+#define RTW_DEBUG_BEACON 0x200000
+#define RTW_DEBUG_LED 0x400000
+#define RTW_DEBUG_MAX 0x7fffff
extern int rtw_debug;
#define RTW_DPRINTF(__flags, __x) \
@@ -73,15 +74,6 @@ extern int rtw_debug;
#define DPRINTF(__sc, __flags, __x)
#endif /* RTW_DEBUG */
-#if 0
-enum rtw_rftype {
- RTW_RFTYPE_INTERSIL = 0,
- RTW_RFTYPE_RFMD,
- RTW_RFTYPE_PHILIPS,
- RTW_RFTYPE_MAXIM
-};
-#endif
-
enum rtw_locale {
RTW_LOCALE_USA = 0,
RTW_LOCALE_EUROPE,
@@ -345,6 +337,29 @@ struct rtw_sa2400 {
typedef void (*rtw_pwrstate_t)(struct rtw_regs *, enum rtw_pwrstate, int, int);
+union rtw_keys {
+ u_int8_t rk_keys[4][16];
+ u_int32_t rk_words[16];
+};
+
+#define RTW_LED_SLOW_TICKS MAX(1, hz/2)
+#define RTW_LED_FAST_TICKS MAX(1, hz/10)
+
+struct rtw_led_state {
+#define RTW_LED0 0x1
+#define RTW_LED1 0x2
+ u_int8_t ls_slowblink:2;
+ u_int8_t ls_actblink:2;
+ u_int8_t ls_default:2;
+ u_int8_t ls_state;
+ u_int8_t ls_event;
+#define RTW_LED_S_RX 0x1
+#define RTW_LED_S_TX 0x2
+#define RTW_LED_S_SLOW 0x4
+ struct timeout ls_slow_ch;
+ struct timeout ls_fast_ch;
+};
+
struct rtw_softc {
struct device sc_dev;
struct ieee80211com sc_ic;
@@ -352,9 +367,6 @@ struct rtw_softc {
bus_dma_tag_t sc_dmat;
u_int32_t sc_flags;
-#if 0
- enum rtw_rftype sc_rftype;
-#endif
enum rtw_attach_state sc_attach_state;
enum rtw_rfchipid sc_rfchipid;
enum rtw_locale sc_locale;
@@ -418,8 +430,10 @@ struct rtw_softc {
struct rtw_tx_radiotap_header tap;
u_int8_t pad[64];
} sc_txtapu;
+ union rtw_keys sc_keys;
int sc_txkey;
struct ifqueue sc_beaconq;
+ struct rtw_led_state sc_led_state;
int sc_hwverid;
};