/*
   ***************************************************************************
   *
   * Datei:
   *      RSysSummaryLists.c
   *
   * Inhalt:
   *
   *      --- Globale Routinen ---
   *
   *    void MakeHardwareList ( void );
   *    void MakeMemoryList ( void );
   *    void MakeSystemList ( void );
   *
   *      --- Lokale  Routinen ---
   *
   *    static RSYS_hardwareentry *allocentry ( RSYS_hardwareentry *prev , char *title , char *info );
   *    static RSYS_hardwareentry *allochardwareentry ( RSYS_hardwareentry *prev , char *title , char *info );
   *    static RSYS_hardwareentry *allocnumhardwareentry ( RSYS_hardwareentry *prev , char *title , unsigned long num , int hex );
   *    static void CheckProcessors ( char *cpu , char *fpu , char *mmu );
   *    static void extract_comp ( UWORD manufactnr , UWORD prodnr , char *name , char *company , int type );
   *
   * Bemerkungen:
   *      Listen für Hardwarekonfiguration, Speicherlisten und Systemliste.
   *
   * Erstellungsdatum:
   *      25-Jun-93     Rolf Böhme
   *
   * Änderungen:
   *      25-Jun-93     Rolf Böhme        Erstellung
   *
   ***************************************************************************
 */

#include "RSys.h"
#include "protos.h"


static RSYS_hardwareentry firsthardwareentry =

{
  "", "", NULL
};

static REMEMBER *Key = NULL;

 /*
  * allochardwareentry() erzeugt einen Eintrag für die
  * Hardwareliste
  */
static RSYS_hardwareentry *
allochardwareentry (RSYS_hardwareentry * prev, char *title, char *info)
{
  RSYS_hardwareentry *new;

  if (new = (RSYS_hardwareentry *) AllocRemember ((REMEMBER **) & Key,
						sizeof (RSYS_hardwareentry),
						  MEMF_CLEAR))
    {
      if (title)
	strncpy (new->title, title, TITLELEN);
      else
	strcpy (new->title, field[BLANK_FIELD]);

      if (info)
	strncpy (new->info, info, MAXSTRLEN);
      else
	new->info[0] = STRINGEND;

      prev->next = new;

      new->next = NULL;
    }
  else
    ErrorHandle (title, MEMORY_ERR, ALLOC_FAIL, KILL);

  return new;
}

 /*
  * allochardwareentry() erzeugt einen Eintrag für die
  * Hardwareliste
  */
static RSYS_hardwareentry *
allocentry (RSYS_hardwareentry * prev, char *title, char *info)
{
  RSYS_hardwareentry *new;

  if (new = (RSYS_hardwareentry *) AllocRemember ((REMEMBER **) & Key,
						sizeof (RSYS_hardwareentry),
						  MEMF_CLEAR))
    {
      strncpy (new->title, title, TITLELEN);

      if (info)
	strncpy (new->info, info, MAXSTRLEN);
      else
	strcpy (new->info, "-");

      prev->next = new;

      new->next = NULL;
    }
  else
    ErrorHandle (title, MEMORY_ERR, ALLOC_FAIL, KILL);

  return new;
}

 /*
  * allocnumhardwareentry() erzeugt einen Zahleneintrag für die
  * Hardwareliste
  */
static RSYS_hardwareentry *
allocnumhardwareentry (RSYS_hardwareentry * prev, char *title,
		       unsigned long num, int hex)
{
  RSYS_hardwareentry *new;

  if (new = (RSYS_hardwareentry *) AllocRemember ((REMEMBER **) & Key,
						sizeof (RSYS_hardwareentry),
						  MEMF_CLEAR))
    {
      strncpy (new->title, title, TITLELEN);

      if (hex)
	sprintf (new->info, "0x%08lX", num);
      else
	sprintf (new->info, "%ld", num);

      prev->next = new;

      new->next = NULL;
    }
  else
    ErrorHandle (title, MEMORY_ERR, ALLOC_FAIL, KILL);

  return new;
}


 /*
  * extract_comp() ermittelt einen Company-Namen und einen
  * Produktnamen aus dem Manufacturer-Eintrag in der
  * ExpansionBase
  */
