#include <sos/types.h>
#include <hwcore/ioports.h>
#include <hwcore/irq.h>

#define KBD_IOPORT       0x60

#define KBD_CTRL_PRESSED (1<<0)
#define KBD_ALT_PRESSED  (1<<1)
#define KBD_DEL_PRESSED  (1<<2)

static unsigned char ctrlaltdel = 0;

static char no_idt[8] = {0, };
static void reboot()
{
  asm volatile("lidt %0 ; int $45": :"m" (no_idt));
}

static void kbd_irq(int id_irq)
{
  unsigned char c;
  sos_bool_t    key_up = FALSE;
  unsigned char mask = 0;

  /* Recupere le scancode */
  c = inb(KBD_IOPORT);

  /* On ignore les scancodes "etendus" */
  if (c == 0xe0)
    {
      inb(KBD_IOPORT);
      return;
    }

  /* On detecte si la touche est relachee ou pas */
  if (c >= 0x80)
    {
      key_up = TRUE;
      c -= 0x80;
    }

  switch (c)
    {
    case 29: /* Left Ctrl */
      mask = KBD_CTRL_PRESSED;
      break;
    case 56 /* Left ALT */:
      mask = KBD_ALT_PRESSED;
      break;
    case 83: /* Pav Num 'point' */
      mask = KBD_DEL_PRESSED;
      break;

    default:
      return;
    }


  if (key_up)
    ctrlaltdel &= ~mask;
  else
    ctrlaltdel |= mask;

  if (ctrlaltdel == (KBD_ALT_PRESSED
		     | KBD_CTRL_PRESSED
		     | KBD_DEL_PRESSED))
    {
      reboot();
    }
}

void setup_ctrlaltdel()
{
  sos_irq_set_routine(SOS_IRQ_KEYBOARD,
		      kbd_irq);
}
