/*
 * vmode.c (utilities for the Veridata EL-486S/25e notebook)
 * Time-stamp: <29 Mar 94 (23:23) by pive@ruca.ua.ac.be>
 */

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

#include "veridata.h"

void inline outb_p(char value, unsigned short port)
{
__asm__ __volatile__ ("outb %%al,%%dx"
                ::"a" ((char) value),"d" ((unsigned short) port));
        SLOW_DOWN_IO;
}

unsigned int inline inb_p(unsigned short port)
{
        unsigned int _v;
__asm__ __volatile__ ("inb %%dx,%%al"
                :"=a" (_v):"d" ((unsigned short) port),"0" (0));
        SLOW_DOWN_IO;
        return _v;
}

void usage(char *name)
{
  fprintf(stderr,"Usage: %s -tbsi[+]\n",name);
  fprintf(stderr,"\t-t turbo on\n");
  fprintf(stderr,"\t-b backlight on\n");
  fprintf(stderr,"\t-s serial 0 on\n");
  fprintf(stderr,"\t-i inverse video on\n");
  fprintf(stderr,"an option followed with + to disables it\n");
}

void print_status()
{
  unsigned int status;

  status=inb_p(VERIDATA_PORT);
  printf("Veridata ExecuLite-486s/25e settings:\n");
  printf("\tturbo mode:\t%s\n",
	 (status&CPU_FAST)?"on":"off");
  printf("\tbacklight:\t%s\n",
	 (status&BACKLIGHT_ON)?"on":"off");
  printf("\tserial 0:\t%s\n",
	 (status&COM1_ENABLE)?"enabled":"disabled");
  printf("\tvideo mode:\t%s\n",
	 (status&INVERSE_ON)?"inverse":"normal");
/* it works, but is not usefull
  printf("\tblank mode:\t%s\n",
	 (status&BLANK_OFF)?"normal":"blank");
*/
  printf("\tpower mode:\t%s\n",
	 (status&POWER_EXT)?"extern":"intern");
  printf("\tpower level:\t");
  switch (status & POWER_MASK) {
  case POWER_OK:
    printf("ok\n");
    break;
  case POWER_LVL1:
    printf("level 1\n");
    break;
  case POWER_LVL2:
    printf("level 2\n");
    break;
  }
}

main(int argc, char *argv[])
{
  unsigned int status,i;

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

  /* I should check the computer */

  /* initialise the status variable, clear bit 6 and 7 */
  status=inb_p(VERIDATA_PORT) & SAFETY_MASK;

  /* probably some better parsing routines would be nice, but the heck... */
  for (i=1; i<argc; i++) {
    while (*argv[i]) {
      switch (*argv[i]) {
      case '-': /* ignore the minus sign */
	break;
      case 't': 
	if (argv[i][1]=='+') {
	  status &= ~CPU_FAST;
	  *argv[i] ++;
	} else
	  status |= CPU_FAST;
	break;
      case 'b':
	if (argv[i][1]=='+') {
	  status &= ~BACKLIGHT_ON;
	  *argv[i] ++;
	} else
	  status |= BACKLIGHT_ON;
	break;
      case 's':
	if (argv[i][1]=='+') {
	  status &= ~COM1_ENABLE;
	  *argv[i] ++;
	} else
	  status |= COM1_ENABLE;
	break;
      case 'i':
	if (argv[i][1]=='+') {
	  status &= ~INVERSE_ON;
	  *argv[i] ++;
	} else
	  status |= INVERSE_ON;
	break;
      default:
	usage(argv[0]);
	exit(0);
      }
      *argv[i] ++;
    }
  }
  outb_p(status,VERIDATA_PORT);
  print_status();
}
