/*
***************************************************************************
*
* Datei:
*	  RSysSummaryLists.c
*
* Inhalt:
*
*      --- Globale Routinen ---
*
*    void MakeHardwareList ( void );
*    void MakeMemoryList ( void );
*    void MakeSystemList ( void );
*
*      --- Lokale  Routinen ---
*
*    static struct _hardwareentry *allocentry ( struct _hardwareentry *prev , char *title , char *info );
*    static struct _hardwareentry *allochardwareentry ( struct _hardwareentry *prev , char *title , char *info );
*    static struct _hardwareentry *allocnumhardwareentry ( struct _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"

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(title, 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(title, 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(title, MEMORY_ERR, ALLOC_FAIL, KILL);

	return new;
}

extern char **company_str;
extern struct Manufacturer *manu;

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

 	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;
}

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",
      /* 24 */ "Manuf. type"
	},cpu[3][10];
	struct ConfigDev *lastboard = NULL;
	struct ExpansionRom *expansionrom;
   int manutype;
	struct 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);
	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, 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 = (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[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((struct 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((struct 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)
{
	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);

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

	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, 0);

	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, 0);

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

	return;
}
