diff -x CVS -x .tmp_versions -uNr madwifi-orig/driver/if_ath.c madwifi-led/driver/if_ath.c
--- madwifi-orig/driver/if_ath.c	2004-06-11 02:26:59.000000000 +0200
+++ madwifi-led/driver/if_ath.c	2004-06-11 02:41:46.000000000 +0200
@@ -139,6 +139,20 @@
 static  int     ath_xchanmode = AH_TRUE;        /* enable extended channels */
 static  int     ath_ctlpkt_type=-1;             /* Control pkt type to filter */
 
+#ifdef SOFTLED
+
+/* a constant timer rate is used instead of only calling the ath_led_timer()
+   because the rfKill pin needs to be polled yet */
+#define ATH_LED_TICK HZ/10
+
+void
+ath_led_timer (unsigned long data);
+
+void
+ath_update_LED (struct ath_hal *ah, struct ieee80211com *ic,
+		u_int32_t event);
+#endif /* SOFTLED */
+
 #ifdef AR_DEBUG
 int	ath_debug = 0;
 #define	IFF_DUMPPKTS(_ic)	(ath_debug || netif_msg_dumppkts(_ic))
@@ -368,6 +382,18 @@
 
 	printk("%s: 802.11 address: %s\n",
 		dev->name, ether_sprintf(dev->dev_addr));
+
+#ifdef SOFTLED
+	ic->ic_ledStateList = 0;
+	ic->ic_ledStateLLen = 0;
+	ic->ic_rfKillState = 1;
+	/* start LED timer */
+	init_timer(&ic->ic_ledTimer);
+	ic->ic_ledTimer.data = (unsigned long)sc;
+	ic->ic_ledTimer.function = ath_led_timer;
+	ic->ic_ledTimer.expires = jiffies + ATH_LED_TICK;
+	add_timer(&ic->ic_ledTimer);
+#endif
 	return 0;
 bad2:
 	ath_desc_free(sc);
@@ -385,8 +411,10 @@
 
 	DPRINTF(("ath_detach flags %x\n", dev->flags));
 #ifdef SOFTLED 
-	sc->sc_ic.ic_beaconCnt = 0;
-	ath_hal_gpioSet(sc->sc_ah,sc->sc_ic.ic_ledPin,1);
+	/* stop LED timer */
+	del_timer_sync(&sc->sc_ic.ic_ledTimer);
+	/* turn off LED */
+	ath_hal_gpioSet(sc->sc_ah,sc->sc_ic.ic_ledPin,sc->sc_ic.ic_ledInverse);
 #endif
 	ath_stop(dev);
 	sc->sc_invalid = 1;
@@ -1675,40 +1703,86 @@
 
 #ifdef SOFTLED
 void
