summaryrefslogtreecommitdiff
path: root/sys/dev/ic/bwi.c
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2007-10-18 05:56:16 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2007-10-18 05:56:16 +0000
commit024f3df0062008ce2087603099c549c9817efac4 (patch)
tree26f75bcb3cdc5859a02277181161371db1f97a2b /sys/dev/ic/bwi.c
parent72fc5a49fe02d2c1e51324bb423b249f7aef654c (diff)
Add some first LEDs support. Tested on my cardbus Linksys WPC54G Ver 3.
Diff ported from DragonFlyBSD
Diffstat (limited to 'sys/dev/ic/bwi.c')
-rw-r--r--sys/dev/ic/bwi.c109
1 files changed, 107 insertions, 2 deletions
diff --git a/sys/dev/ic/bwi.c b/sys/dev/ic/bwi.c
index 11a5256093d..8cc57d68458 100644
--- a/sys/dev/ic/bwi.c
+++ b/sys/dev/ic/bwi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bwi.c,v 1.61 2007/10/04 05:44:42 mglocker Exp $ */
+/* $OpenBSD: bwi.c,v 1.62 2007/10/18 05:56:15 mglocker Exp $ */
/*
* Copyright (c) 2007 The DragonFly Project. All rights reserved.
@@ -258,6 +258,8 @@ int bwi_regwin_switch(struct bwi_softc *, struct bwi_regwin *,
struct bwi_regwin **);
int bwi_regwin_select(struct bwi_softc *, int);
void bwi_regwin_info(struct bwi_softc *, uint16_t *, uint8_t *);
+void bwi_led_attach(struct bwi_softc *);
+void bwi_led_newstate(struct bwi_softc *, enum ieee80211_state);
int bwi_bbp_attach(struct bwi_softc *);
int bwi_bus_init(struct bwi_softc *, struct bwi_mac *);
void bwi_get_card_flags(struct bwi_softc *);
@@ -657,7 +659,7 @@ bwi_attach(struct bwi_softc *sc)
bwi_get_card_flags(sc);
- /* TODO: LED */
+ bwi_led_attach(sc);
for (i = 0; i < sc->sc_nmac; ++i) {
struct bwi_regwin *old;
@@ -5875,6 +5877,107 @@ bwi_regwin_info(struct bwi_softc *sc, uint16_t *type, uint8_t *rev)
*type, *rev, __SHIFTOUT(val, BWI_ID_HI_REGWIN_VENDOR_MASK));
}
+void
+bwi_led_attach(struct bwi_softc *sc)
+{
+ 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
+ };
+
+ uint16_t gpio, val[BWI_LED_MAX];
+ int i;
+
+ gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO01);
+ val[0] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_0);
+ val[1] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_1);
+
+ gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO23);
+ val[2] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_2);
+ val[3] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_3);
+
+ for (i = 0; i < BWI_LED_MAX; ++i) {
+ 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;
+ } 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);
+ }
+
+ DPRINTF("%dth led, act %d, lowact %d\n",
+ i, led->l_act, led->l_flags & BWI_LED_F_ACTLOW);
+ }
+}
+
+void
+bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ uint16_t val;
+ int i;
+
+ if ((ic->ic_if.if_flags & IFF_RUNNING) == 0)
+ return;
+
+ val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
+ for (i = 0; i < BWI_LED_MAX; ++i) {
+ struct bwi_led *led = &sc->sc_leds[i];
+ int on;
+
+ if (led->l_act == BWI_LED_ACT_UNKN ||
+ led->l_act == BWI_LED_ACT_NULL) {
+ /* Don't touch it */
+ continue;
+ }
+
+ switch (led->l_act) {
+ case BWI_LED_ACT_ON: /* Always on */
+ on = 1;
+ 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:
+ on = 1;
+ switch (nstate) {
+ case IEEE80211_S_INIT:
+ on = 0;
+ break;
+ case IEEE80211_S_RUN:
+ if (led->l_act == BWI_LED_ACT_11G &&
+ ic->ic_curmode != IEEE80211_MODE_11G)
+ on = 0;
+ break;
+ default:
+ if (led->l_act == BWI_LED_ACT_RUN ||
+ led->l_act == BWI_LED_ACT_ACTIVE)
+ on = 0;
+ break;
+ }
+ break;
+ }
+
+ if (led->l_flags & BWI_LED_F_ACTLOW)
+ on = !on;
+
+ if (on)
+ val |= (1 << i);
+ else
+ val &= ~(1 << i);
+ }
+ CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
+}
+
int
bwi_bbp_attach(struct bwi_softc *sc)
{
@@ -6659,6 +6762,8 @@ bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
timeout_del(&sc->sc_scan_ch);
timeout_del(&sc->sc_calib_ch);
+ bwi_led_newstate(sc, nstate);
+
if (nstate == IEEE80211_S_INIT)
goto back;