xref: /inferno-os/os/mpc/rmap.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1*74a4d8c2SCharles.Forsyth #include "u.h"
2*74a4d8c2SCharles.Forsyth #include "lib.h"
3*74a4d8c2SCharles.Forsyth #include "mem.h"
4*74a4d8c2SCharles.Forsyth #include "dat.h"
5*74a4d8c2SCharles.Forsyth #include "fns.h"
6*74a4d8c2SCharles.Forsyth 
7*74a4d8c2SCharles.Forsyth void
mapinit(RMap * rmap,Map * map,int size)8*74a4d8c2SCharles.Forsyth mapinit(RMap *rmap, Map *map, int size)
9*74a4d8c2SCharles.Forsyth {
10*74a4d8c2SCharles.Forsyth 	lock(rmap);
11*74a4d8c2SCharles.Forsyth 	rmap->map = map;
12*74a4d8c2SCharles.Forsyth 	rmap->mapend = map+(size/sizeof(Map));
13*74a4d8c2SCharles.Forsyth 	unlock(rmap);
14*74a4d8c2SCharles.Forsyth }
15*74a4d8c2SCharles.Forsyth 
16*74a4d8c2SCharles.Forsyth void
mapfree(RMap * rmap,ulong addr,int size)17*74a4d8c2SCharles.Forsyth mapfree(RMap* rmap, ulong addr, int size)
18*74a4d8c2SCharles.Forsyth {
19*74a4d8c2SCharles.Forsyth 	Map *mp;
20*74a4d8c2SCharles.Forsyth 	ulong t;
21*74a4d8c2SCharles.Forsyth 
22*74a4d8c2SCharles.Forsyth 	if(size <= 0)
23*74a4d8c2SCharles.Forsyth 		return;
24*74a4d8c2SCharles.Forsyth 
25*74a4d8c2SCharles.Forsyth 	lock(rmap);
26*74a4d8c2SCharles.Forsyth 	for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
27*74a4d8c2SCharles.Forsyth 		;
28*74a4d8c2SCharles.Forsyth 
29*74a4d8c2SCharles.Forsyth 	if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
30*74a4d8c2SCharles.Forsyth 		(mp-1)->size += size;
31*74a4d8c2SCharles.Forsyth 		if(addr+size == mp->addr){
32*74a4d8c2SCharles.Forsyth 			(mp-1)->size += mp->size;
33*74a4d8c2SCharles.Forsyth 			while(mp->size){
34*74a4d8c2SCharles.Forsyth 				mp++;
35*74a4d8c2SCharles.Forsyth 				(mp-1)->addr = mp->addr;
36*74a4d8c2SCharles.Forsyth 				(mp-1)->size = mp->size;
37*74a4d8c2SCharles.Forsyth 			}
38*74a4d8c2SCharles.Forsyth 		}
39*74a4d8c2SCharles.Forsyth 	}
40*74a4d8c2SCharles.Forsyth 	else{
41*74a4d8c2SCharles.Forsyth 		if(addr+size == mp->addr && mp->size){
42*74a4d8c2SCharles.Forsyth 			mp->addr -= size;
43*74a4d8c2SCharles.Forsyth 			mp->size += size;
44*74a4d8c2SCharles.Forsyth 		}
45*74a4d8c2SCharles.Forsyth 		else do{
46*74a4d8c2SCharles.Forsyth 			if(mp >= rmap->mapend){
47*74a4d8c2SCharles.Forsyth 				print("mapfree: %s: losing 0x%luX, %d\n",
48*74a4d8c2SCharles.Forsyth 					rmap->name, addr, size);
49*74a4d8c2SCharles.Forsyth 				break;
50*74a4d8c2SCharles.Forsyth 			}
51*74a4d8c2SCharles.Forsyth 			t = mp->addr;
52*74a4d8c2SCharles.Forsyth 			mp->addr = addr;
53*74a4d8c2SCharles.Forsyth 			addr = t;
54*74a4d8c2SCharles.Forsyth 			t = mp->size;
55*74a4d8c2SCharles.Forsyth 			mp->size = size;
56*74a4d8c2SCharles.Forsyth 			mp++;
57*74a4d8c2SCharles.Forsyth 		}while(size = t);
58*74a4d8c2SCharles.Forsyth 	}
59*74a4d8c2SCharles.Forsyth 	unlock(rmap);
60*74a4d8c2SCharles.Forsyth }
61*74a4d8c2SCharles.Forsyth 
62*74a4d8c2SCharles.Forsyth ulong
rmapalloc(RMap * rmap,ulong addr,int size,int align)63*74a4d8c2SCharles.Forsyth rmapalloc(RMap* rmap, ulong addr, int size, int align)
64*74a4d8c2SCharles.Forsyth {
65*74a4d8c2SCharles.Forsyth 	Map *mp;
66*74a4d8c2SCharles.Forsyth 	ulong maddr, oaddr;
67*74a4d8c2SCharles.Forsyth 
68*74a4d8c2SCharles.Forsyth 	lock(rmap);
69*74a4d8c2SCharles.Forsyth 	for(mp = rmap->map; mp->size; mp++){
70*74a4d8c2SCharles.Forsyth 		maddr = mp->addr;
71*74a4d8c2SCharles.Forsyth 
72*74a4d8c2SCharles.Forsyth 		if(addr){
73*74a4d8c2SCharles.Forsyth 			if(maddr > addr)
74*74a4d8c2SCharles.Forsyth 				break;
75*74a4d8c2SCharles.Forsyth 			if(maddr+mp->size < addr)
76*74a4d8c2SCharles.Forsyth 				continue;
77*74a4d8c2SCharles.Forsyth 			if(addr+size > maddr+mp->size)
78*74a4d8c2SCharles.Forsyth 				break;
79*74a4d8c2SCharles.Forsyth 			maddr = addr;
80*74a4d8c2SCharles.Forsyth 		}
81*74a4d8c2SCharles.Forsyth 
82*74a4d8c2SCharles.Forsyth 		if(align > 0)
83*74a4d8c2SCharles.Forsyth 			maddr = ((maddr+align-1)/align)*align;
84*74a4d8c2SCharles.Forsyth 		if(mp->addr+mp->size-maddr < size)
85*74a4d8c2SCharles.Forsyth 			continue;
86*74a4d8c2SCharles.Forsyth 
87*74a4d8c2SCharles.Forsyth 		oaddr = mp->addr;
88*74a4d8c2SCharles.Forsyth 		mp->addr = maddr+size;
89*74a4d8c2SCharles.Forsyth 		mp->size -= maddr-oaddr+size;
90*74a4d8c2SCharles.Forsyth 		if(mp->size == 0){
91*74a4d8c2SCharles.Forsyth 			do{
92*74a4d8c2SCharles.Forsyth 				mp++;
93*74a4d8c2SCharles.Forsyth 				(mp-1)->addr = mp->addr;
94*74a4d8c2SCharles.Forsyth 			}while((mp-1)->size = mp->size);
95*74a4d8c2SCharles.Forsyth 		}
96*74a4d8c2SCharles.Forsyth 
97*74a4d8c2SCharles.Forsyth 		unlock(rmap);
98*74a4d8c2SCharles.Forsyth 		if(oaddr != maddr)
99*74a4d8c2SCharles.Forsyth 			mapfree(rmap, oaddr, maddr-oaddr);
100*74a4d8c2SCharles.Forsyth 
101*74a4d8c2SCharles.Forsyth 		return maddr;
102*74a4d8c2SCharles.Forsyth 	}
103*74a4d8c2SCharles.Forsyth 	unlock(rmap);
104*74a4d8c2SCharles.Forsyth 
105*74a4d8c2SCharles.Forsyth 	return 0;
106*74a4d8c2SCharles.Forsyth }
107