-ath_update_LED (struct net_device *dev, struct ath_hal *ah, 
-                struct ieee80211com *ic, u_int32_t event)
+ath_led_timer (unsigned long data)
 {
-	static unsigned int state=1;
-	int rateOn, rateOff, diff;
-	
-	if (ic->ic_state != IEEE80211_S_RUN) {
-		// Device is in scan mode, searching for AP
-		/* We flash the LED on for 5s and off for 200ms */
-		if (ic->ic_beaconCnt >= (2+state*48)) {
-			ath_hal_gpioCfgOutput(ah,ic->ic_ledPin);
-			ath_hal_gpioSet(ah,ic->ic_ledPin,state);
-			state ^= 1;
-			ic->ic_beaconCnt = 0;
-		}
-	}
-	else {
-		switch(event) {
-		case TRANSMIT_EVENT:
-		case RECEIVE_EVENT:
-			rateOn = 20;
-			rateOff = 2;
-			diff = rateOn-rateOff;
-			if (ic->ic_beaconCnt >= (rateOff + state*diff)) {
-				ath_hal_gpioCfgOutput(ah,ic->ic_ledPin);
-				ath_hal_gpioSet(ah,ic->ic_ledPin,state);
-				state ^= 1;
-				ic->ic_beaconCnt = 0;
-			}
-			break;
-		default:
-			break;
+	struct ath_softc *sc = (struct ath_softc*)data;
+	struct ath_hal *ah = sc->sc_ah;
+	struct ieee80211com *ic = &sc->sc_ic;
+	int state, rfkill, ifup;
+
+	if (sc->sc_invalid != 0) {
+		mod_timer(&ic->ic_ledTimer, jiffies + ATH_LED_TICK);
+		return;
+	}
+
+	/* XXX insert appropriate rfkill pin existence condition */
+	if (ic->ic_rfKillPin < 6) {
+		ath_hal_gpioCfgInput(ah,ic->ic_rfKillPin);
+		rfkill = ath_hal_gpioGet(ah,ic->ic_rfKillPin);
+		if (rfkill != ic->ic_rfKillState) {
+			printk("%s: rfKill state changed to %i\n",
+				ic->ic_dev.name, rfkill);
+			ic->ic_rfKillState = rfkill;
 		}
+	} else rfkill = 1;
+
+	state = ic->ic_ledStateList & 1;
+	ifup = ((ic->ic_dev.flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP));
+
+	ath_hal_gpioCfgOutput(ah,ic->ic_ledPin);
+	ath_hal_gpioSet(ah,ic->ic_ledPin,(state & ifup & rfkill) ^ ic->ic_ledInverse);
+
+	if (ic->ic_ledStateLLen > 0) {
+		/* shift LED "program" by one - go to next "instruction" */
+		ic->ic_ledStateList >>= 1;
+		ic->ic_ledStateLLen--;
+	}
+
+	if (ic->ic_ledStateLLen == 0 && ic->ic_state != IEEE80211_S_RUN) {
+		/* in scan mode, add another cycle */
+		ic->ic_ledStateList = 0x00ff;
+		ic->ic_ledStateLLen = 16;
+	}
+
+	mod_timer(&ic->ic_ledTimer, jiffies + ATH_LED_TICK);
+}
+
+void
+ath_update_LED (struct ath_hal *ah, struct ieee80211com *ic,
+		u_int32_t event)
+{
+	switch(event) {
+	case TRANSMIT_EVENT:
+		if (ic->ic_ledStateLLen > 0) return;
+		ic->ic_ledStateList = 6; /* xxx110 = short off, permanent on */
+		ic->ic_ledStateLLen = 2; /* 2 states + permanent on */
+		break;
+	case RECEIVE_EVENT:
+		/* only blink on RX in monitor mode */
+		if (ic->ic_ledStateLLen > 0 || ic->ic_opmode != IEEE80211_M_MONITOR)
+			return;
+		ic->ic_ledStateList = 1; /* xxx001 = short on, permanent off */
+		ic->ic_ledStateLLen = 2; /* 2 states + permanent off */
+		break;
+	case STATE_EVENT+IEEE80211_S_INIT:
+	case STATE_EVENT+IEEE80211_S_SCAN:
+	case STATE_EVENT+IEEE80211_S_AUTH:
+	case STATE_EVENT+IEEE80211_S_ASSOC:
+		ic->ic_ledStateList = 0x01f; /* 0000011111b: 500ms on, 500ms off */
+		ic->ic_ledStateLLen = 10;
+		break;
+	case STATE_EVENT+IEEE80211_S_RUN:
+		/* LED is on for normal operation and off for monitor */
+		ic->ic_ledStateList = (ic->ic_opmode == IEEE80211_M_MONITOR)?0:1;
+		ic->ic_ledStateLLen = 0;
+		break;
+	default:
+		/* do nothing... yet */
+		return;
 	}
+	//printk("processed event %i\n", event);
+	/* XXX: run right now instead of later */
+	// ath_led_timer((unsigned long)ah->ah_sc);
 }
 #endif
 
@@ -1948,7 +2022,7 @@
 			bf->bf_skb = NULL;
 #ifdef SOFTLED
 			if (ic->ic_caps & IEEE80211_C_SOFTLED) {
-			    ath_update_LED(dev, ah, ic, RECEIVE_EVENT);
+			    ath_update_LED(ah, ic, RECEIVE_EVENT);
 			}
 #endif
 			ath_rx_capture(dev, ds, skb);
@@ -1999,7 +2073,7 @@
 		}
 #ifdef SOFTLED
 		if (ic->ic_caps & IEEE80211_C_SOFTLED) {
-			ath_update_LED(dev, ah, ic, RECEIVE_EVENT);
+			ath_update_LED(ah, ic, RECEIVE_EVENT);
 		}
 #endif
 		ieee80211_input(dev, skb,
@@ -2331,7 +2405,7 @@
 	spin_unlock_bh(&sc->sc_txqlock[qNum]);
 	
 #ifdef SOFTLED
-	ath_update_LED(dev, ah, ic, TRANSMIT_EVENT);
+	ath_update_LED(ah, ic, TRANSMIT_EVENT);
 #endif
 	ath_hal_txstart(ah, qNum);
 	
@@ -2727,6 +2801,11 @@
 	DPRINTF(("%s: %s -> %s\n", __func__, stname[ostate], stname[nstate]));
 
 	ath_hal_setledstate(ah, leds[nstate]);	/* set LED */
+#ifdef SOFTLED
+	if (ostate != nstate && (ic->ic_caps & IEEE80211_C_SOFTLED)) {
+		ath_update_LED(ah, ic, STATE_EVENT + nstate);
+	}
+#endif
 	netif_stop_queue(dev);			/* before we do anything else */
 
 	if (nstate == IEEE80211_S_INIT) {
diff -x CVS -x .tmp_versions -uNr madwifi-orig/driver/if_ath_pci.c madwifi-led/driver/if_ath_pci.c
--- madwifi-orig/driver/if_ath_pci.c	2004-05-27 01:39:12.000000000 +0200
+++ madwifi-led/driver/if_ath_pci.c	2004-06-11 12:55:10.000000000 +0200
@@ -160,20 +160,19 @@
 		dev->name, athname ? athname : "Atheros ???", phymem, dev->irq);
 #ifdef SOFTLED
 	ath_sc = dev->priv;
-	ath_sc->sc_ic.ic_beaconCnt = 0;
 	/* Check to see if we have an IBM card */
 	printk ("Vendor = 0x%x   id=0x%x subsys: %d\n",id->vendor,id->device,
 		id->subdevice);
 	if ((id->vendor == 0x168c) && 
 	    ((id->device == 0x1014) || (id->device==0x12))) {
 		ath_sc->sc_ic.ic_ledPin = 0;
-		ath_sc->sc_ic.ic_rfKillPin = 1;
+		ath_sc->sc_ic.ic_ledInverse = 1;
+		ath_sc->sc_ic.ic_rfKillPin = -1;
 	} else {
 		ath_sc->sc_ic.ic_ledPin = 1;
+		ath_sc->sc_ic.ic_ledInverse = 0;
 		ath_sc->sc_ic.ic_rfKillPin = 0;
 	}
-	ath_hal_gpioCfgOutput(ath_sc->sc_ah, ath_sc->sc_ic.ic_ledPin);
-	ath_hal_gpioSet(ath_sc->sc_ah,ath_sc->sc_ic.ic_ledPin,0);
 	ath_sc->sc_ic.ic_caps |= IEEE80211_C_SOFTLED;
 #endif
 	
diff -x CVS -x .tmp_versions -uNr madwifi-orig/wlan/if_ieee80211.h madwifi-led/wlan/if_ieee80211.h
--- madwifi-orig/wlan/if_ieee80211.h	2004-05-27 01:39:51.000000000 +0200
+++ madwifi-led/wlan/if_ieee80211.h	2004-06-11 02:39:50.000000000 +0200
@@ -751,9 +751,13 @@
 	void			*ic_wep_ctx;	/* wep crypt context */
 	u_int32_t		ic_iv;		/* initial vector for wep */
 #ifdef SOFTLED
-        u_int16_t               ic_beaconCnt;   /* becaon Count for LEDs */
         u_int16_t               ic_ledPin;      /* GPIO pin for soft LED */
         u_int16_t               ic_rfKillPin;   /* GPIO pin for RF Kill */
+        u_int8_t                ic_ledInverse;  /* Is LED pin inverse? */
+        u_int16_t               ic_rfKillState; /* last read RF Kill GPIO state */
+        struct timer_list       ic_ledTimer;	/* timer for SOFTLED blinking */
+        u_int32_t               ic_ledStateList; /* bit array of future LED states */
+        u_int8_t                ic_ledStateLLen; /* number of used StateList bits */
 #endif
 #ifdef CONFIG_PROC_FS
 	char			ic_procname[12];/* e.g. wlan%d */
@@ -826,6 +830,8 @@
 #define POLL_EVENT 1                            /* Poll event for LED update */
 #define TRANSMIT_EVENT 2                        /* xmit event for LED update */
 #define RECEIVE_EVENT 3                         /* rcv event for LED update */
+#define STATE_EVENT 4                           /* range of events for HAL state */
+#define STATE_EVENT_MAX STATE_EVENT+IEEE80211_S_RUN /* max event */
 #endif
 
 u_int8_t ieee80211_get_rssi(struct ieee80211_node*);
diff -x CVS -x .tmp_versions -uNr madwifi-orig/wlan/if_ieee80211subr.c madwifi-led/wlan/if_ieee80211subr.c
--- madwifi-orig/wlan/if_ieee80211subr.c	2004-05-27 01:39:51.000000000 +0200
+++ madwifi-led/wlan/if_ieee80211subr.c	2004-06-10 23:39:56.000000000 +0200
@@ -1161,27 +1161,15 @@
 		if (ic->ic_state == IEEE80211_S_SCAN) {
 			if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
 			    subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
-#ifdef SOFTLED
-			    ic->ic_beaconCnt++;
-#endif
 				goto out;
 			}
 		} else {
 #if 0
 			if (ic->ic_opmode != IEEE80211_M_IBSS &&
 			    subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
-#ifdef SOFTLED
-			    ic->ic_beaconCnt++;
-#endif
 				goto out;
 			}
 #endif
-#ifdef SOFTLED
-			if (ic->ic_opmode != IEEE80211_M_IBSS &&
-			    subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
-			    ic->ic_beaconCnt++;
-			}
-#endif
 		}
 
 		if (netif_msg_debug(ic)) {
@@ -3012,9 +3000,6 @@
 	IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
 	ieee80211_add_recvhist(ni, rssi, rstamp, rantenna);
 	memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
-#ifdef SOFTLED
-	ic->ic_beaconCnt++;
-#endif
 	ni->ni_intval = le16_to_cpu(*(u_int16_t *)bintval);
 	ni->ni_capinfo = le16_to_cpu(*(u_int16_t *)capinfo);
 	ni->ni_chan = &ic->ic_channels[chan];
