-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdrilib.c
More file actions
301 lines (263 loc) · 6.38 KB
/
drilib.c
File metadata and controls
301 lines (263 loc) · 6.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "xf86drm.h"
#include "xf86drmRandom.c"
#include "xf86drmHash.c"
#include "xf86drm.c"
#include "agpgart.h"
#include "agplib.h"
int drmfd;
unsigned char *gart;
/* Call xchg and cpuid asm instructions to flush the write combining cache.
* Could be replaced with sfence on some cpus or perhaps just the code
* for mb() from the kernel
*/
void flushWriteCombining(void)
{
int xchangeDummy;
__asm__ volatile(" push %%eax ; "
" xchg %%eax, %0 ;"
" pop %%eax" : : "m" (xchangeDummy));
__asm__ volatile(" push %%eax ; "
" push %%ebx ; "
" push %%ecx ; "
" push %%edx ; "
" movl $0,%%eax ; "
" cpuid ; "
" pop %%edx ; "
" pop %%ecx ; "
" pop %%ebx ; "
" pop %%eax" : /* no outputs */ : /* no inputs */ );
}
int bindMemory(unsigned long key, int page)
{
#if 0
printf("bind : 0x%08lx, page : %d\n", key, page);
#endif
if(drmAgpBind(drmfd, key, page << AGP_PAGE_SHIFT) < 0) {
printf("agp bind failed\n");
perror(" ");
exit(1);
}
return 0;
}
int unbindMemory(unsigned long key)
{
#if 0
printf("unbind : 0x%08lx\n", key);
#endif
if(drmAgpUnbind(drmfd, key) < 0) {
printf("agp unbind failed\n");
exit(1);
}
return 0;
}
unsigned long allocMemory(int size)
{
int ret_val;
drmHandle temp;
ret_val = drmAgpAlloc(drmfd, size << AGP_PAGE_SHIFT,
AGP_NORMAL_MEMORY, NULL, &temp);
if(ret_val < 0) {
printf("Agp alloc failed\n");
exit(1);
}
#if 0
printf("alloc : 0x%08lx, size : %d\n", temp, size);
#endif
return temp;
}
unsigned long allocAndBind(int page, int size)
{
unsigned long key = allocMemory(size);
bindMemory(key, page);
return key;
}
int freeMemory(unsigned long key)
{
return drmAgpFree(drmfd, key);
}
int getCurrentPages(void)
{
return drmAgpMemoryUsed(drmfd) >> AGP_PAGE_SHIFT;
}
int openAgpDevice(int flags, int argc, char **argv)
{
drmfd = drmOpenMinor(0, 1);
if(!drmfd) {
printf("open failed");
exit(1);
}
return 0;
}
size_t getApertureSize(void)
{
return drmAgpSize(drmfd) / 0x100000;
}
int supportsGetMap(void)
{
unsigned long ret_val;
ret_val = drmAgpQueryHandleSize(drmfd, AGP_RESERVED_KEY);
if(ret_val == (unsigned long)-1) return 0;
return 1;
}
/* Always return true for now */
int checkPageAvailable(int page)
{
return 1;
}
int printReserved(void)
{
return 0;
}
void *agp_alloc_driver_info(int ctx)
{
return NULL;
}
int agp_copy_driver_info(int ctx, void *buffer)
{
return -1;
}
void agp_output_driver_info(void *ptr)
{
}
/* For some reason my drm shell application won't let me map other types
* of memory, need to compare what I'm doing different then the
* Xserver. Bet it has to do with drmMagic and authentication.
*/
unsigned char *agp_map_memory(unsigned long key, off_t pg_ofs, size_t pages,
unsigned long prot, unsigned long flags)
{
return NULL;
}
/* Drm doesn't really do this, so don't bother */
int agp_unmap_memory(int key, unsigned char *ptr)
{
return 0;
}
int agp_get_num_contexts(void)
{
return drmAgpGetNumContexts(drmfd);
}
int agp_change_context(int ctx)
{
return drmAgpChangeContext(drmfd, ctx);;
}
void agp_close_and_release(void)
{
close(drmfd);
}
drmHandle hSAREA;
drmHandle hFRAME;
drmAddress SAREA;
static int fakeOutDri(void)
{
drmHandle hSAREA;
unsigned long agp_base = drmAgpBase(drmfd);
unsigned long agp_size = drmAgpSize(drmfd);
printf("Using agp base : 0x%08lx\n", agp_base);
if(drmSetBusid(drmfd, "0:0.0") < 0) {
printf("set bus id failed\n");
exit(1);
}
if(drmAddMap(drmfd, 0, 4096, DRM_SHM, DRM_CONTAINS_LOCK, &hSAREA) < 0) {
printf("SAREA create failed\n");
exit(1);
}
if(drmMap(drmfd, hSAREA, 4096, &SAREA) < 0) {
printf("SAREA map failed\n");
exit(1);
}
if(drmAddMap(drmfd, agp_base, agp_size, DRM_FRAME_BUFFER, 0, &hFRAME) < 0) {
printf("Adding fake framebuffer failed\n");
exit(1);
}
return 0;
}
/* do some add map stuff here, steal from Xserver code perhaps */
int initializeAgp(void)
{
int ret_val;
unsigned long size;
drmHandle agpSpace;
drmAddress address;
unsigned long mode;
ret_val = drmAgpAcquire(drmfd);
if(ret_val < 0) {
printf("agp acquire failed\n");
exit(1);
}
size = drmAgpSize(drmfd);
printf("Agp size : %dM\n", (int)(size / 0x100000));
/* Pretend to be the Xserver */
fakeOutDri();
/* setup gart to point to the agp aperture */
ret_val = drmAddMap(drmfd, 0, size, DRM_AGP, 0, &agpSpace);
if(ret_val < 0) {
printf("drm add map failed\n");
exit(1);
}
/* HACK HACK, map ourselves as a framebuffer, otherwise things won't work. */
ret_val = drmMap(drmfd, hFRAME, size, &address);
if(ret_val < 0) {
printf("drm map failed\n");
perror(" ");
exit(1);
}
gart = (void *)address;
/* Setup agp mode */
mode = drmAgpGetMode(drmfd);
ret_val = drmAgpEnable(drmfd, mode);
if(ret_val < 0) {
printf("drm agp enable failed\n");
}
/* Return aperture size */
return size / 0x100000;
}
static int getNumberOfPages(void)
{
unsigned long apertureSize = getApertureSize() * 0x100000;
int numberPages = apertureSize / AGP_PAGE_SIZE;
return numberPages;
}
/* Very stupid brute force approach to finding a slot of size,
* if we want this to be fast we need to make a memory allocator of some
* kind. This test code doesn't have to be terribly efficent so we
* don't care.
* This function only handles the reserved memory, nothing else at the
* moment. Its all we need so don't worry.
*
* returns -1 if we can't find such a region.
*/
int findFirstRegionOfSize(int numberPages)
{
int pagesTotal = getNumberOfPages();
int i, k;
for(i = 0; i < pagesTotal; i++) {
if(checkPageAvailable(i) == TRUE) {
/* We already know the first page is available */
for(k = 1; k < numberPages; k++) {
if(checkPageAvailable(i + k) == FALSE) break;
}
/* Full region is available, return i as the index */
if(k == numberPages) return i;
/* Okay we didn't get the full region and i + k is not available,
* so we continue testing at i + k + 1
*/
i = i + k + 1;
}
}
return -1;
}
/* Agpgart specific tests which aren't important to us. */
void clientTest(int aper_size)
{
}
void testMemoryFailures(int aper_size)
{
}
void keyRecycleTest(void)
{
}