/* MergeMem.c - by  Carolyn Scheppner  CBM  02/87
 *  Attempts to merge the memlists of sequentially configged ram boards
 *  which have the same Attributes (for contiguous expansion ram)
 *
 *  Note:  This program has been tested with an Alegra plugged into
 *         a Microbotics Starboard's pass-thru.  The program makes
 *         the assumption that sequentially configged ram boards
 *         have sequential entries in the MemHeader list.  If this
 *         is not always true, then this program may not work for
 *         some expansion configurations.  Works fine for me though.
 */

#include "exec/types.h"
#include "exec/exec.h" 
#include "exec/execbase.h" 

extern struct ExecBase *SysBase;

main()
   {
   struct MemChunk *chunk;
   struct MemHeader *mem, *firstmem, *prevmem = 0;
   struct ExecBase *eb = SysBase;
   ULONG  memsize;

   /* Temps */
   struct MemChunk *oldFirst;
   APTR   oldLower, oldUpper;
   ULONG  oldFree;

   Forbid();
   firstmem = (struct MemHeader *)eb->MemList.lh_Head;

   /* Go to end of MemHeader list */
   for (mem = firstmem;
           mem->mh_Node.ln_Succ;
              mem = (struct MemHeader *)mem->mh_Node.ln_Succ)
      printf("Found memory type $%lx at $%lx\n",mem->mh_Attributes,mem);

   /* Back up from terminal node to point at last MemHeader */
   mem = (struct MemHeader *)mem->mh_Node.ln_Pred;

   /* Backwards, for each except first */
   for ( ; (ULONG)mem != (ULONG)firstmem; mem = prevmem)
      {
      prevmem = (struct MemHeader *)mem->mh_Node.ln_Pred;

      /* If prev MemHeader describes neighboring ram of same Attributes */
      if(((ULONG)prevmem->mh_Upper == (ULONG)mem->mh_Lower - 32L)&&
           (prevmem->mh_Attributes == mem->mh_Attributes))
         {
         printf("Merging $%lx with $%lx\n",prevmem,mem);
         /* Save needed stuff from MemHeader before Remove()ing it */
         oldFirst = mem->mh_First;
         oldLower = mem->mh_Lower;
         oldUpper = mem->mh_Upper;
         oldFree  = mem->mh_Free;
         Remove(mem);

         /* Adjust Upper and Free in prev MemHeader to include this mem */
         memsize = (ULONG)oldUpper - (ULONG)oldLower +32L;
         prevmem->mh_Upper = (APTR)((ULONG)prevmem->mh_Upper + memsize);
         prevmem->mh_Free += oldFree;

         /* Link last free chunk of prevmem to first free of mem */
         for (chunk = prevmem->mh_First;
                  chunk->mc_Next; chunk = chunk->mc_Next);
         chunk->mc_Next = oldFirst;

         /* Now FreeMem() the old MemHeader as a 32 byte chunk */
         FreeMem(mem,32);
         }
      }
   Permit();
   }