static void
extract_comp (UWORD manufactnr, UWORD prodnr, char *name, char *company, int type)
{
  int i, j;

  strcpy (company, field[UNKNOWN_FIELD]);
  strcpy (name, field[UNKNOWN_FIELD]);
  type = -1;

  if (Flags.dummy1 == 0)
    return;

  for (i = 0; i < hardwarecnt; i++)
    if (manu[i].manu_nr == manufactnr)
      {
	strncpy (company, company_str[manu[i].company], BUFSIZE);

	j = i;
	while ((manu[j].prod_nr != prodnr) && (manu[j].manu_nr == manufactnr))
	  j++;

	if ((manu[j].prod_nr == prodnr) && (manu[j].manu_nr == manufactnr))
	  {
	    type = manu[j].type_nr;
	    strncpy (name, manu[j].name, BUFSIZE);
	  }

	break;
      }

  return;
}


 /*
  * CheckProcessors() prüft den Type der CPU, MMU und der FPU
  * mit ein paar kleinen Assemblerroutinen, die ich aus dem
  * Quelltext des Programmes SetCPU von D. Haynie geratzt habe
  */
static void
CheckProcessors (char *cpu, char *fpu, char *mmu)
{
  ULONG _cpu = GetCPUType ();
  ULONG _fpu = GetFPUType ();
  ULONG _mmu = GetMMUType ();

  sprintf (cpu, "CPU %ld", _cpu);

  if (_fpu != 0L)
    sprintf (fpu, "FPU %ld", _fpu);
  else
    strcpy (fpu, "None");

  if (_mmu != 0L)
    sprintf (mmu, "MMU %ld", _mmu);
  else
    strcpy (mmu, "None");

  return;
}

 /*
  * MakeHardwareList() erzeugt eine Anzeigeliste mit den
  * Daten der Hardware-Ausstattung des Rechners, auf dem RSys
  * läuft
  */
