/***********************************************************/
/*                                                         */
/*     Power Management Program for Libretto V1.0          */
/*                                                         */
/*              1996/09/05  Masakazu Iizuka                */
/*              1998/04/29  use SMI by S.Nomura            */
/*              1998/05/25  Small Bug Fix by T.Ishioka     */
/*                                                         */
/***********************************************************/

#undef HAVE_GETOPT_LONG
#ifdef __linux__
#define HAVE_GETOPT_LONG 1
#endif

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#endif
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include "libapm.h"

#ifndef CMOS_ACCESS
#include "bios.h"
#endif /* CMOS_ACCESS */

#undef DEBUG

typedef struct {
    int   powerup;    /* Power-up Mode           */
    int   standby;    /* Standby Time            */
    int   off;        /* System Auto Off         */
    int   panel;      /* Panal Power On/Off      */
    int   on;         /* Alarm Power On          */
    char  hour[3];    /* Alarm Power On (Hour)   */
    char  min[3];     /* Alarm Power On (Minute) */
    int   lcd;        /* LCD Power               */
    int   vol;        /* Beep Volume             */
    int   suspend;    /* Suspend or Hybernation  */
} PMFLAG;

char   version[] = "1.0beta5";
PMFLAG cmos = { -1, -1, -1, -1, -1, "", "", -1, -1, -1 };
PMFLAG exec = { -1, -1, -1, -1, -1, "", "", -1, -1, -1 };

void get_status(void);
void print_status(void);
void set_powerup(void);
void set_standby(void);
void set_off(void);
void set_panel(void);
void set_on(void);
void set_lcd(void);
void usage(void);
int time_conv(char *);
#ifndef CMOS_ACCESS
void set_vol(void);
void set_suspend(void);
void init(void);
#endif /* CMOS_ACCESS */

