]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/drm/sis_mm.c
This commit was generated by cvs2svn to compensate for changes in r136632,
[FreeBSD/FreeBSD.git] / sys / dev / drm / sis_mm.c
1 /* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*-
2  * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
3  *
4  * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5  * All rights reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  * 
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  * 
26  * Authors:
27  *    Sung-Ching Lin <sclin@sis.com.tw>
28  * 
29  * $FreeBSD$
30  */
31
32 #include "dev/drm/sis.h"
33 #include "dev/drm/drmP.h"
34 #include "dev/drm/sis_drm.h"
35 #include "dev/drm/sis_drv.h"
36 #include "dev/drm/sis_ds.h"
37 #if defined(__linux__) && defined(CONFIG_FB_SIS)
38 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
39 #include <video/sisfb.h>
40 #else
41 #include <linux/sisfb.h>
42 #endif
43 #endif
44
45 #define MAX_CONTEXT 100
46 #define VIDEO_TYPE 0 
47 #define AGP_TYPE 1
48
49 typedef struct {
50         int used;
51         int context;
52         set_t *sets[2]; /* 0 for video, 1 for AGP */
53 } sis_context_t;
54
55 static sis_context_t global_ppriv[MAX_CONTEXT];
56
57
58 static int add_alloc_set(int context, int type, unsigned int val)
59 {
60         int i, retval = 0;
61         
62         for (i = 0; i < MAX_CONTEXT; i++) {
63                 if (global_ppriv[i].used && global_ppriv[i].context == context)
64                 {
65                         retval = setAdd(global_ppriv[i].sets[type], val);
66                         break;
67                 }
68         }
69         return retval;
70 }
71
72 static int del_alloc_set(int context, int type, unsigned int val)
73 {  
74         int i, retval = 0;
75
76         for (i = 0; i < MAX_CONTEXT; i++) {
77                 if (global_ppriv[i].used && global_ppriv[i].context == context)
78                 {
79                         retval = setDel(global_ppriv[i].sets[type], val);
80                         break;
81                 }
82         }
83         return retval;
84 }
85
86 /* fb management via fb device */ 
87 #if defined(__linux__) && defined(CONFIG_FB_SIS)
88
89 int sis_fb_init( DRM_IOCTL_ARGS )
90 {
91         return 0;
92 }
93
94 int sis_fb_alloc( DRM_IOCTL_ARGS )
95 {
96         drm_sis_mem_t fb;
97         struct sis_memreq req;
98         int retval = 0;
99
100         DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
101
102         req.size = fb.size;
103         sis_malloc(&req);
104         if (req.offset) {
105                 /* TODO */
106                 fb.offset = req.offset;
107                 fb.free = req.offset;
108                 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
109                         DRM_DEBUG("adding to allocation set fails\n");
110                         sis_free(req.offset);
111                         retval = DRM_ERR(EINVAL);
112                 }
113         } else {  
114                 fb.offset = 0;
115                 fb.size = 0;
116                 fb.free = 0;
117         }
118
119         DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb));
120
121         DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
122
123         return retval;
124 }
125
126 int sis_fb_free( DRM_IOCTL_ARGS )
127 {
128         drm_sis_mem_t fb;
129         int retval = 0;
130
131         DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
132
133         if (!fb.free)
134                 return DRM_ERR(EINVAL);
135
136         if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
137                 retval = DRM_ERR(EINVAL);
138         sis_free(fb.free);
139
140         DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free);
141
142         return retval;
143 }
144
145 #else
146
147 /* Called by the X Server to initialize the FB heap.  Allocations will fail
148  * unless this is called.  Offset is the beginning of the heap from the
149  * framebuffer offset (MaxXFBMem in XFree86).
150  *
151  * Memory layout according to Thomas Winischofer:
152  * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC|
153  *
154  *    X driver/sisfb                                  HW-   Command-
155  *  framebuffer memory           DRI heap           Cursor   queue
156  */
157 int sis_fb_init( DRM_IOCTL_ARGS )
158 {
159         DRM_DEVICE;
160         drm_sis_private_t *dev_priv = dev->dev_private;
161         drm_sis_fb_t fb;
162
163         DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t *)data, sizeof(fb));
164
165         if (dev_priv == NULL) {
166                 dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t),
167                     DRM_MEM_DRIVER);
168                 dev_priv = dev->dev_private;
169                 if (dev_priv == NULL)
170                         return ENOMEM;
171         }
172
173         if (dev_priv->FBHeap != NULL)
174                 return DRM_ERR(EINVAL);
175
176         dev_priv->FBHeap = mmInit(fb.offset, fb.size);
177
178         DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
179
180         return 0;
181 }
182
183 int sis_fb_alloc( DRM_IOCTL_ARGS )
184 {
185         DRM_DEVICE;
186         drm_sis_private_t *dev_priv = dev->dev_private;
187         drm_sis_mem_t fb;
188         PMemBlock block;
189         int retval = 0;
190
191         if (dev_priv == NULL || dev_priv->FBHeap == NULL)
192                 return DRM_ERR(EINVAL);
193   
194         DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
195   
196         block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
197         if (block) {
198                 /* TODO */
199                 fb.offset = block->ofs;
200                 fb.free = (unsigned long)block;
201                 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
202                         DRM_DEBUG("adding to allocation set fails\n");
203                         mmFreeMem((PMemBlock)fb.free);
204                         retval = DRM_ERR(EINVAL);
205                 }
206         } else {
207                 fb.offset = 0;
208                 fb.size = 0;
209                 fb.free = 0;
210         }
211
212         DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb));
213
214         DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset);
215
216         return retval;
217 }
218
219 int sis_fb_free( DRM_IOCTL_ARGS )
220 {
221         DRM_DEVICE;
222         drm_sis_private_t *dev_priv = dev->dev_private;
223         drm_sis_mem_t fb;
224
225         if (dev_priv == NULL || dev_priv->FBHeap == NULL)
226                 return DRM_ERR(EINVAL);
227
228         DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
229
230         if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock)fb.free))
231                 return DRM_ERR(EINVAL);
232
233         if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
234                 return DRM_ERR(EINVAL);
235         mmFreeMem((PMemBlock)fb.free);
236
237         DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
238
239         return 0;
240 }
241
242 #endif
243
244 /* agp memory management */ 
245
246 int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
247 {
248         DRM_DEVICE;
249         drm_sis_private_t *dev_priv = dev->dev_private;
250         drm_sis_agp_t agp;
251
252         if (dev_priv == NULL) {
253                 dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t),
254                     DRM_MEM_DRIVER);
255                 dev_priv = dev->dev_private;
256                 if (dev_priv == NULL)
257                         return ENOMEM;
258         }
259
260         if (dev_priv->AGPHeap != NULL)
261                 return DRM_ERR(EINVAL);
262
263         DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t *)data, sizeof(agp));
264
265         dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
266
267         DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
268   
269         return 0;
270 }
271
272 int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
273 {
274         DRM_DEVICE;
275         drm_sis_private_t *dev_priv = dev->dev_private;
276         drm_sis_mem_t agp;
277         PMemBlock block;
278         int retval = 0;
279    
280         if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
281                 return DRM_ERR(EINVAL);
282   
283         DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp));
284   
285         block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
286         if (block) {
287                 /* TODO */
288                 agp.offset = block->ofs;
289                 agp.free = (unsigned long)block;
290                 if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
291                         DRM_DEBUG("adding to allocation set fails\n");
292                         mmFreeMem((PMemBlock)agp.free);
293                         retval = -1;
294                 }
295         } else {  
296                 agp.offset = 0;
297                 agp.size = 0;
298                 agp.free = 0;
299         }
300
301         DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, agp, sizeof(agp));
302
303         DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
304
305         return retval;
306 }
307
308 int sis_ioctl_agp_free( DRM_IOCTL_ARGS )
309 {
310         DRM_DEVICE;
311         drm_sis_private_t *dev_priv = dev->dev_private;
312         drm_sis_mem_t agp;
313
314         if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
315                 return DRM_ERR(EINVAL);
316
317         DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp));
318
319         if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock)agp.free))
320                 return DRM_ERR(EINVAL);
321
322         mmFreeMem((PMemBlock)agp.free);
323         if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
324                 return DRM_ERR(EINVAL);
325
326         DRM_DEBUG("free agp, free = 0x%lx\n", agp.free);
327
328         return 0;
329 }
330
331 int sis_init_context(int context)
332 {
333         int i;
334
335         for (i = 0; i < MAX_CONTEXT ; i++) {
336                 if (global_ppriv[i].used &&
337                     (global_ppriv[i].context == context))
338                         break;
339         }
340
341         if (i >= MAX_CONTEXT) {
342                 for (i = 0; i < MAX_CONTEXT ; i++) {
343                         if (!global_ppriv[i].used) {
344                                 global_ppriv[i].context = context;
345                                 global_ppriv[i].used = 1;
346                                 global_ppriv[i].sets[0] = setInit();
347                                 global_ppriv[i].sets[1] = setInit();
348                                 DRM_DEBUG("init allocation set, socket=%d, "
349                                     "context = %d\n", i, context);
350                                 break;
351                         }
352                 }
353                 if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
354                     (global_ppriv[i].sets[1] == NULL))
355                 {
356                         return 0;
357                 }
358         }
359         
360         return 1;
361 }
362
363 int sis_final_context(int context)
364 {
365         int i;
366
367         for (i=0; i<MAX_CONTEXT; i++) {
368                 if (global_ppriv[i].used &&
369                     (global_ppriv[i].context == context))
370                         break;
371         }
372
373         if (i < MAX_CONTEXT) {
374                 set_t *set;
375                 ITEM_TYPE item;
376                 int retval;
377
378                 DRM_DEBUG("find socket %d, context = %d\n", i, context);
379
380                 /* Video Memory */
381                 set = global_ppriv[i].sets[0];
382                 retval = setFirst(set, &item);
383                 while (retval) {
384                         DRM_DEBUG("free video memory 0x%lx\n", item);
385 #if defined(__linux__) && defined(CONFIG_FB_SIS)
386                         sis_free(item);
387 #else
388                         mmFreeMem((PMemBlock)item);
389 #endif
390                         retval = setNext(set, &item);
391                 }
392                 setDestroy(set);
393
394                 /* AGP Memory */
395                 set = global_ppriv[i].sets[1];
396                 retval = setFirst(set, &item);
397                 while (retval) {
398                         DRM_DEBUG("free agp memory 0x%lx\n", item);
399                         mmFreeMem((PMemBlock)item);
400                         retval = setNext(set, &item);
401                 }
402                 setDestroy(set);
403
404                 global_ppriv[i].used = 0;         
405         }
406         
407         return 1;
408 }