void
MakeHardwareList (void)
{
  RSYS_hardwareentry *loop;
  int count = 0, i;
/*
   GMD

   UWORD type = SysBase->AttnFlags;
 */
  char out[BUFSIZE], comp[BUFSIZE], name[BUFSIZE], *titles[] =
  {
  /* 0 */ "Processor",
  /* 1 */ "Coprocessor",
  /* 2 */ "Memory Unit",
  /* 3 */ "Denise",
  /* 4 */ "Agnus",
  /* 5 */ "Type",
  /* 6 */ "Company",
  /* 7 */ "Name",
  /* 8 */ "Init Action",
  /* 9 */ "Driver",
  /* 10 */ "Priority",
  /* 11 */ "Diagnosis",
  /* 12 */ "Manuf   #",
  /* 13 */ "Product #",
  /* 14 */ "Serial",
  /* 15 */ "Board addr",
  /* 16 */ "Board size",
  /* 17 */ "Slot  addr",
  /* 18 */ "Slot  size",
  /* 19 */ "           >",
  /* 20 */ "Alice",
  /* 21 */ "Lisa",
  /* 22 */ "MLisa",
  /* 23 */ "Chipset",
  /* 24 */ "Manuf type"
  };

  char cpu[3][10];
  CONFIGDEV *lastboard = NULL;
  EXPANSIONROM *expansionrom;

/* GMD */
  int manutype = -1;		/*GMD */

  NODE *devnode;

  DPOS;

  loop = allochardwareentry (&firsthardwareentry,
			  "------------------------------- Hardware", NULL);

  CheckProcessors (cpu[0], cpu[1], cpu[2]);

  for (i = 0; i < 3; i++)
    loop = allochardwareentry (loop, titles[i], cpu[i]);

  if (GfxBase->ChipRevBits0 & GFXF_HR_DENISE)
    loop = allochardwareentry (loop, titles[3], "ECS-Denise (8373)");
  else
    loop = allochardwareentry (loop, titles[3], "Normal Denise (8362)");

  if (GfxBase->ChipRevBits0 & GFXF_HR_AGNUS)
    loop = allochardwareentry (loop, titles[4], "ECS-Agnus (8372)");
  else
    loop = allochardwareentry (loop, titles[4], "Normal Agnus");

  count += 6;

  if (GfxBase->ChipRevBits0 & (GFXF_AA_ALICE | GFXF_AA_LISA | GFXF_AA_MLISA))
    {
      if (GfxBase->ChipRevBits0 & GFXF_AA_ALICE)
	loop = allochardwareentry (loop, titles[20], "AA-Alice");
      else
	loop = allochardwareentry (loop, titles[20], "Non AA-Alice");

      if (GfxBase->ChipRevBits0 & GFXF_AA_LISA)
	loop = allochardwareentry (loop, titles[21], "AA-Lisa");
      else
	loop = allochardwareentry (loop, titles[21], "Non AA-Lisa");

      if (GfxBase->ChipRevBits0 & GFXF_AA_MLISA)
	loop = allochardwareentry (loop, titles[22], "AA-MLisa");
      else
	loop = allochardwareentry (loop, titles[22], "Non AA-MLisa");

      count += 3;
    }
  else
    {
      loop = allochardwareentry (loop, titles[23], "No AA-Chipset");
      count++;
    }

  loop = allochardwareentry (loop, (char *) field[BLANK_FIELD], NULL);

  count += 2;

  if (ExpansionBase = (EXPANSIONBASE *) OpenLibrary ((UBYTE *) "expansion.library", NULL))
    {
      int cnt = 0;
      int j = 0;

      while (lastboard = FindConfigDev (lastboard, -1L, -1L))
	{
	  UBYTE buf[TITLELEN] =
	  "-------------------------------- Expansion Board ?";		/*GMD */

	  buf[49] = '0' + j++;
	  loop = allochardwareentry (loop, buf, NULL);
	  expansionrom = &(lastboard->cd_Rom);
	  if (expansionrom->er_Type & ERTF_MEMLIST)
	    loop = allochardwareentry (loop, titles[5], "RAM Expansion");
	  else
	    loop = allochardwareentry (loop, titles[5], "Other Expansion");

	  extract_comp (expansionrom->er_Manufacturer,
			expansionrom->er_Product, name, comp, manutype);
	  loop = allochardwareentry (loop, titles[6], comp);
	  loop = allochardwareentry (loop, titles[7], name);

	  count += 3;

	  if (lastboard->cd_Flags & CDF_SHUTUP)
	    {
	      loop = allochardwareentry (loop, titles[8], "No active");
	      count++;
	    }

	  if (lastboard->cd_Flags & CDF_CONFIGME)
	    {
	      loop = allochardwareentry (loop, titles[8], "Need Driver");
	      count++;
	    }

	  if (lastboard->cd_Flags & CDF_BADMEMORY)
	    {
	      loop = allochardwareentry (loop, titles[19], "Contains bad memory");
	      count++;
	    }

	  if (lastboard->cd_Flags & CDF_PROCESSED)
	    {
	      loop = allochardwareentry (loop, titles[19], "Private processed");
	      count++;
	    }

	  if (devnode = (NODE *) lastboard->cd_Driver)
	    {
	      loop = allochardwareentry (loop, titles[9], devnode->ln_Name);
	      loop = allocnumhardwareentry (loop, titles[10],
					    (unsigned long) devnode->ln_Pri,
					    FALSE);
	      count += 2;
	    }

	  if (expansionrom->er_Flags & ERTF_DIAGVALID)
	    loop = allochardwareentry (loop, titles[11], "Action attached");
	  else
	    loop = allochardwareentry (loop, titles[11], "No action attached");

	  loop = allocnumhardwareentry (loop, titles[12],
		      (unsigned long) expansionrom->er_Manufacturer, FALSE);
	  loop = allocnumhardwareentry (loop, titles[13],
			   (unsigned long) expansionrom->er_Product, FALSE);
	  loop = allocnumhardwareentry (loop, titles[14],
		       (unsigned long) expansionrom->er_SerialNumber, TRUE);
	  loop = allocnumhardwareentry (loop, titles[24],
					(unsigned long) manutype, FALSE);
	  loop = allocnumhardwareentry (loop, titles[15],
			     (unsigned long) lastboard->cd_BoardAddr, TRUE);
	  loop = allocnumhardwareentry (loop, titles[16],
			    (unsigned long) lastboard->cd_BoardSize, FALSE);
	  loop = allocnumhardwareentry (loop, titles[17],
			      (unsigned long) lastboard->cd_SlotAddr, TRUE);
	  loop = allocnumhardwareentry (loop, titles[18],
			     (unsigned long) lastboard->cd_SlotSize, FALSE);

	  loop = allochardwareentry (loop, (char *) field[BLANK_FIELD], NULL);

	  count += 10;

	  cnt++;
	}

      sprintf (out, "%ld expansions found", cnt);
      loop = allochardwareentry (loop, "Summary", out);
      count++;

      CloseLibrary ((LIBRARY *) ExpansionBase);
    }
  else
    ErrorHandle ("expansion.library", LIBRARY_ERR, OPEN_FAIL, NO_KILL);

  countentries = count;

  Entries = AllocScrollEntries (countentries);

  loop = firsthardwareentry.next;
  i = 0;

  while (loop && (i < countentries))
    {
      if (loop->info[0])
	sprintf (Entries[i].se_Entry, "%-13s : %s", loop->title, loop->info);
      else
	strncpy (Entries[i].se_Entry, loop->title, BUFSIZE);

      i++;

      loop = loop->next;
    }

  FreeRemember ((REMEMBER **) & Key, TRUE);

  CreateEntryList (NO_SORT, 0);

  PrintInfo ("Hardwarelist read", SPEAK, 0);

  return;
}

 /*
  * MakeMemoryList() erzeugt eine Liste der Speichereinträge mit
  * allen Fragmentierungen
  */
