/*
***************************************************************************
*
* Datei:
*    RSysSummaryLists.c
*
* Inhalt:
*    void MakeHardwareList(void);
*    void MakeMemoryList(void);
*    void MakeSystemList(void);
*
* Bemerkungen:
*    Listen für Hardwarekonfiguration, Speicherlisten und Systemliste.
*
* Erstellungsdatum:
*    25-Jun-93    Rolf Böhme
*
* Änderungen:
*    25-Jun-93    Rolf Böhme    Erstellung
*
***************************************************************************
*/

#include "RSysDebug.h"
#include "RSysFunc.h"

#define MEMTYPELEN 15

static struct _hardwareentry
{
   char  title[TITLELEN];
   char  info[MAXSTRLEN];
   struct _hardwareentry *next;
}     firsthardwareentry =

{
   "", "", NULL
};

static struct Remember *Key = NULL;

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

   if (new = (struct _hardwareentry *) AllocRemember((struct Remember **) & Key,
                                                     sizeof(struct _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(MEMORY_ERR, ALLOC_FAIL, KILL);

   return (new);
}

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

   if (new = (struct _hardwareentry *) AllocRemember((struct Remember **) & Key,
                                                     sizeof(struct _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(MEMORY_ERR, ALLOC_FAIL, KILL);

   return (new);
}

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

   if (new = (struct _hardwareentry *)AllocRemember((struct Remember **) & Key,
                                                    sizeof(struct _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(MEMORY_ERR, ALLOC_FAIL, KILL);

   return (new);
}

static char *company_str[] =
{
   /* 0 */ "Stormbringer",
   /* 1 */ "C= Braunschweig",
   /* 2 */ "C= West Chester",
   /* 3 */ "Unknown",
   /* 4 */ "MicroBotics",
   /* 5 */ "ASDG",
   /* 6 */ "Ameristar",
   /* 7 */ "Supra",
   /* 8 */ "IVS TrumpCard",
   /* 9 */ "Kronos",
   /* 10 */ "Roßmöller",
   /* 11 */ "Golem (earlier Kupke)",
   /* 12 */ "Nexus Adv. Storage Systems",
   /* 13 */ "IVS TrumpCard",
   /* 14 */ "Hydra",
   /* 15 */ "DMI Resolver",
   /* 16 */ "Vortex",
   /* 17 */ "ReadySoft",
   /* 18 */ "MacroSystems",
   /* 19 */ "Combitec",
   /* 20 */ "ReisWare",
   /* 21 */ "Great Valley Products (GVP)",
   /* 22 */ "XPert Germany"
};

#define NONE (UWORD)(-1)

static struct Manufacturer
{
   UWORD manu_nr;
   UWORD prod_nr;
   UWORD type_nr;
   char name[BUFSIZE];
   int  company;
}     manu[]=
{
   /*  0 */ { 256, NONE, 0,      "MC68030 Board",             0 },
   /*  1 */ { 513, 1,   196,     "A2088",                     1 },
   /*  2 */ { 513, 1,   196,     "A2286",                     1 },
   /*  3 */ { 514, 81, NONE,     "A2630 MC68030 (2MB Stand.)",2 },
   /*  4 */ { 514, 10, 230,      "A2091/A590 or A2052/A2058", 2 },
   /*  5 */ { 514, 1, 209,       "2090A",                     2 },
   /*  6 */ { 514, 3, 209,       "A2091",                     2 },
   /*  7 */ { 514, 2, 209,       "A590",                      2 },
   /*  8 */ { 514, 10, 230,      "A2052",                     2 },
   /*  9 */ { 514, 70, NONE,     "A2232 Mult. Ser. Board",    2 },
   /* 10 */ { 514, 112, NONE,    "A2065 Ethernet Comm. Board",2 },
   /* 11 */ { 514, 146, NONE,    "Unknown",                   2 },
   /* 12 */ { 514, NONE, 103,    "A2386SX",                   2 },
   /* 13 */ { 1005, 1, 193,      "a^2 Live!",                 3 },
   /* 14 */ { 1010, 3, 230,      "MicroBotic 8up!",           4 },
   /* 15 */ { 1023, NONE, NONE,  "Unknown",                   5 },
   /* 16 */ { 1053, NONE, NONE,  "Unknown",                   6 },
   /* 17 */ { 1056, 12, 209,     "Wordsync",                  7 },
   /* 18 */ { 1056, 10, NONE,    "RAM 2000 Memory Board",     7 },
   /* 19 */ { 1056, 11, 193,     "2400zi (internal Modem)",   7 },
   /* 20 */ { 1056, NONE, 9,     "500RX",                     7 },
   /* 21 */ { 1761, 8, 230,      "GVP (2MB on board)",        21 },
   /* 22 */ { 2012, 48, NONE,    "Classic HD Controller",     8 },
   /* 23 */ { 2017, 9, 231,      "32 BIT Ram",                21 },
   /* 24 */ { 2017, 8, 209,      "A3001",                     21 },
   /* 25 */ { 2017, 3, 210,      "Impact Hard Card",          21 },
   /* 26 */ { 2017, 2, 209,      "Hard Card / 2 MB",          21 },
   /* 27 */ { 2017, 2, 210,      "Impact / 8MB",              21 },
   /* 28 */ { 2017, NONE, 13,    "A3001 REV.  7",             21 },
   /* 29 */ { 2050, 4, 209,      "Cltd.  Kronos SCSI",        9 },
   /* 30 */ { 2052, 1, 230,      "Roßmöller 2/8MB",           10 },
   /* 31 */ { 2071, 1, 209,      "ICD Advantage SCSI",        21 },
   /* 32 */ { 2071, NONE, 2,     "ICD AD IDE",                21 },
   /* 33 */ { 2073, 2, 193,      "Kupke SCSI-II SCSI",        11 },
   /* 34 */ { 2102, 1, NONE,     "SCSI Controller",           12 },
   /* 35 */ { 2112, 48, NONE,    "Classic HD Controller",     8 },
   /* 36 */ { 2121, 1, 193,      "Hydra Ethernet",            14 },
   /* 37 */ { 2129, 1, NONE,     "Graphics Board (T34010)",   15 },
   /* 38 */ { 2162,1,NONE,       "Domino Graphic Card",       22 },
   /* 39 */ { 8215, 3, 217,      "Athlet AT-Bus (IDE)",       16 },
   /* 40 */ { 8448, NONE, 1,     "A-MAX-IIPlus Card",         17 },
   /* 41 */ { 18260, 6, 1,       "Retina Graphics Card",      18 },
   /* 42 */ { 26230, 131, 230,   "MacroSystems MegaRAM",      18 },
   /* 43 */ { 26470, 130, 230,   "Combitec RAM",              19 },
   /* 44 */ { 43537, NONE, 17,   "ReisWare Scanner Interface",20 },
   /* 45 */ { NONE, NONE, NONE,  "Unknown",                   3  }
};

#define CNT_DEVELOPER (sizeof(manu)/sizeof(struct Manufacturer))

   /*
    * 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)
{
   register int i,j;

   strncpy(company,company_str[3],BUFSIZE);
   strncpy(name,company_str[3],BUFSIZE);

   for (i = 0; i < CNT_DEVELOPER - 1; 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))
            strncpy(name,manu[j].name,BUFSIZE);

         break;
      }

   return;
}

extern ULONG GetCPUType(void),GetFPUType(void),GetMMUType(void);

   /*
    * 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(),_fpu = GetFPUType(),_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)
{
   struct _hardwareentry *loop;
   int   count = 0,
         i;
   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.nr.",
      /* 13 */ "Prod.nr.",
      /* 14 */ "Serial",
      /* 15 */ "Boardaddr.",
      /* 16 */ "Boardsize",
      /* 17 */ "Slotaddr.",
      /* 18 */ "Slotsize",
      /* 19 */ "           >",
      /* 20 */ "Alice",
      /* 21 */ "Lisa",
      /* 22 */ "MLisa",
      /* 23 */ "Chipset"
   },cpu[3][10];
   struct ConfigDev *lastboard = NULL;
   struct ExpansionRom *expansionrom;
   struct Node *devnode /*, *node */;
/*   struct BootNode *bootnode; */

   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;

#define GFXF_AA_ALICE   4
#define GFXF_AA_LISA	   8
#define GFXF_AA_MLISA   16	/* internal use only */

   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);
   loop = allochardwareentry(loop, "----- Expansion", NULL);

   count += 2;

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

      while (lastboard = FindConfigDev(lastboard, -1L, -1L))
      {
         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);
         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 = (struct 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[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 += 9;

         cnt++;
      }

      sprintf(out,"%ld expansions found",cnt);
      loop = allochardwareentry(loop, "Summary", out);
      count++;
/* -------------------------------------------------------------------------
      loop = allochardwareentry(loop, (char *)field[BLANK_FIELD], NULL);
      count++;
      loop = allochardwareentry(loop, "----- Boot nodes", NULL);
      count++;

      Forbid();

      for(node = ExpansionBase->MountList.lh_Head; node->ln_Succ; node = node->ln_Succ)
      {
         bootnode = (struct BootNode *)node;

         loop = allocentry(loop, "Name", bootnode->bn_Node.ln_Name);

         loop = allocnumhardwareentry(loop, "Priority", (ULONG)bootnode->bn_Node.ln_Pri, FALSE);
         loop = allocnumhardwareentry(loop, "Flags", (ULONG)bootnode->bn_Flags,TRUE);
         loop = allocnumhardwareentry(loop, "Device node", (ULONG)bootnode->bn_DeviceNode,TRUE);
         loop = allochardwareentry(loop, (char *)field[BLANK_FIELD], NULL);

         count += 5;
      }

      Permit();

      cnt = CountNodes(&ExpansionBase->MountList);

      sprintf(out,"%ld Boot nodes found",cnt);
      loop = allochardwareentry(loop, "Summary", out);
      count++;
 -------------------------------------------------------------------------*/

      CloseLibrary((struct Library *) ExpansionBase);
   }
   else
      ErrorHandle(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((struct Remember **) & Key, TRUE);

   CreateEntryList(NO_SORT);

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

   return;
}

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

   DPOS;

   countentries = CountMemory() + 3;

   if (NoEntries())
      return;

   Entries = AllocScrollEntries(countentries);

   Forbid();

   for (MemHeader = (struct MemHeader *) SysBase->MemList.lh_Head;
        MemHeader->mh_Node.ln_Succ && (i < countentries);
        MemHeader = (struct 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);

      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");

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

   Permit();

   sprintf(Entries[0].se_Entry, "Total  : %8ld C:%8ld F:%8ld",
           BlockSize, AvailMem(MEMF_CHIP), AvailMem(MEMF_FAST));

   sprintf(Entries[1].se_Entry, "Largest: %8s C:%8ld F:%8ld",
           field[BLANK_FIELD], AvailMem(MEMF_CHIP | MEMF_LARGEST),
           AvailMem(MEMF_FAST | MEMF_LARGEST));

   strcpy(Entries[2].se_Entry,"-------------- Fragmentation --------------");

   CreateEntryList(NO_SORT);

   return;
}

   /*
    * MakeSystemList() gibt eine Kurzinfo über das laufende System
    */
void
MakeSystemList(void)
{
   int   count = 0;
   long timeptr;
   struct tm tm,
        *tmhelp = &tm;

   DPOS;

   countentries = 10;
   Entries = AllocScrollEntries(countentries);

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

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

   sprintf(Entries[count++].se_Entry, "Tasks       : %ld",
           CountNodes(&SysBase->TaskWait) + CountNodes(&SysBase->TaskReady) + 1);

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

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

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

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

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

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

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

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

   CreateEntryList(NO_SORT);

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

   return;
}
