2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
6 #include <exec/memory.h>
7 #include <proto/exec.h>
9 #include <aros/debug.h>
11 #include "intelG45_intern.h"
12 #include "intelG45_regs.h"
14 static void G45_AttachMemory(struct g45staticdata
*sd
, intptr_t physical
,
15 intptr_t virtual, intptr_t length
);
16 static void G45_DetachMemory(struct g45staticdata
*sd
, intptr_t virtual,
18 static APTR
AllocAlignedMem(IPTR size
, UWORD alignment
);
19 static VOID
FreeAlignedMem(APTR mem
);
21 APTR
AllocGfxMem(struct g45staticdata
*sd
, ULONG size
)
24 struct MemHeader
*header
, *next_header
, *gap_header
= NULL
, *tail
;
26 header
= (APTR
)sd
->CardMem
.mlh_Head
;
27 tail
= (APTR
)&sd
->CardMem
.mlh_Tail
;
29 while (header
!= tail
&& result
== NULL
)
32 result
= Allocate(header
, size
);
35 next_header
= (APTR
)header
->mh_Node
.ln_Succ
;
36 if (next_header
!= tail
)
38 if (gap_header
== NULL
39 && header
->mh_Upper
!= next_header
->mh_Lower
)
47 /* If a header with a gap after it wasn't found, we use the last one */
48 if (gap_header
== NULL
)
49 gap_header
= (APTR
)sd
->CardMem
.mlh_TailPred
;
52 /* Choose first 16MB block that isn't represented by an existing
54 header
= ObtainGfxMemory(sd
,
55 gap_header
->mh_Upper
- (APTR
)sd
->Card
.Framebuffer
, 16 * MBYTES
,
59 Insert((APTR
)&sd
->CardMem
, &header
->mh_Node
,
60 &gap_header
->mh_Node
);
61 result
= Allocate(header
, size
);
69 VOID
FreeGfxMem(struct g45staticdata
*sd
, APTR ptr
, ULONG size
)
71 struct MemHeader
*header
, *tail
;
74 header
= (APTR
)sd
->CardMem
.mlh_Head
;
75 tail
= (APTR
)&sd
->CardMem
.mlh_Tail
;
77 while (header
!= tail
&& !freed
)
79 /* Check if this is the header containing the memory to be freed */
80 if (ptr
>= header
->mh_Lower
&& ptr
< header
->mh_Upper
)
83 Deallocate(header
, ptr
, size
);
88 /* Unmap memory from graphics chip if it's unused. We don't unmap
89 * the first header because it's the initial BIOS-stolen memory */
90 if (header
->mh_Free
== header
->mh_Upper
- header
->mh_Lower
91 && (struct MinNode
*)header
!= sd
->CardMem
.mlh_Head
)
93 Remove(&header
->mh_Node
);
94 ReleaseGfxMemory(sd
, header
);
99 header
= (APTR
)header
->mh_Node
.ln_Succ
;
103 intptr_t G45_VirtualToPhysical(struct g45staticdata
*sd
, intptr_t virtual)
105 intptr_t page
= virtual >> 12; /* get page number */
106 intptr_t result
= -1;
108 if (page
>= 0 && page
< sd
->Card
.GATT_size
/ 4)
110 uint32_t pte
= readl(&sd
->Card
.GATT
[page
]);
113 result
= pte
& 0xfffff000;
114 result
|= virtual & 0xfff;
121 struct MemHeader
*ObtainGfxMemory(struct g45staticdata
*sd
, intptr_t virtual,
122 intptr_t length
, BOOL stolen
)
126 struct MemHeader
*header
= NULL
;
127 struct MemChunk
*chunk
;
129 /* Ensure we don't over-extend graphics memory into scratch area at end
131 if (virtual + length
>= sd
->ScratchArea
)
133 length
= sd
->ScratchArea
- virtual;
140 /* Get memory (aligned to page size) */
143 sys_mem
= AllocAlignedMem(length
, 4096);
144 D(bug("[GMA] Got %08x\n", sys_mem
));
147 header
= AllocVec(sizeof(struct MemHeader
), MEMF_CLEAR
);
148 if ((sys_mem
== NULL
&& !stolen
) || header
== NULL
)
154 D(bug("[GMA] Mapping system memory %08x to graphics virtual %08x "
155 "with size %08x\n", sys_mem
, virtual, length
));
158 /* Mirror allocated system memory in graphics memory window */
159 G45_AttachMemory(sd
, (IPTR
)sys_mem
, virtual, length
);
162 /* Set up a memory header to allocate from within graphics memory
164 chunk
= (struct MemChunk
*)(sd
->Card
.Framebuffer
+ virtual);
165 chunk
->mc_Next
= NULL
;
166 chunk
->mc_Bytes
= length
;
168 header
->mh_Node
.ln_Type
= NT_MEMORY
;
169 header
->mh_Node
.ln_Name
= sys_mem
;
170 header
->mh_First
= chunk
;
171 header
->mh_Lower
= chunk
;
172 header
->mh_Free
= length
;
173 header
->mh_Upper
= (UBYTE
*)chunk
+ length
;
179 FreeAlignedMem(sys_mem
);
186 void ReleaseGfxMemory(struct g45staticdata
*sd
, struct MemHeader
*header
)
188 D(bug("[GMA] Releasing memory block to system (header=%p)\n", header
));
189 D(bug("[GMA] mh_Lower=%p mh_Upper=%p mh_Free=%p\n",
190 header
->mh_Lower
, header
->mh_Upper
, header
->mh_Free
));
192 G45_DetachMemory(sd
, (char *)header
->mh_Lower
- sd
->Card
.Framebuffer
,
194 FreeAlignedMem(header
->mh_Node
.ln_Name
);
198 static void G45_AttachMemory(struct g45staticdata
*sd
, intptr_t physical
,
199 intptr_t virtual, intptr_t length
)
201 intptr_t page
= virtual >> 12;
205 physical
&= 0xfffff000;
206 length
&= 0xfffff000;
210 writel(physical
| 1, &sd
->Card
.GATT
[page
]);
216 while ((page
< sd
->Card
.GATT_size
/ 4) && length
);
221 void G45_AttachCacheableMemory(struct g45staticdata
*sd
, intptr_t physical
,
222 intptr_t virtual, intptr_t length
)
224 intptr_t page
= virtual >> 12;
228 physical
&= 0xfffff000;
229 length
&= 0xfffff000;
233 writel(physical
| 7, &sd
->Card
.GATT
[page
]);
239 while ((page
< sd
->Card
.GATT_size
/ 4) && length
);
244 static void G45_DetachMemory(struct g45staticdata
*sd
, intptr_t virtual,
247 intptr_t page
= virtual >> 12;
253 writel(0, &sd
->Card
.GATT
[page
]);
258 while ((page
< sd
->Card
.GATT_size
/ 4) && length
);
263 static APTR
AllocAlignedMem(IPTR size
, UWORD alignment
)
265 APTR mem
= NULL
, original_mem
;
267 size
+= 2 * sizeof(APTR
) + alignment
;
268 original_mem
= AllocMem(size
, MEMF_REVERSE
);
269 if (original_mem
!= NULL
)
271 mem
= (APTR
)((IPTR
)(original_mem
+ 2 * sizeof(APTR
) + alignment
- 1)
273 *((APTR
*)mem
- 1) = original_mem
;
274 *((IPTR
*)mem
- 2) = size
;
280 static VOID
FreeAlignedMem(APTR mem
)
283 FreeMem(*((APTR
*)mem
- 1), *((IPTR
*)mem
- 2));