/*
 * This is 'pwrm', the laptop power manager.
 *
 * Copyright (c) 1992,93 Hansruedi Heeb
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 1, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Author's address: heeb@iis.ethz.ch
 */

#include <stdio.h>
#include <unistd.h>

#include "pwrm.h"
#include "portio.h"

void installation_check()
{
  int b1,b2;

  b1=read_locked_port(LOCK_STATUS_REGISTER_PORT) & 0x8000;
  b2=read_locked_port(LOCK_STATUS_REGISTER_PORT) & 0x8000;
  if (b1==b2) {
    fprintf(stderr,"*** no WD7600 Chipset installed, exit.\n",
	    b1,b2);
    exit(1);
  }
}

void status_report(char *name)
{
  int i,out_l,out_h,inp,intr,nmi,b_timer,l_timer;
  int port_cs,disk_cs,prog_cs,cpu_cl;
  int fl_op,fl_cs1,fl_cs2,fl_qu,fl_ct;

  out_l  =read_locked_byte_port(PMC_OUTPUT_CONTROL_REG_0_7_PORT);
  out_h  =read_locked_byte_port(PMC_OUTPUT_CONTROL_REG_8_15_PORT);
  inp    =read_locked_port(PMC_INPUTS_PORT);
  intr   =read_locked_port(PMC_INTERRUPT_ENABLE_PORT);
  nmi    =read_locked_port(NMI_STATUS_PORT);
  i      =read_locked_port(PMC_TIMERS_PORT);
  port_cs=read_locked_port(PORT_CHIP_SELECT_PORT);
  disk_cs=read_locked_port(TIMING_DISK_CHIP_SELECT_PORT);
  prog_cs=read_locked_port(PROGRAMMABLE_CHIP_SELECT_PORT);
  cpu_cl =read_locked_port(CPU_CLOCK_CONTROL_REGISTER);
  fl_op  =read_locked_port(FLOPPY_OPERATION_CHIP_SELECT);
  fl_cs1 =read_locked_port(FLOPPY_CHIP_SELECT_1);
  fl_cs2 =read_locked_port(FLOPPY_CHIP_SELECT_2);
  fl_qu  =read_locked_port(FLOPPY_DUNNOW);
  fl_ct  =read_locked_port(FLOPPY_CONTROL_CHIP_SELECT);
  l_timer=i & 0x00ff;
  b_timer=(i & 0xff00) >> 8;
#ifdef DEBUG
  fprintf(stderr,
   "Status: PMCout=%2x%2x PMCinp=%4x PMCint=%4x PMCnmi=%2x lcd=%2x bkl=%2x\n",
	  out_h,out_l,inp,intr,nmi,l_timer,b_timer);
  fprintf(stderr,"        CSport=%4x CSdisk=%4x CSprog=%4x CPUclk=%4x\n",
	  port_cs,disk_cs,prog_cs,cpu_cl);
  fprintf(stderr,"        FPopcs=%4x FPcs_1=%4x FPcs_2=%4x FPctcs=%4x\n",
	  fl_op,fl_cs1,fl_cs2,fl_qu,fl_ct);
#else
  fprintf(stderr,"%s status: ",name);
  if (l_timer>=MAX_TIMEOUT)
    fprintf(stderr,"LCD on, ");
  else
    fprintf(stderr,"LCD %d s, ",l_timer*S_PER_TIME_UNIT);
  if (b_timer>=MAX_TIMEOUT)
    fprintf(stderr,"backlighting on\n");
  else
    fprintf(stderr,"backlighting %d s\n",b_timer*S_PER_TIME_UNIT);
#endif
}

void set_backlight_timeout(t)
     int t;
{
  int old,new;

  if (t==INFINITE) {
    new=0xff;
  } else {
    new=t/S_PER_TIME_UNIT;
    if (new==0x00 && t!=0) new=0x01;
    if (new>0xfe) new=0xfe;
  }
  new=new << 8;
  old=read_locked_port(PMC_TIMERS_PORT) & 0x00ff;
#ifdef DEBUG
  fprintf(stderr,"bkl t=%d old=%x new=%x\n",t,old,new);
#endif
  write_locked_port((old | new),PMC_TIMERS_PORT);
}

void set_lcd_timeout(t)
     int t;
{
  int old,new;

  if (t==INFINITE) {
    new=0xff;
  } else {
    new=t/S_PER_TIME_UNIT;
    if (new==0x00 && t!=0) new=0x01;
    if (new>0xfe) new=0xfe;
  }
  old=read_locked_port(PMC_TIMERS_PORT) & 0xff00;
#ifdef DEBUG
  fprintf(stderr,"lcd t=%d old=%x new=%x\n",t,old,new);
#endif
  write_locked_port((old | new),PMC_TIMERS_PORT);
}

void usage_and_exit(char *name)
{
  fprintf(stderr,"Usage: %s -ABLv -b sec -l sec -R sec\n",name);
  fprintf(stderr,"   -A     AC operation, power management off\n");
  fprintf(stderr,"   -B     backlighting time-out off\n");
  fprintf(stderr,"   -L     LCD time-out off\n");
  fprintf(stderr,"   -R n   repeat command every n seconds\n");
  fprintf(stderr,"   -b n   set backlighting time-out to n seconds \n");
  fprintf(stderr,"   -l n   set LCD time-out to n seconds \n");
  fprintf(stderr,"   -v     report status\n");
}

main(int argc, char *argv[])
{
  int c;
  int v_flag,a_cap_flag,b_flag,l_flag,repeat_flag;
  int b_arg,l_arg,r_cap_arg;
  extern char *optarg;
  extern int optind;

  if (iopl(3)) {
    fprintf(stderr,"%s: iopl failed (must be root!)\n",argv[0]);
    exit(1);
  }

  installation_check();

  b_flag=FALSE; l_flag=FALSE; v_flag=FALSE;
  r_cap_arg=0;

  while ((c = getopt(argc, argv, "b:Bl:LAR:v")) != -1) {
    switch (c) {
    case 'b':
      b_flag = TRUE;
      b_arg=atoi(optarg);
      break;
    case 'B':
      b_flag = TRUE;
      b_arg=INFINITE;
      break;
    case 'l':
      l_flag = TRUE;
      l_arg=atoi(optarg);
      break;
    case 'L':
      l_flag = TRUE;
      l_arg=INFINITE;
      break;
    case 'A':
      b_flag = TRUE;
      b_arg=INFINITE;
      l_flag = TRUE;
      l_arg=INFINITE;
      break;
    case 'R':
      r_cap_arg=atoi(optarg);
      break;
    case 'v':
      v_flag = TRUE;
      break;
    case '?':
      usage_and_exit(argv[0]);
      break;
    }
  }

  if (b_flag) set_backlight_timeout(b_arg);
  if (l_flag) set_lcd_timeout(l_arg);
  status_report(argv[0]);
  if (r_cap_arg>0) {
    while (TRUE) {
      if (test_port_bit(5,PMC_INPUTS_PORT)) {
	fprintf(stderr,"Standby button pressed\n");
      }
      sleep(r_cap_arg);
      status_report(argv[0]);
    }
  }

  exit(0);
}