void
MakeMemoryList (void)
{
  int i = 3;
  MEMCHUNK *Loop;
  MEMHEADER *MemHeader;
  char cattype[MEMTYPELEN], type[5];
  ULONG BlockSize = 0L, MemSize;

  DPOS;

  countentries = CountMemory () + 3;

  if (NoEntries ())
    return;

  Entries = AllocScrollEntries (countentries);

  Forbid ();

  for (MemHeader = (MEMHEADER *) SysBase->MemList.lh_Head;
       MemHeader->mh_Node.ln_Succ && (i < countentries);
       MemHeader = (MEMHEADER *) MemHeader->mh_Node.ln_Succ)
    {
      MemSize = ((ULONG) MemHeader->mh_Upper - (ULONG) MemHeader->mh_Lower);
      BlockSize += MemSize;

      if (MemHeader->mh_Attributes & MEMF_CHIP)
	strcpy (type, "CHIP");
      else if (MemHeader->mh_Attributes & MEMF_FAST)
	strcpy (type, "FAST");
      else
	strcpy (type, field[NO_TYPE]);

      strncpy (cattype, type, MEMTYPELEN);

      Entries[i].se_obj_id.address = MemHeader;
      sprintf (Entries[i].se_Entry, EntryAttr[MEMORY].ea_dataformat,
	       (ULONG) MemHeader, MemSize, type);

      i++;

      for (Loop = MemHeader->mh_First; Loop && (i < countentries);
	   Loop = Loop->mc_Next)
	{
	  strncpy (cattype, type, MEMTYPELEN);
	  strcat (cattype, "-CHUNK");

	  Entries[i].se_obj_id.address = Loop;
	  sprintf (Entries[i].se_Entry, EntryAttr[MEMORY].ea_dataformat,
		   (ULONG) Loop, Loop->mc_Bytes, cattype);
	  i++;
	}
    }

  Permit ();
  {
    /*GMD */
    ULONG total = BlockSize / 1024;
    ULONG fast = AvailMem (MEMF_FAST) / 1024;
    ULONG chipx = AvailMem (MEMF_CHIP) / 1024;
    ULONG fast_l = AvailMem (MEMF_FAST | MEMF_LARGEST) / 1024;
    ULONG chip_l = AvailMem (MEMF_CHIP | MEMF_LARGEST) / 1024;


    sprintf (Entries[0].se_Entry, "Total:    %6ldK CHIP:%5ldK FAST:%5ldK",
	     total, chipx, fast);

    sprintf (Entries[1].se_Entry, "Largest: %8s CHIP:%5ldK FAST:%5ldK",
	     field[BLANK_FIELD], chip_l, fast_l);
  }
  strcpy (Entries[2].se_Entry, "-------------- Fragmentation --------------");

  CreateEntryList (NO_SORT, 0);

  return;
}

 /*
  * MakeSystemList() gibt eine Kurzinfo über das laufende System
  */
