summaryrefslogtreecommitdiff
path: root/os/boot/mpc/rmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/boot/mpc/rmap.c')
-rw-r--r--os/boot/mpc/rmap.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/os/boot/mpc/rmap.c b/os/boot/mpc/rmap.c
new file mode 100644
index 00000000..8b8a0bef
--- /dev/null
+++ b/os/boot/mpc/rmap.c
@@ -0,0 +1,104 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+void
+mapinit(RMap *rmap, Map *map, int size)
+{
+ lock(rmap);
+ rmap->map = map;
+ rmap->mapend = map+(size/sizeof(Map));
+ unlock(rmap);
+}
+
+void
+mapfree(RMap* rmap, ulong addr, int size)
+{
+ Map *mp;
+ ulong t;
+
+ if(size <= 0)
+ return;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
+ ;
+
+ if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
+ (mp-1)->size += size;
+ if(addr+size == mp->addr){
+ (mp-1)->size += mp->size;
+ while(mp->size){
+ mp++;
+ (mp-1)->addr = mp->addr;
+ (mp-1)->size = mp->size;
+ }
+ }
+ }
+ else{
+ if(addr+size == mp->addr && mp->size){
+ mp->addr -= size;
+ mp->size += size;
+ }
+ else do{
+ if(mp >= rmap->mapend){
+ print("mapfree: %s: losing 0x%uX, %d\n",
+ rmap->name, addr, size);
+ break;
+ }
+ t = mp->addr;
+ mp->addr = addr;
+ addr = t;
+ t = mp->size;
+ mp->size = size;
+ mp++;
+ }while(size = t);
+ }
+ unlock(rmap);
+}
+
+ulong
+mapalloc(RMap* rmap, ulong addr, int size, int align)
+{
+ Map *mp;
+ ulong maddr, oaddr;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->size; mp++){
+ maddr = mp->addr;
+
+ if(addr){
+ if(maddr > addr)
+ continue;
+ if(addr+size > maddr+mp->size)
+ break;
+ maddr = addr;
+ }
+
+ if(align > 0)
+ maddr = ((maddr+align-1)/align)*align;
+ if(mp->addr+mp->size-maddr < size)
+ continue;
+
+ oaddr = mp->addr;
+ mp->addr = maddr+size;
+ mp->size -= maddr-oaddr+size;
+ if(mp->size == 0){
+ do{
+ mp++;
+ (mp-1)->addr = mp->addr;
+ }while((mp-1)->size = mp->size);
+ }
+
+ unlock(rmap);
+ if(oaddr != maddr)
+ mapfree(rmap, oaddr, maddr-oaddr);
+
+ return maddr;
+ }
+ unlock(rmap);
+
+ return 0;
+}