/*
 *  This code expects that the PROM already defines routines called "led-on"
 *  and "led-off" to toggle the led state. If that's not the case, you should
 *  add them, i.e.:
 *
 *             ok nvedit
 *             1: : led-on aux@ 1 or aux! ;
 *             2: : led-off aux@ 1 not and aux! ;
 *             3: ^C
 *             ok nvstore
 *             ok nvrun
 *             ok setenv use-nvramrc? true
 *
 */

static const char rcsid[] = "$Id: led.c,v 1.1 1997/10/05 06:34:56 jhawk Exp jhawk $ ";

#define _KERNEL

#include <sys/types.h>
#include <sys/systm.h>

#include <sys/modctl.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>

#undef _KERNEL

#include <sys/param.h>
#include <sys/promif.h>

static struct modlmisc ledmisc = {
  &mod_miscops,
  "jhawk's led twiddler"
};

static struct modlinkage led_modlinkage = {
  MODREV_1,
  &ledmisc,
  NULL
};

void blink_led();

int led_freq;
int led_freq_calc;
static int led_timeout;

void (*led_old_idle)();
extern void (*idle_cpu)();

int _fini()
{
  if (led_timeout)
    untimeout(led_timeout);
  prom_interpret("led-on",0,0,0,0,0);
  return mod_remove(&led_modlinkage);
}

int _info(struct modinfo *modp)
{
  return mod_info(&led_modlinkage, modp);
}

#define LEDFREQ (hz)

int _init()
{
  led_freq = LEDFREQ;
  led_freq_calc = -1;
 
  led_timeout = timeout(blink_led, NULL, led_freq);

  return mod_install(&led_modlinkage);
}



/* Macros to see if the load-average is greater than a/1 or 1/b */
#define LOADGTM(a) (avenrun < (a)*FSCALE)
#define LOADGTD(b) (avenrun < FSCALE/(b))

void blink_led() {
  static int state;
  extern long avenrun;
  int load;

  /*
   * Here we just use led_freq to set the frequency of blinks.
   * Potentially a more advanced scheme would involve a mechanism
   * for more complicated patterns, like an array of delays.
   */

  if (led_freq_calc) {
    if LOADGTD(2)
      led_freq = 4*hz;
    else if LOADGTM(1)
      led_freq = 2*hz;
    else if LOADGTM(2)
      led_freq = hz;
    else if LOADGTM(4)
      led_freq = hz/2;
    else
      led_freq = hz/4;
  }

  prom_interpret( state?"led-off":"led-on",
		  0,0,0,0,0);
  state ^= 1;
#ifdef LEDDEBUG
  printf("freq %d\n", led_freq);
#endif
  led_timeout = timeout(blink_led, NULL, led_freq);

}
