/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1987, 1991 by Mike Parker.			    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

#include <vax/mtpr.h>
#include <vax/pte.h>

struct map {
  int size;
  char *bitmap;
  int firstfree; };

struct map phys;
struct map virt;

int physbase;
char *virtbase;

initmem()
{
 extern int memsize;
 extern int freephys;
 extern int freevirt;
 int mem;
 int bmrup;
 int mapphys;

 virt.size = mfpr(SLR) - ((freevirt & ~0x80000000) >> 9);
 bmrup = (virt.size + 511) & ~511;
 mapphys = getphys(virt.size);
 virt.bitmap = (char *) (0x80000000 | mapphys);
 bzero(virt.bitmap,virt.size);
 virtbase = (char *) freevirt;
 virt.firstfree = 0;
 mem = memsize - freephys;
 phys.size = (mem - (mem / 513)) / 512;
 bmrup = (phys.size + 511) & ~511;
 if (bmrup+(phys.size*512) != mem)
  { panic("initmem botch");
  }
 mapphys = getphys(phys.size);
 phys.bitmap = (char *) (0x80000000 | mapphys);
 bzero(phys.bitmap,phys.size);
 phys.firstfree = 0;
 physbase = freephys;
 printf("\tphys\t\tvirt\n");
 printf("pages\t%d\t\t%d\n",phys.size,virt.size);
 printf("base\t%08x\t%08x\n",physbase,(int)virtbase);
 if (virt.size < phys.size)
  { printf("WARNING: more physical than virtual, increase SYS_XVA\n");
  }
}

clearmem()
{
 clearmap(&virt);
 clearmap(&phys);
}

clearmap(map)
register struct map *map;
{
 bzero(map->bitmap,map->size);
 map->firstfree = 0;
}

allocin(map,n)
register struct map *map;
int n;
{
 int s;
 int i;
 int found;

 if (n <= 0)
  { return(0);
  }
 s = splhigh();
 found = 0;
 for (i=map->firstfree;i<map->size;i++)
  { if (map->bitmap[i])
     { found = 0;
     }
    else
     { found ++;
       if (found >= n)
	{ i -= n - 1;
	  bfill(&map->bitmap[i],n,1);
	  if (i == map->firstfree)
	   { register int j;
	     for (j=i+n;(j<map->size)&&map->bitmap[j];j++) ;
	     map->firstfree = j;
	   }
	  splx(s);
	  return(i);
	}
     }
  }
 splx(s);
 return(-1);
}

allocat(map,n,at)
register struct map *map;
int n;
int at;
{
 int s;
 int i;

 if (n <= 0)
  { return(1);
  }
 if ((at < 0) || (at >= map->size) || (at+n >= map->size))
  { return(0);
  }
 s = splhigh();
 for (i=0;i<n;i++)
  { if (map->bitmap[at+i])
     { splx(s);
       return(0);
     }
  }
 bfill(&map->bitmap[at],n,1);
 if (at == map->firstfree)
  { register int j;
    for (j=at+n;(j<map->size)&&map->bitmap[j];j++) ;
    map->firstfree = j;
  }
 splx(s);
 return(1);
}

freein(map,at,n)
register struct map *map;
int at;
int n;
{
 int i;
 int s;

 if (n <= 0)
  { return;
  }
 s = splhigh();
 if (at < map->firstfree)
  { map->firstfree = at;
  }
 bzero(&map->bitmap[at],n);
 splx(s);
}

int palloc(nbytes)
int nbytes;
{
 int i;

 i = allocin(&phys,(nbytes+511)>>9);
 return((i<0)?0:physbase+(i<<9));
}

int pget(nbytes,p)
int nbytes;
int p;
{
 return(allocat(&phys,(nbytes+511)>>9,(p-physbase)>>9));
}

pfree(p,nbytes)
int p;
int nbytes;
{
 freein(&phys,(p-physbase)>>9,(nbytes+511)>>9);
}

char *valloc(nbytes)
int nbytes;
{
 int i;

 i = allocin(&virt,(nbytes+511)>>9);
 return((i<0)?0:virtbase+(i<<9));
}

int vget(nbytes,v)
int nbytes;
char *v;
{
 return(allocat(&virt,(nbytes+511)>>9,(v-virtbase)>>9));
}

vfree(v,nbytes)
char *v;
int nbytes;
{
 freein(&virt,(v-virtbase)>>9,(nbytes+511)>>9);
}

char *alloc(nbytes)
{
 char *v;
 int p;

 v = valloc(nbytes);
 if (v == 0)
  { return(0);
  }
 p = palloc(nbytes);
 if (p == 0)
  { vfree(v,nbytes);
    return(0);
  }
 setkmap(v,p,(nbytes+511)>>9);
 return(v);
}

free(v,nbytes)
char *v;
int nbytes;
{
 int *kptep;
 int npg;
 int vpn;

 kptep = (int *) (0x80000000 | mfpr(SBR));
 npg = (nbytes + 511) >> 9;
 vpn = (((int)v) & ~0x80000000) >> 9;
 for (;npg>0;npg--)
  { pfree((kptep[vpn]&PG_PFNUM)<<9,512);
    vfree(v,512);
    v += 512;
    vpn ++;
  }
}

int phys_mem_left()
{
 int s;
 int t;
 int i;

 s = splhigh();
 t = 0;
 for (i=phys.firstfree;i<phys.size;i++)
  { if (! phys.bitmap[i]) t ++;
  }
 splx(s);
 return(t<<9);
}