void
MakeSystemList (void)
{
  int count = 0;
  long timeptr;
  TM tm, *tmhelp = &tm;
  int tasks, processes;
  static UBYTE *xmonth[] =
  {
    "",
    "Jan",
    "Feb",
    "Mar",
    "Apr",
    "May",
    "Jun",
    "Jul",
    "Aug",
    "Sep",
    "Oct",
    "Nov",
    "Dec"
  };

  DPOS;

  countentries = 10;
  Entries = AllocScrollEntries (countentries);

  timeptr = time (NULL);
  tmhelp = localtime ((time_t *) & timeptr);

  sprintf (Entries[count++].se_Entry,
	   "%02ld-%s-%ld, day = %3ld, week = %2ld",
      tmhelp->tm_mday, xmonth[tmhelp->tm_mon + 1], (1900 + tmhelp->tm_year),
	   tmhelp->tm_yday + 1, (int) ((tmhelp->tm_yday + 1) / 7) + 1);

  /*
   * GMD
   */
  sprintf (Entries[count++].se_Entry, "  ");	/* blank line */

  tasks = CountNodesType (&SysBase->TaskWait, NT_TASK) +
    CountNodesType (&SysBase->TaskReady, NT_TASK);

  sprintf (Entries[count++].se_Entry, "Tasks       : %3ld", tasks);


  processes = CountNodesType (&SysBase->TaskWait, NT_PROCESS) +
    CountNodesType (&SysBase->TaskReady, NT_PROCESS) + 1;

  sprintf (Entries[count++].se_Entry, "Processes   : %3ld", processes);


  sprintf (Entries[count++].se_Entry, "Libraries   : %3ld",
	   CountNodes (&SysBase->LibList));

  /*
   * GMD
   */
  sprintf (Entries[count++].se_Entry, "Devices     : %3ld",
	   CountNodes (&SysBase->DeviceList));

  sprintf (Entries[count++].se_Entry, "Ports       : %3ld",
	   CountNodes (&SysBase->PortList));

  sprintf (Entries[count++].se_Entry, "Volumes     : %3ld",
	   CountDevices (LDF_VOLUMES));

  sprintf (Entries[count++].se_Entry, "Assigns     : %3ld",
	   CountDevices (LDF_ASSIGNS));

  sprintf (Entries[count++].se_Entry, "Fonts       : %3ld",
	   CountNodes (&GfxBase->TextFonts));

  sprintf (Entries[count++].se_Entry, "Resources   : %3ld",
	   CountNodes (&SysBase->ResourceList));

  sprintf (Entries[count++].se_Entry, "Windows     : %3ld",
	   CountIntuiObjects ((int) WINDOWS));

  sprintf (Entries[count++].se_Entry, "Screens     : %3ld",
	   CountIntuiObjects ((int) SCREENS));

  CreateEntryList (NO_SORT, 0);

/*
   GMD
   PrintInfo ("Systeminfo read", SPEAK, 0);
 */
  return;
}