int main(int argc, char *argv[])
{
    int r;
    char c;

#ifdef HAVE_GETOPT_LONG
    struct option longopts[] = {
      { "Help",        0, 0, 'h' },
      { "Version",     0, 0, 'v' },
      { "PowerUp",     1, 0, 'P' },
      { "StandbyTime", 1, 0, 'T' },
      { "AutoOff",     1, 0, 'a' },
      { "PanelSwitch", 1, 0, 'S' },
      { "AlarmOn",     1, 0, 'A' },
      { "LcdPower",    1, 0, 'L' },
#ifndef CMOS_ACCESS
      { "Volume",      1, 0, 'V' },
      { "Off",         1, 0, 'O' },
#endif /* CMOS_ACCESS */
      {0, 0, 0, 0}
    };
#endif

    if( 0 != geteuid() ){
        printf("%s: Only root can execute !!\n", argv[0]);
        exit(-1);
    }

#ifdef LIBRETTO
    r = islibretto();
    if (r != 0){
      printf("Only Use \"TOSHIBA Libretto20/50\"\n");
      exit(0);
    }
#endif /* LIBRETTO */

#ifndef CMOS_ACCESS
    init();
#endif /* CMOS_ACCESS */

    get_status();

#ifdef HAVE_GETOPT_LONG
    while ((c = getopt_long(argc,argv,
                            "hvP:T:a:S:A:L:V:O:", longopts, NULL)) != -1) {
#else
    while ((c = getopt(argc,argv, "hvP:T:a:S:A:L:V:O:")) != -1) {
#endif
      switch (c) {
        case 'h':
          usage();
          break;
        case 'v':
          printf("version : %s\n", version);
          exit(0);
          break;
        case 'P':
          if (strcmp(optarg, "boot")        == 0)  exec.powerup = 0;
          if (strcmp(optarg, "hibernation") == 0)  exec.powerup = 1;
          if (exec.powerup == -1)  usage();
          break;
        case 'T':
#ifdef CMOS_ACCESS
          if (strcmp(optarg,  "0") == 0)  exec.standby = 0;
          if (strcmp(optarg,  "5") == 0)  exec.standby = 1;
          if (strcmp(optarg, "10") == 0)  exec.standby = 2;
          if (strcmp(optarg, "15") == 0)  exec.standby = 3;
          if (strcmp(optarg, "30") == 0)  exec.standby = 4;
          if (strcmp(optarg, "45") == 0)  exec.standby = 5;
          if (strcmp(optarg, "60") == 0)  exec.standby = 6;
          if (strcmp(optarg, "unlimit") == 0)  exec.standby = 7;
#else
          if (strcmp(optarg,  "0") == 0)  exec.standby = TIME_00;
          if (strcmp(optarg,  "5") == 0)  exec.standby = TIME_05;
          if (strcmp(optarg, "10") == 0)  exec.standby = TIME_10;
          if (strcmp(optarg, "15") == 0)  exec.standby = TIME_15;
          if (strcmp(optarg, "30") == 0)  exec.standby = TIME_30;
          if (strcmp(optarg, "45") == 0)  exec.standby = TIME_45;
          if (strcmp(optarg, "60") == 0)  exec.standby = TIME_60;
          if (strcmp(optarg, "unlimit") == 0)  exec.standby = TIME_UNLIMIT;
#endif /* CMOS_ACCESS */
          if (exec.standby == -1)  usage();
          break;
        case 'a':
#ifdef CMOS_ACCESS
          if (strcmp(optarg, "disable") == 0)  exec.off = 0;
          if (strcmp(optarg, "10")      == 0)  exec.off = 1;
          if (strcmp(optarg, "20")      == 0)  exec.off = 2;
          if (strcmp(optarg, "30")      == 0)  exec.off = 3;
          if (strcmp(optarg, "40")      == 0)  exec.off = 4;
          if (strcmp(optarg, "50")      == 0)  exec.off = 5;
          if (strcmp(optarg, "60")      == 0)  exec.off = 6;
#else
          if (strcmp(optarg, "disable") == 0)  exec.off = TIME_00;
          if (strcmp(optarg, "10")      == 0)  exec.off = TIME_10;
          if (strcmp(optarg, "20")      == 0)  exec.off = TIME_20;
          if (strcmp(optarg, "30")      == 0)  exec.off = TIME_30;
          if (strcmp(optarg, "40")      == 0)  exec.off = TIME_40;
          if (strcmp(optarg, "50")      == 0)  exec.off = TIME_50;
          if (strcmp(optarg, "60")      == 0)  exec.off = TIME_60;
#endif /* CMOS_ACCESS */
          if (exec.off == -1)  usage();
          break;
        case 'S':
          if (strcmp(optarg, "disable") == 0)  exec.panel = 0;
          if (strcmp(optarg, "enable")  == 0)  exec.panel = 1;
          if (exec.panel == -1)  usage();
          break;
        case 'A':
          if (strcmp(optarg, "disable") == 0)  exec.on = 0;
          time_conv(optarg);
          if (exec.on == -1)  usage();
          break;
        case 'L':
          if (strcmp(optarg, "0") == 0)  exec.lcd = 0;
          if (strcmp(optarg, "1") == 0)  exec.lcd = 1;
          if (strcmp(optarg, "2") == 0)  exec.lcd = 2;
          if (strcmp(optarg, "3") == 0)  exec.lcd = 3;
          if (exec.lcd == -1)  usage();
          break;
#ifndef CMOS_ACCESS
        case 'V':
          if (strcmp(optarg, "0") == 0)  exec.vol = VOL_OFF;
          else if (strcmp(optarg, "1") == 0)  exec.vol = VOL_LOW;
          else if (strcmp(optarg, "2") == 0)  exec.vol = VOL_MID;
          else if (strcmp(optarg, "3") == 0)  exec.vol = VOL_HIGH;
          else usage();
          break;
        case 'O':
          if (strcmp(optarg, "suspend") == 0)  exec.suspend = 0;
          else if (strcmp(optarg, "hibernation") == 0)  exec.suspend = 1;
          else usage();
          break;
#endif /* CMOS_ACCESS */
        case '?':
          usage();
          break;
        default: break;
      }
    }
#ifdef DEBUG
    printf("POWERUP:%d STANDBY:%d OFF:%d PANEL:%d ON:%d(%s:%s) LCD:%d\n",
           exec.powerup, exec.standby, exec.off, exec.panel,
           exec.on, exec.hour, exec.min, exec.lcd);
#endif
    if (exec.powerup != -1)  set_powerup();
    if (exec.standby != -1)  set_standby();
    if (exec.off     != -1)  set_off();
    if (exec.panel   != -1)  set_panel();
    if (exec.on      != -1)  set_on();
    if (exec.lcd     != -1)  set_lcd();
#ifndef CMOS_ACCESS
    if (exec.vol     != -1)  set_vol();
    if (exec.suspend != -1)  set_suspend();
#endif /* CMOS_ACCESS */
    get_status();
    print_status();
    exit(0);
}

void usage(void)
{
#ifdef CMOS_ACCESS
# ifdef HAVE_GETOPT_LONG
    printf("\n\
usage: libretto-config [-v --Version]\n\
              [-h --Help]\n\
              [-P --PowerUp {boot,hibernation}]\n\
              [-T --StandbyTime {0,5,10,15,30,45,60,unlimit}]\n\
              [-a --AutoOff {disable,10,20,30,40,50,60}]\n\
              [-S --PanelSwitch {disable,enable}]\n\
              [-A --AlarmOn {disable,<time>}]\n\
              [-L --LcdPower {0,1,2,3}]\n\
          \n");
# else /* not HAVE_GETOPT_LONG */
    printf("\n\
usage: libretto-config [-v			: Version]\n\
              [-h				: Help]\n\
              [-P {boot,hibernation}		: PowerUp]\n\
              [-T {0,5,10,15,30,45,60,unlimit}	: StandbyTime]\n\
              [-a {disable,10,20,30,40,50,60}	: AutoOff]\n\
              [-S {disable,enable}		: PanelSwitch]\n\
              [-A {disable,<time>}		: AlarmOn]\n\
              [-L {0,1,2,3}			: LcdPower]\n\
          \n");
# endif /* HAVE_GETOPT_LONG */

#else /* not CMOS_ACCESS */

# ifdef HAVE_GETOPT_LONG
    printf("\
usage: libretto-config [-v --Version]\n\
              [-h --Help]\n\
              [-P --PowerUp {boot,hibernation}]\n\
              [-T --StandbyTime {0,5,10,15,30,45,60,unlimit}]\n\
              [-a --AutoOff {disable,10,20,30,40,50,60}]\n\
              [-S --PanelSwitch {disable,enable}]\n\
              [-A --AlarmOn {disable,<time>}]\n\
              [-L --LcdPower {0,1,2,3}]\n\
              [-V --Volume {0,1,2,3}]\n\
              [-O --Off {suspend|hibernation}  Use Only >= Libretto100]\n\
          \n");
# else /* not HAVE_GETOPT_LONG */
    printf("\
usage: libretto-config [-v			: Version]\n\
              [-h				: Help]\n\
              [-P {boot,hibernation}		: PowerUp]\n\
              [-T {0,5,10,15,30,45,60,unlimit}	: StandbyTime]\n\
              [-a {disable,10,20,30,40,50,60}	: AutoOff]\n\
              [-S {disable,enable}		: PanelSwitch]\n\
              [-A {disable,<time>}		: AlarmOn]\n\
              [-L {0,1,2,3}			: LcdPower]\n\
              [-V {0,1,2,3}			: Volume]\n\
              [-O {suspend|hibernation}		: Off (Use Only>=Libretto100)]\n\
          \n");
# endif /* HAVE_GETOPT_LONG */

#endif /* CMOS_ACCESS */
    exit(1);
}

#ifndef CMOS_ACCESS
void init(void)
{
  /* SMI port */
#ifdef __linux__
  ioperm(0xb2, 1, 1);
#else
  open("/dev/io", O_RDWR, 0);
#endif
}
#endif /* CMOS_ACCESS */

void get_status(void)
{
#ifdef CMOS_ACCESS
    char  r, h, m;
#else
    u_short ret, st;
#endif /* CMOS_ACCESS */

    /*
        Power-up Mode
    */
#ifdef CMOS_ACCESS
    r = get_cmos(0x38);
    if ((r & 0x10) == 0x00)  cmos.powerup = 0;  /* Disable */
    if ((r & 0x10) == 0x10)  cmos.powerup = 1;  /* Enable */
#else
    if ((ret = bios_read(BIOS_POWERSW_MODE, &st)) != 0x0000){
      fprintf(stderr, "Can not get BIOS_POWERSW_MODE: 0x%x\n", ret);
      return;
    }
    if (st == POWERSW_BOOT)
      cmos.powerup = 0;  /* boot */
    else if (st == POWERSW_HIBER)
      cmos.powerup = 1;  /* resume */
    else {
      fprintf(stderr, "Unknown POWERSW_MODE: 0x%x\n", st);
      return;
    }
#endif /* CMOS_ACCESS */

    /*
        Standby Time
    */
#ifdef CMOS_ACCESS
    r = get_cmos(0x46);
    if ((r & 0x07) == 0x00)  cmos.standby = 0;  /*  0 min */
    if ((r & 0x07) == 0x01)  cmos.standby = 1;  /*  5 min */
    if ((r & 0x07) == 0x02)  cmos.standby = 2;  /* 10 min */
    if ((r & 0x07) == 0x03)  cmos.standby = 3;  /* 15 min */
    if ((r & 0x07) == 0x04)  cmos.standby = 4;  /* 30 min */
    if ((r & 0x07) == 0x05)  cmos.standby = 5;  /* 45 min */
    if ((r & 0x07) == 0x06)  cmos.standby = 6;  /* 60 min */
    if ((r & 0x07) == 0x07)  cmos.standby = 7;  /* unlimit */
#else
    if ((ret = bios_read(BIOS_STANDBYTIME, &st)) == 0x0000){
      switch (st){
      case TIME_00: case TIME_05: case TIME_10: case TIME_15:
      case TIME_30: case TIME_45: case TIME_60: case TIME_UNLIMIT:
        cmos.standby = st;
        break;
      default:
        fprintf(stderr, "Error: Unknown STANDBYTIME: 0x%x\n", st);
      }
    } else if (ret == 0x8000){
      /* not supported */
#if 0
      fprintf(stderr, "STANDBY TIME is not supported.\n");
#endif
    } else {
      fprintf(stderr, "Error: Can not get BIOS_STANDBYTIME: 0x%x\n", ret);
      return;
    }
#endif /* CMOS_ACCESS */

    /*
        System Auto Off
    */
#ifdef CMOS_ACCESS
    r = get_cmos(0x40);
    if ((r & 0x07) == 0x00)  cmos.off = 0;      /* Disable */
    if ((r & 0x07) == 0x01)  cmos.off = 1;      /* 10 min  */
    if ((r & 0x07) == 0x02)  cmos.off = 2;      /* 20 min  */
    if ((r & 0x07) == 0x03)  cmos.off = 3;      /* 30 min  */
    if ((r & 0x07) == 0x04)  cmos.off = 4;      /* 40 min  */
    if ((r & 0x07) == 0x05)  cmos.off = 5;      /* 50 min  */
    if ((r & 0x07) == 0x06)  cmos.off = 6;      /* 60 min  */
#else
    if ((ret = bios_read(BIOS_AUTOOFF, &st)) == 0x0000){
      switch (st){
      case TIME_00: case TIME_10: case TIME_20: case TIME_30:
      case TIME_40: case TIME_50: case TIME_60:
        cmos.off = st;
        break;
      default:
        fprintf(stderr, "Error: Unknown AUTOOFF: 0x%x\n", st);
      }
    } else if (ret == 0x8000){
      /* not supported */
#if 0
      fprintf(stderr, "AUTOOFF TIMER is not supported.\n");
#endif
    } else {
      fprintf(stderr, "Error: Can not get BIOS_AUTOOFF: 0x%x\n", ret);
      return;
    }
#endif /* CMOS_ACCESS */

    /*
        Panel Power On/Off
    */
#ifdef CMOS_ACCESS
    r = get_cmos(0x40);
    if ((r & 0x10) == 0x00)  cmos.panel = 0;    /* Disable */
    if ((r & 0x10) == 0x10)  cmos.panel = 1;    /* Enable */
#else
    if ((ret = bios_read(BIOS_PANELSW, &st)) == 0x0000){
      if (st == 0x0000)  cmos.panel = 0;    /* Disable */
      else if (st == 0x0001)  cmos.panel = 1;    /* Enable */
    } else if (ret == 0x8000){
      /* not supported */
#if 0
      fprintf(stderr, "PANEL POWER On/Off is not supported.\n");
#endif
    } else {
      fprintf(stderr, "Error: Can not get BIOS_PANELSW: 0x%x\n", ret);
      return;
    }
#endif /* CMOS_ACCESS */

    /*
        Alarm Power On
    */
#ifdef CMOS_ACCESS
    r = get_cmos(0x40);
    h = get_cmos(0x41);
    m = get_cmos(0x42);
    if ((r & 0x80) == 0x00)  cmos.on = 0;       /* Disable */
    if ((r & 0x80) == 0x80){                    /* Enable */
      cmos.on = 1;
      cmos.hour[0] = i2a((h & 0xf0) >> 4);      /* Hour */
      cmos.hour[1] = i2a(h & 0x0f);
      cmos.hour[2] = '\0';
      cmos.min[0]  = i2a((m & 0xf0) >> 4);      /* Minute */
      cmos.min[1]  = i2a(m & 0x0f);
      cmos.min[2]  = '\0';
    }
#else
    if ((ret = bios_read(BIOS_WAKEUP_TIME, &st)) == 0x0000){
      if (st & 0x0001)
        cmos.on = 0;       /* Disable */
      else {
        cmos.on = 1;
        sprintf(cmos.hour, "%02d", (st >> 7) & 0x1f);
        sprintf(cmos.min, "%02d", (st >> 1) & 0x3f);
      }
    } else if (ret == 0x8000){
      /* not supported */
#if 0
      fprintf(stderr, "ALARM POWER ON is not supported.\n");
#endif
    } else {
      fprintf(stderr, "Error: Can not get BIOS_WAKEUP_TIME: 0x%x\n", ret);
      return;
    }
#endif /* CMOS_ACCESS */

    /*
        LCD Power
    */
#ifdef CMOS_ACCESS
    r = get_cmos(0x37);
    if ((r & 0x0f) == 0x00)  cmos.lcd = 0;
    if ((r & 0x0f) == 0x04)  cmos.lcd = 1;
    if ((r & 0x0f) == 0x08)  cmos.lcd = 2;
    if ((r & 0x0f) == 0x0c)  cmos.lcd = 3;
#else
    if ((ret = bios_read(BIOS_LCD, &st)) == 0x0000){
      cmos.lcd = st;
    } else if (ret == 0x8000){
      /* not supported */
#if 0
      fprintf(stderr, "LCD BACK LIGHT CONTROL is not supported.\n");
#endif
    } else {
      fprintf(stderr, "Error: Can not get BIOS_LCD: 0x%x\n", ret);
      return;
    }
#endif /* CMOS_ACCESS */


#ifndef CMOS_ACCESS
    /*
        Volume
    */
    if ((ret = bios_read(BIOS_VOL, &st)) == 0x0000){
      cmos.vol = st;
    } else if (ret == 0x8000){
      /* not supported */
#if 0
      fprintf(stderr, "VOLUME CONTROL is not supported.\n");
#endif
    } else {
      fprintf(stderr, "Error: Can not get BIOS_VOL: 0x%x\n", ret);
      return;
    }
#endif /* CMOS_ACCESS */

#ifndef CMOS_ACCESS
    /*
        Suspend/Hiber
    */
    if ((ret = bios_read(BIOS_SUSPEND, &st)) == 0x0000){
      cmos.suspend = st;
    } else if (ret == 0x8000){
      /* not supported */
#if 0
      fprintf(stderr, "SUSPEND is not supported.\n");
#endif
    } else {
      fprintf(stderr, "Error: Can not get BIOS_SUSPEND: 0x%x\n", ret);
      return;
    }
#endif /* CMOS_ACCESS */
}

void set_powerup(void)
{
#ifdef CMOS_ACCESS
    char r;

    if (exec.powerup == 0 && cmos.powerup != 0){
      r = get_cmos(0x37);
      set_cmos(0x37, r - 0x10);
      r = get_cmos(0x38);
      set_cmos(0x38, r - 0x10);
    }
    if (exec.powerup == 1 && cmos.powerup != 1){
      r = get_cmos(0x37);
      set_cmos(0x37, r + 0x10);
      r = get_cmos(0x38);
      set_cmos(0x38, r+ 0x10);
    }
#else
    if (cmos.powerup < 0)
      return;
    if (cmos.powerup != exec.powerup){
      bios_write(BIOS_POWERSW_MODE, exec.powerup);
    }
#endif /* CMOS_ACCESS */
}

void set_standby(void)
{
#ifdef CMOS_ACCESS
    char r;

    if (cmos.standby != exec.standby){
      r = get_cmos(0x46);
      set_cmos(0x46, r - cmos.standby + exec.standby);
      r = get_cmos(0x47);
      set_cmos(0x47, r - cmos.standby + exec.standby);
    }
#else
    if (cmos.standby < 0)
      return;
    if (cmos.standby != exec.standby){
      bios_write(BIOS_STANDBYTIME, exec.standby);
    }
#endif /* CMOS_ACCESS */
}

void set_off(void)
{
#ifdef CMOS_ACCESS
    char r;

    if (cmos.off != exec.off){
      r = get_cmos(0x40);
      set_cmos(0x40, r - cmos.off + exec.off);
      r = get_cmos(0x47);
      set_cmos(0x47, r - cmos.off + exec.off);
    }
#else
    if (cmos.off < 0)
      return;
    if (cmos.off != exec.off){
      bios_write(BIOS_AUTOOFF, exec.off);
    }
#endif
}

void set_panel(void)
{
#ifdef CMOS_ACCESS
    char r;

    if (exec.panel == 0 && cmos.panel != 0){
      r = get_cmos(0x40);
      set_cmos(0x40, r - 0x10);
      r = get_cmos(0x47);
      set_cmos(0x47, r - 0x10);
      r = get_physmem(0x046e);
      set_physmem(0x046e, r - 0x01);
#ifdef DEBUG
      printf("0000:046e = %04x -> %04x\n", r, get_physmem(0x046e));
#endif
    }
    if (exec.panel == 1 && cmos.panel != 1){
      r = get_cmos(0x40);
      set_cmos(0x40, r + 0x10);
      r = get_cmos(0x47);
      set_cmos(0x47, r + 0x10);
      r = get_physmem(0x046e);
      set_physmem(0x046e, r + 0x01);
#ifdef DEBUG
      printf("0000:046e = %04x -> %04x\n", r, get_physmem(0x046e));
#endif
    }
#else
    if (cmos.panel < 0)
      return;
    if (cmos.panel != exec.panel){
      bios_write(BIOS_PANELSW, exec.panel);
    }
#endif /* CMOS_ACCESS */
}

void set_on(void)
{
    int h1 = 0;
    int h2 = 0;
    int m1 = 0;
    int m2 = 0;
#ifdef CMOS_ACCESS
    char r;

    if (exec.on == 1){
      h1 = a2i(exec.hour[0]) * 16 + a2i(exec.hour[1]);
      m1 = a2i(exec.min[0])  * 16 + a2i(exec.min[1]);
    }
    if (cmos.on == 1){
      h2 = a2i(cmos.hour[0]) * 16 + a2i(cmos.hour[1]);
      m2 = a2i(cmos.min[0])  * 16 + a2i(cmos.min[1]);
    }
    if (exec.on < cmos.on){                 /* Disable */
      r = get_cmos(0x40);
      set_cmos(0x40, r - 0x80);
      set_cmos(0x41, 0x80);
      set_cmos(0x42, 0x00);
      r = get_cmos(0x47);
      set_cmos(0x47, r - h2 - m2 - 0x80);
    }
    if (exec.on > cmos.on){                 /* Enable */
      r = get_cmos(0x40);
      set_cmos(0x40, r + 0x80);
      set_cmos(0x41, h1);
      set_cmos(0x42, m1);
      r = get_cmos(0x47);
      set_cmos(0x47, r + h1 + m1 + 0x80);
    }
    if ((exec.on == cmos.on) && (exec.on == 1)){ /* Time Change */
      if ((h1 == h2) && (m1 == m2)){
        ;
      }else{
        set_cmos(0x41, h1);
        set_cmos(0x42, m1);
        r = get_cmos(0x47);
        set_cmos(0x47, r - h2 - m2 + h1 + m1);
      }
    }
#else
    u_short val;

    if (cmos.on < 0)
      return;
    if (exec.on == 1){
      h1 = a2i(exec.hour[0]) * 10 + a2i(exec.hour[1]);
      m1 = a2i(exec.min[0])  * 10 + a2i(exec.min[1]);
    }
    if (cmos.on == 1){
      h2 = a2i(cmos.hour[0]) * 10 + a2i(cmos.hour[1]);
      m2 = a2i(cmos.min[0])  * 10 + a2i(cmos.min[1]);
    }
    if (exec.on < cmos.on){                 /* Disable */
      bios_write(BIOS_WAKEUP_DATE, 0x0000);
      bios_write(BIOS_WAKEUP_TIME, 0x0001);
    }
    if (exec.on){                 /* Enable */
      val = (h1 << 7) | (m1 << 1);
      bios_write(BIOS_WAKEUP_TIME, val);
    }
#endif /* CMOS_ACCESS */
}

void set_lcd(void)
{
#ifdef CMOS_ACCESS
    char r;

    if (exec.lcd != cmos.lcd){
      r = get_cmos(0x37);
      set_cmos(0x37, r + (exec.lcd - cmos.lcd) * 4);
      r = get_cmos(0x38);
      set_cmos(0x38, r + (exec.lcd - cmos.lcd) * 4);
    }
#else
    if (cmos.lcd < 0)
      return;
    if (exec.lcd != cmos.lcd){
      bios_write(BIOS_LCD, exec.lcd);
    }
#endif /* CMOS_ACCESS */
}

#ifndef CMOS_ACCESS
void set_vol(void)
{
    if (cmos.vol < 0)
      return;
    if (exec.vol != cmos.vol){
      bios_write(BIOS_VOL, exec.vol);
    }
}

void set_suspend(void)
{
    if (cmos.suspend < 0)
      return;
    if (exec.suspend != cmos.suspend){
      bios_write(BIOS_SUSPEND, exec.suspend);
    }
}
#endif /* CMOS_ACCESS */

void print_status(void)
{
    char s[8][50], wk[50];

    sprintf(s[0], "Unknown");
    if (cmos.powerup == 0)  sprintf(s[0], "Boot");
    if (cmos.powerup == 1)  sprintf(s[0], "Hibernation");
    sprintf(s[1], "Unknown");
#ifdef CMOS_ACCESS
    if (cmos.standby == 0)  sprintf(s[1], "0 min");
    if (cmos.standby == 1)  sprintf(s[1], "5 min");
    if (cmos.standby == 2)  sprintf(s[1], "10 min");
    if (cmos.standby == 3)  sprintf(s[1], "15 min");
    if (cmos.standby == 4)  sprintf(s[1], "30 min");
    if (cmos.standby == 5)  sprintf(s[1], "45 min");
    if (cmos.standby == 6)  sprintf(s[1], "60 min");
    if (cmos.standby == 7)  sprintf(s[1], "Unlimit");
#else
    if (cmos.standby == TIME_00)  sprintf(s[1], "0 min");
    if (cmos.standby == TIME_05)  sprintf(s[1], "5 min");
    if (cmos.standby == TIME_10)  sprintf(s[1], "10 min");
    if (cmos.standby == TIME_15)  sprintf(s[1], "15 min");
    if (cmos.standby == TIME_30)  sprintf(s[1], "30 min");
    if (cmos.standby == TIME_45)  sprintf(s[1], "45 min");
    if (cmos.standby == TIME_60)  sprintf(s[1], "60 min");
    if (cmos.standby == TIME_UNLIMIT)  sprintf(s[1], "Unlimit");
#endif /* CMOS_ACCESS */
    if (cmos.powerup == 0){
      strcpy(wk, s[1]);
      sprintf(s[1], "****** (%s)", wk);
    }
    sprintf(s[2], "Unknown");
#ifdef CMOS_ACCESS
    if (cmos.off == 0)  sprintf(s[2], "Disabled");
    if (cmos.off == 1)  sprintf(s[2], "10 min");
    if (cmos.off == 2)  sprintf(s[2], "20 min");
    if (cmos.off == 3)  sprintf(s[2], "30 min");
    if (cmos.off == 4)  sprintf(s[2], "40 min");
    if (cmos.off == 5)  sprintf(s[2], "50 min");
    if (cmos.off == 6)  sprintf(s[2], "60 min");
#else
    if (cmos.off == TIME_00)  sprintf(s[2], "Disabled");
    if (cmos.off == TIME_10)  sprintf(s[2], "10 min");
    if (cmos.off == TIME_20)  sprintf(s[2], "20 min");
    if (cmos.off == TIME_30)  sprintf(s[2], "30 min");
    if (cmos.off == TIME_40)  sprintf(s[2], "40 min");
    if (cmos.off == TIME_50)  sprintf(s[2], "50 min");
    if (cmos.off == TIME_60)  sprintf(s[2], "60 min");
#endif /* CMOS_ACCESS */
    sprintf(s[3], "Unknown");
    if (cmos.panel == 0)  sprintf(s[3], "Disabled");
    if (cmos.panel == 1)  sprintf(s[3], "Enabled");
    if (cmos.powerup == 0){
      strcpy(wk, s[3]);
      sprintf(s[3], "****** (%s)", wk);
    }
    sprintf(s[4], "Unknown");
    if (cmos.on == 0)  sprintf(s[4], "Disabled");
    if (cmos.on == 1){
      if ((cmos.hour[0] != '\0') && (cmos.min[0] != '\0')){
        sprintf(s[4], "%2s:%2s", cmos.hour, cmos.min);
      }
    }
    sprintf(s[5], "Unknown");
    if (cmos.lcd == 0)  sprintf(s[5], "0");
    if (cmos.lcd == 1)  sprintf(s[5], "1");
    if (cmos.lcd == 2)  sprintf(s[5], "2");
    if (cmos.lcd == 3)  sprintf(s[5], "3");
#ifndef CMOS_ACCESS
    sprintf(s[6], "Unknown");
    if (cmos.vol == VOL_OFF)  sprintf(s[6], "off");
    else if (cmos.vol == VOL_LOW)  sprintf(s[6], "low");
    else if (cmos.vol == VOL_MID)  sprintf(s[6], "mid");
    else if (cmos.vol == VOL_HIGH)  sprintf(s[6], "high");
    sprintf(s[7], "Unknown");
    if (cmos.suspend == 0)  sprintf(s[7], "Suspend");
    else if (cmos.suspend == 1)  sprintf(s[7], "Hibernation");
#endif /* CMOS_ACCESS */

#ifndef CMOS_ACCESS
    printf("\
Power Management for Libretto V%-8s\n\
+-----------------------------------------------------------+\n\
|   0) Power-up Mode      : %-32s|\n\
|   1) Standby Time       : %-32s|\n\
|   2) System Auto Off    : %-32s|\n\
|   3) Panel Power On/Off : %-32s|\n\
|   4) Alarm Power On     : %-32s|\n\
|   5) LCD Power          : %-32s|\n\
|   6) Volume             : %-32s|\n\
|   7) Off (Suspend/Hiber): %-32s|\n\
+-----------------------------------------------------------+\n\n",
    version, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]);
#else
    printf("\
Power Management for Libretto V%-8s\n\
+-----------------------------------------------------------+\n\
|   0) Power-up Mode      : %-32s|\n\
|   1) Standby Time       : %-32s|\n\
|   2) System Auto Off    : %-32s|\n\
|   3) Panel Power On/Off : %-32s|\n\
|   4) Alarm Power On     : %-32s|\n\
|   5) LCD Power          : %-32s|\n\
+-----------------------------------------------------------+\n\n",
    version, s[0], s[1], s[2], s[3], s[4], s[5]);
#endif /* CMOS_ACCESS */
}

int time_conv(char *str)
{
  char s[6];
  int r = 1;
  int hh, mm;

  strncpy(s, str, 5); s[5]=0x00;
  hh = a2i(s[0]) * 10 + a2i(s[1]);
  mm = a2i(s[3]) * 10 + a2i(s[4]);
  if (hh >= 0 && hh < 24){
    if (mm >= 0 && mm < 60){
      if (s[2] == ':' && s[5] == '\0'){
        exec.on = 1;
        exec.hour[0] = s[0];
        exec.hour[1] = s[1];
        exec.hour[2] = '\0';
        exec.min[0]  = s[3];
        exec.min[1]  = s[4];
        exec.min[2]  = '\0';
        r = 0;
     }
    }
  }
  return r;
}


syntax highlighted by Code2HTML, v. 0.9.1