OSDN Git Service

Add a "dev" argument to DRIVER_CTX_[CD]TOR. This will be used in an
[android-x86/external-libdrm.git] / shared-core / via_mm.c
1 /*
2  * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3  * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sub license,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19  * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 #define __NO_VERSION__
25 #include "via.h"
26 #include "drmP.h"
27 #include "via_drm.h"
28 #include "via_drv.h"
29 #include "via_ds.h"
30 #include "via_mm.h"
31
32 #define MAX_CONTEXT 100
33
34 unsigned int VIA_DEBUG = 1;
35
36 typedef struct {
37         int used;
38         int context;
39         set_t *sets[2]; /* 0 for frame buffer, 1 for AGP , 2 for System*/
40 } via_context_t;
41
42 static via_context_t global_ppriv[MAX_CONTEXT];
43
44 static int add_alloc_set(int context, int type, unsigned int val)
45 {
46         int i, retval = 0;
47   
48         for (i = 0; i < MAX_CONTEXT; i++) {
49                 if (global_ppriv[i].used && 
50                     global_ppriv[i].context == context) {
51                         retval = via_setAdd(global_ppriv[i].sets[type], val);
52                         break;
53                 }
54         }
55   
56         return retval;
57 }
58
59 static int del_alloc_set(int context, int type, unsigned int val)
60 {  
61         int i, retval = 0;
62   
63         for (i = 0; i < MAX_CONTEXT; i++)
64                 if (global_ppriv[i].used && 
65                     global_ppriv[i].context == context) {
66                         retval = via_setDel(global_ppriv[i].sets[type], val);
67                         break;
68                 }
69   
70         return retval;
71 }
72
73 /* agp memory management */ 
74 static memHeap_t *AgpHeap = NULL;
75
76 int via_agp_init( DRM_IOCTL_ARGS )
77 {
78         drm_via_agp_t agp;
79   
80         DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t *)data, sizeof(agp));
81
82         AgpHeap = via_mmInit(agp.offset, agp.size);
83
84         DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
85   
86         return 0;
87 }
88
89 /* fb memory management */ 
90 static memHeap_t *FBHeap = NULL;
91
92 int via_fb_init( DRM_IOCTL_ARGS )
93 {
94         drm_via_fb_t fb;
95
96    
97         DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t *)data, sizeof(fb));
98
99         FBHeap = via_mmInit(fb.offset, fb.size);
100
101         DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
102
103         return 0;
104 }
105
106 int via_init_context(drm_device_t *dev, int context)
107 {
108         int i;
109     
110         for (i = 0; i < MAX_CONTEXT ; i++)
111                 if (global_ppriv[i].used && 
112                     (global_ppriv[i].context == context))
113                         break;
114     
115         if (i >= MAX_CONTEXT) {
116                 for (i = 0; i < MAX_CONTEXT ; i++) {
117                         if (!global_ppriv[i].used) {
118                                 global_ppriv[i].context = context;
119                                 global_ppriv[i].used = 1;
120                                 global_ppriv[i].sets[0] = via_setInit();
121                                 global_ppriv[i].sets[1] = via_setInit();
122                                 DRM_DEBUG("init allocation set, socket=%d,"
123                                           " context = %d\n", i, context);
124                                 break;
125                         }
126                 }
127         
128                 if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
129                     (global_ppriv[i].sets[1] == NULL)) {
130                         return 0;
131                 }
132         }
133     
134         return 1;
135 }
136
137 int via_final_context(drm_device_t *dev, int context)
138 {
139         int i;
140         for (i=0; i<MAX_CONTEXT; i++)
141                 if (global_ppriv[i].used && 
142                     (global_ppriv[i].context == context))
143                         break;
144     
145         if (i < MAX_CONTEXT) {
146                 set_t *set;
147                 unsigned int item;
148                 int retval;
149           
150                 DRM_DEBUG("find socket %d, context = %d\n", i, context);
151             
152                 /* Video Memory */
153                 set = global_ppriv[i].sets[0];
154                 retval = via_setFirst(set, &item);
155                 while (retval) {
156                         DRM_DEBUG("free video memory 0x%x\n", item);
157                         via_mmFreeMem((PMemBlock)item);
158                         retval = via_setNext(set, &item);
159                 }
160                 via_setDestroy(set);
161             
162                 /* AGP Memory */
163                 set = global_ppriv[i].sets[1];
164                 retval = via_setFirst(set, &item);
165                 while (retval) {
166                         DRM_DEBUG("free agp memory 0x%x\n", item);
167                         via_mmFreeMem((PMemBlock)item);
168                         retval = via_setNext(set, &item);
169                 }
170                 via_setDestroy(set);
171         
172                 global_ppriv[i].used = 0;         
173         }
174     
175         return 1;
176 }
177 int via_mem_alloc( DRM_IOCTL_ARGS)
178 {
179         drm_via_mem_t mem;
180     
181         DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *)data, sizeof(mem));
182         switch (mem.type) {
183         case VIDEO :
184                 if (via_fb_alloc(&mem) < 0)
185                         return -EFAULT;
186                 DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *)data, mem, 
187                                        sizeof(mem));
188                 return 0;
189         case AGP :
190                 if (via_agp_alloc(&mem) < 0)
191                         return -EFAULT;
192                 DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *)data, mem, 
193                                        sizeof(mem));
194                 return 0;
195         }
196
197         return -EFAULT;
198 }
199
200 int via_fb_alloc(drm_via_mem_t* mem)
201 {
202         drm_via_mm_t fb;
203         PMemBlock block;
204         int retval = 0;
205    
206         if (!FBHeap)
207                 return -1;
208
209         fb.size = mem->size;
210         fb.context = mem->context;
211   
212         block = via_mmAllocMem(FBHeap, fb.size, 5, 0);
213         if (block) {
214                 fb.offset = block->ofs;
215                 fb.free = (unsigned int)block;
216                 if (!add_alloc_set(fb.context, VIDEO, fb.free)) {
217                         DRM_DEBUG("adding to allocation set fails\n");
218                         via_mmFreeMem((PMemBlock)fb.free);
219                         retval = -1;
220                 }
221         }
222         else {  
223                 fb.offset = 0;
224                 fb.size = 0;
225                 fb.free = 0;
226                 retval = -1;
227         }
228    
229         mem->offset = fb.offset;
230         mem->index = fb.free;
231
232         DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, 
233                   (int)fb.offset);
234   
235         return retval;
236 }
237 int via_agp_alloc(drm_via_mem_t* mem)
238 {
239         drm_via_mm_t agp;
240         PMemBlock block;
241         int retval = 0;
242
243         if (!AgpHeap)
244                 return -1;
245
246         agp.size = mem->size;
247         agp.context = mem->context;
248   
249         block = via_mmAllocMem(AgpHeap, agp.size, 5, 0);
250         if (block) {
251                 agp.offset = block->ofs;
252                 agp.free = (unsigned int)block;
253                 if (!add_alloc_set(agp.context, AGP, agp.free)) {
254                         DRM_DEBUG("adding to allocation set fails\n");
255                         via_mmFreeMem((PMemBlock)agp.free);
256                         retval = -1;
257                 }
258         }
259         else {  
260                 agp.offset = 0;
261                 agp.size = 0;
262                 agp.free = 0;
263         }       
264    
265         mem->offset = agp.offset;
266         mem->index = agp.free;
267
268         DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, 
269                   (unsigned int)agp.offset);
270         return retval;
271 }
272
273 int via_mem_free( DRM_IOCTL_ARGS )
274 {
275         drm_via_mem_t mem;
276     
277         DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *)data, sizeof(mem));
278
279         switch (mem.type) {
280
281         case VIDEO :
282                 if (via_fb_free(&mem) == 0)
283                         return 0;
284                 break;
285         case AGP :
286                 if (via_agp_free(&mem) == 0)
287                         return 0;
288                 break;
289         }
290     
291         return -EFAULT;
292 }
293 int via_fb_free(drm_via_mem_t* mem)
294 {
295         drm_via_mm_t fb;
296         int retval = 0;
297
298     
299         if (!FBHeap) {
300                 return -1;
301         }
302
303         fb.free = mem->index;
304         fb.context = mem->context;
305     
306         if (!fb.free)
307                 {
308                         return -1;
309
310                 }
311
312         via_mmFreeMem((PMemBlock)fb.free);
313     
314         if (!del_alloc_set(fb.context, VIDEO, fb.free))
315                 {
316                         retval = -1;
317                 }
318     
319         DRM_DEBUG("free fb, free = %d\n", fb.free);
320     
321         return retval;
322
323 int via_agp_free(drm_via_mem_t* mem)
324 {
325         drm_via_mm_t agp;
326   
327         int retval = 0;
328
329         agp.free = mem->index;
330         agp.context = mem->context;
331     
332         if (!agp.free)
333                 return -1;
334
335         via_mmFreeMem((PMemBlock)agp.free);
336     
337         if (!del_alloc_set(agp.context, AGP, agp.free)) {
338                 retval = -1;
339         }
340
341         DRM_DEBUG("free agp, free = %d\n", agp.free);
342   
343         return retval;
344 }
345
346 EXPORT_SYMBOL(via_fb_alloc);
347 EXPORT_SYMBOL(via_fb_free);