From 024f3df0062008ce2087603099c549c9817efac4 Mon Sep 17 00:00:00 2001 From: Marcus Glocker Date: Thu, 18 Oct 2007 05:56:16 +0000 Subject: Add some first LEDs support. Tested on my cardbus Linksys WPC54G Ver 3. Diff ported from DragonFlyBSD --- sys/dev/ic/bwi.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++- sys/dev/ic/bwireg.h | 27 ++++++++++++- sys/dev/ic/bwivar.h | 12 +++++- 3 files changed, 144 insertions(+), 4 deletions(-) (limited to 'sys') 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; diff --git a/sys/dev/ic/bwireg.h b/sys/dev/ic/bwireg.h index 9a02ddb05da..78c3a7fe4d6 100644 --- a/sys/dev/ic/bwireg.h +++ b/sys/dev/ic/bwireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bwireg.h,v 1.5 2007/09/30 22:26:10 mglocker Exp $ */ +/* $OpenBSD: bwireg.h,v 1.6 2007/10/18 05:56:15 mglocker Exp $ */ /* * Copyright (c) 2007 The DragonFly Project. All rights reserved. @@ -314,6 +314,7 @@ #define BWI_ADDR_FILTER_BSSID 3 #define BWI_ADDR_FILTER_DATA 0x422 +#define BWI_MAC_GPIO_CTRL 0x049c #define BWI_MAC_GPIO_MASK 0x049e #define BWI_MAC_PRE_TBTT 0x0612 #define BWI_MAC_SLOTTIME 0x0684 @@ -369,6 +370,12 @@ #define BWI_SPROM_CARD_INFO_LOCALE (0x0f << 8) #define BWI_SPROM_LOCALE_JAPAN 5 #define BWI_SPROM_PA_PARAM_11BG 0x5e +#define BWI_SPROM_GPIO01 0x64 +#define BWI_SPROM_GPIO_0 0x00ff +#define BWI_SPROM_GPIO_1 0xff00 +#define BWI_SPROM_GPIO23 0x0066 +#define BWI_SPROM_GPIO_2 0x00ff +#define BWI_SPROM_GPIO_3 0xff00 #define BWI_SPROM_MAX_TXPWR 0x68 #define BWI_SPROM_MAX_TXPWR_MASK_11BG 0x00ff /* XXX */ #define BWI_SPROM_MAX_TXPWR_MASK_11A 0xff00 /* XXX */ @@ -390,6 +397,24 @@ #define BWI_CARD_F_EXT_LNA (1 << 12) /* external LNA */ #define BWI_CARD_F_ALT_IQ (1 << 15) /* alternate I/Q */ +/* + * PROM GPIO + */ +#define BWI_LED_ACT_LOW (1 << 7) +#define BWI_LED_ACT_MASK 0x7f +#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_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_UNKN 9 +#define BWI_LED_ACT_RUN 10 +#define BWI_LED_ACT_NULL 11 + /* * BBP IDs */ diff --git a/sys/dev/ic/bwivar.h b/sys/dev/ic/bwivar.h index d54cfdeffaf..22682f032f2 100644 --- a/sys/dev/ic/bwivar.h +++ b/sys/dev/ic/bwivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bwivar.h,v 1.18 2007/10/04 05:44:43 mglocker Exp $ */ +/* $OpenBSD: bwivar.h,v 1.19 2007/10/18 05:56:15 mglocker Exp $ */ /* * Copyright (c) 2007 The DragonFly Project. All rights reserved. @@ -256,6 +256,13 @@ struct bwi_fw_iv { } iv_val; } __packed; +struct bwi_led { + uint8_t l_flags; /* BWI_LED_F_ */ + uint8_t l_act; /* BWI_LED_ACT_ */ +}; + +#define BWI_LED_F_ACTLOW 0x1 + enum bwi_clock_mode { BWI_CLOCK_MODE_SLOW, BWI_CLOCK_MODE_FAST, @@ -422,6 +429,7 @@ do { \ } while (0) #define BWI_MAC_MAX 2 +#define BWI_LED_MAX 4 enum bwi_bus_space { BWI_BUS_SPACE_30BIT = 1, @@ -508,6 +516,8 @@ struct bwi_softc { int sc_nmac; struct bwi_mac sc_mac[BWI_MAC_MAX]; + + struct bwi_led sc_leds[BWI_LED_MAX]; enum bwi_bus_space sc_bus_space; -- cgit v1.2.3