
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <conio.h>
#include <dos.h>
#include <string.h>

#ifdef M_I86  /* for uSoft */
 #define enable         _enable
 #define disable        _disable
 #define inportb(a)     inp(a)
 #define outportb(a,b)  outp(a,b)
#endif

typedef unsigned char byte;
typedef unsigned int  uint;

int  main(void);
byte read_cmos(int);
void dump_cmos(void);
void dump_setup(void);
char *floppy_type(int);


int main()
{
  printf("  --- Contents of CMOS RAM ---\n\n");
  dump_cmos();
  dump_setup();
  return(0);
}


/*
 * This routine assumes that the machine/compiler combination is
 * fast enough to test for the absence of the UIP bit, then perform
 * an outportb and another inportb in less than 244 usecs.  If the
 * accuracy of reading the clock bytes is critical, the BIOS functions
 * should be used, or assembly code.  Otherwise, inline code for the
 * input and output instructions may be used.
 */
byte read_cmos(int locn)
{
  register byte ret_val;

  if (locn < 10)
  {
    for (;;)
    {
      outportb(0x70, 10);
      disable();

      if ((inportb(0x71) & 0x80) == 0)
      {
        outportb(0x70, locn);
        ret_val = (byte)inportb(0x71);
        enable();
        return(ret_val);
      }
      enable();
    }
  }
  outportb(0x70, locn);
  return((byte)inportb(0x71));
}


/*
 * dump_cmos()
 */
void dump_cmos()
{
  int i, j, val;

  printf("     ");

  for (i = 0; i < 16; i++)
    printf(" %02x", i);

  printf("\n     ");

  for (i = 0; i < 16; i++)
    printf(" --", i);
  printf("\n");

  for (i = 0; i < 4; i++)
  {
    printf("%04x:", i*16);

    for (j = i * 16; j < ((i+1)*16); j++)
      printf(" %02x", read_cmos(j));

    printf(" ");

    for (j = i * 16; j < ((i+1)*16); j++)
    {
      val = read_cmos(j);

      if (isprint(val))
        putchar(val);
      else
        putchar('.');
    }
    printf("\n");
  }
  printf("\n");
}


/*
 * read_time()
 */
void read_time(byte dest[3])
{
  byte current_seconds;
  int i;

  do
  {
    for (i = 0; i < 3; i++)
      dest[i] = read_cmos(i * 2);

    current_seconds = read_cmos(0);

  } while (current_seconds != dest[0]);
}


/*
 * floppy_type()
 */
char *floppy_type(int drive_number)
{
  uint drive;

  static char *drives[] = { "None", "360K", "1.2M", "720K", "1.44M" };

  if (drive_number == 1)
    drive = read_cmos(16) >> 4;
  else
    drive = read_cmos(16) & 15;

  if (drive < 5)
    return(drives[drive]);
  else
    return("?");
}


/*
 * hard_type()
 */
char *hard_type(int drive_number)
{
  uint drive;
  static char buffer[8];

  if (drive_number == 1)
  {
    drive = read_cmos(18) >> 4;

    if (drive == 15)
      drive = read_cmos(25);
  }
  else
  {
    drive = read_cmos(18) & 15;

    if (drive == 15)
      drive = read_cmos(26);
  }
  if (drive != 0)
    itoa(drive, buffer, 10);
  else
    strcpy(buffer, "None");

  return(buffer);
}


/*
 * floppy_count()
 */
int floppy_count(void)
{
  return((read_cmos(20) >> 6) + 1);
}



/*
 * display_type()
 */
char *display_type(void)
{
  static char *displays[] = { "VGA/EGA",
                              "Color 40 column",
                              "Color 80 column",
                              "Monochrome" };

  return(displays[(read_cmos(20) >> 4) & 3]);
}


char *months[] = { "", "January", "February", "March", "April",
                   "May", "June", "July", "August", "September",
                   "", "", "", "", "", "",
                   "October", "November", "December" };


/*
 * dump_setup()
 */
void dump_setup()
{
  byte time[3];
  int memory,
      checksum;

  read_time(time);

  printf("Current Time      :  %02x:%02x:%02x    ",
         time[2], time[1], time[0]);

  printf("Current Date    :  %s %02x, %x%02x\n",
         months[read_cmos(8)], read_cmos(7),
         read_cmos(50), read_cmos(9));

  printf("Alarm Time        :  %x:%02x:%02x\n",
         read_cmos(5), read_cmos(3), read_cmos(1));

  printf("Floppy drive 1    :  %-12s", floppy_type(1));

  printf("Floppy drive 2  :  %s\n", floppy_type(2));

  printf("Fixed disk 1      :  %-12s", hard_type(1));

  printf("Fixed disk 2    :  %s\n", hard_type(2));

  printf("No. of floppies   :  %d\n", floppy_count());

  printf("Primary display   :  %s\n", display_type());

  printf("Math Coprocessor  :  %s\n",
         (read_cmos(20) & 2) ? "Yes" : "No");

  printf("Diskettes         :  %s\n",
         (read_cmos(20) & 1) ? "Installed" : "No");

  memory = read_cmos(21) + (read_cmos(22) << 8);
  printf("Standard RAM      :  %dK\n", memory);

  memory = read_cmos(23) + (read_cmos(24) << 8);
  printf("Extended RAM      :  %dK\n", memory);

  memory = read_cmos(48) + (read_cmos(49) << 8);
  printf("Extended RAM      :  %dK\n", memory);

  checksum = read_cmos(47) + (read_cmos(46) << 8);
  printf("Checksum          :  %04x\n", checksum);
}
