commented early_printk patch because of rejects.
[linux-flexiantxendom0-3.2.10.git] / drivers / char / 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  */
30
31 #include <linux/config.h>
32 #include "sis.h"
33 #include "video/sisfb.h"
34 #include "drmP.h"
35 #include "sis_drm.h"
36 #include "sis_drv.h"
37 #include "sis_ds.h"
38
39 #define MAX_CONTEXT 100
40 #define VIDEO_TYPE 0 
41 #define AGP_TYPE 1
42
43 typedef struct {
44   int used;
45   int context;
46   set_t *sets[2]; /* 0 for video, 1 for AGP */
47 } sis_context_t;
48
49 static sis_context_t global_ppriv[MAX_CONTEXT];
50
51 static int add_alloc_set(int context, int type, unsigned int val)
52 {
53   int i, retval = 0;
54   
55   for(i = 0; i < MAX_CONTEXT; i++)
56     if(global_ppriv[i].used && global_ppriv[i].context == context){
57       retval = setAdd(global_ppriv[i].sets[type], val);
58       break;
59     }
60   return retval;
61 }
62
63 static int del_alloc_set(int context, int type, unsigned int val)
64 {  
65   int i, retval = 0;
66   for(i = 0; i < MAX_CONTEXT; i++)
67     if(global_ppriv[i].used && global_ppriv[i].context == context){
68       retval = setDel(global_ppriv[i].sets[type], val);
69       break;
70     }
71   return retval;
72 }
73
74 /* fb management via fb device */ 
75 #if 1
76 int sis_fb_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
77                   unsigned long arg)
78 {
79   drm_sis_mem_t fb;
80   struct sis_memreq req;
81   int retval = 0;
82    
83   if (copy_from_user(&fb, (drm_sis_mem_t *)arg, sizeof(fb)))
84           return -EFAULT;
85   
86   req.size = fb.size;
87   sis_malloc(&req);
88   if(req.offset){
89     /* TODO */
90     fb.offset = req.offset;
91     fb.free = req.offset;
92     if(!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)){
93       DRM_DEBUG("adding to allocation set fails\n");
94       sis_free(req.offset);
95       retval = -1;
96     }
97   }
98   else{  
99     fb.offset = 0;
100     fb.size = 0;
101     fb.free = 0;
102   }
103    
104   if (copy_to_user((drm_sis_mem_t *)arg, &fb, sizeof(fb))) return -EFAULT;
105
106   DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
107
108   return retval;
109 }
110
111 int sis_fb_free(struct inode *inode, struct file *filp, unsigned int cmd,
112                   unsigned long arg)
113 {
114   drm_sis_mem_t fb;
115   int retval = 0;
116     
117   if (copy_from_user(&fb, (drm_sis_mem_t *)arg, sizeof(fb)))
118           return -EFAULT;
119   
120   if(!fb.free){
121     return -1;
122   }
123
124   sis_free(fb.free);
125   if(!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
126     retval = -1;
127
128   DRM_DEBUG("free fb, offset = %d\n", fb.free);
129   
130   return retval;
131 }
132
133 #else
134
135 int sis_fb_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
136                   unsigned long arg)
137 {
138   return -1;
139 }
140
141 int sis_fb_free(struct inode *inode, struct file *filp, unsigned int cmd,
142                   unsigned long arg)
143 {
144   return 0;
145 }
146
147 #endif
148
149 /* agp memory management */ 
150 #if 1
151
152 static memHeap_t *AgpHeap = NULL;
153
154 int sisp_agp_init(struct inode *inode, struct file *filp, unsigned int cmd,
155                   unsigned long arg)
156 {
157   drm_sis_agp_t agp;
158    
159   if (copy_from_user(&agp, (drm_sis_agp_t *)arg, sizeof(agp)))
160           return -EFAULT;
161
162   AgpHeap = mmInit(agp.offset, agp.size);
163
164   DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
165   
166   return 0;
167 }
168
169 int sisp_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
170                   unsigned long arg)
171 {
172   drm_sis_mem_t agp;
173   PMemBlock block;
174   int retval = 0;
175    
176   if(!AgpHeap)
177     return -1;
178   
179   if (copy_from_user(&agp, (drm_sis_mem_t *)arg, sizeof(agp)))
180           return -EFAULT;
181   
182   block = mmAllocMem(AgpHeap, agp.size, 0, 0);
183   if(block){
184     /* TODO */
185     agp.offset = block->ofs;
186     agp.free = (unsigned long)block;
187     if(!add_alloc_set(agp.context, AGP_TYPE, agp.free)){
188       DRM_DEBUG("adding to allocation set fails\n");
189       mmFreeMem((PMemBlock)(unsigned long)agp.free);
190       retval = -1;
191     }
192   }
193   else{  
194     agp.offset = 0;
195     agp.size = 0;
196     agp.free = 0;
197   }
198    
199   if (copy_to_user((drm_sis_mem_t *)arg, &agp, sizeof(agp))) return -EFAULT;
200
201   DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
202
203   return retval;
204 }
205
206 int sisp_agp_free(struct inode *inode, struct file *filp, unsigned int cmd,
207                   unsigned long arg)
208 {
209   drm_sis_mem_t agp;
210   int retval = 0;
211
212   if(!AgpHeap)
213     return -1;
214     
215   if (copy_from_user(&agp, (drm_sis_mem_t *)arg, sizeof(agp)))
216           return -EFAULT;
217   
218   if(!agp.free){
219     return -1;
220   }
221
222   mmFreeMem((PMemBlock)(unsigned long)agp.free);
223   if(!del_alloc_set(agp.context, AGP_TYPE, agp.free))
224     retval = -1;
225
226   DRM_DEBUG("free agp, free = %d\n", agp.free);
227   
228   return retval;
229 }
230
231 #endif
232
233 int sis_init_context(int context)
234 {
235         int i;
236         
237         for(i = 0; i < MAX_CONTEXT ; i++)
238           if(global_ppriv[i].used && (global_ppriv[i].context == context))
239             break;
240
241         if(i >= MAX_CONTEXT){
242           for(i = 0; i < MAX_CONTEXT ; i++){
243             if(!global_ppriv[i].used){
244               global_ppriv[i].context = context;
245               global_ppriv[i].used = 1;
246               global_ppriv[i].sets[0] = setInit();
247               global_ppriv[i].sets[1] = setInit();
248               DRM_DEBUG("init allocation set, socket=%d, context = %d\n", 
249                          i, context);
250               break;
251             }   
252           }
253           if((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
254              (global_ppriv[i].sets[1] == NULL)){
255             return 0;
256           }
257         }
258         
259         return 1;
260 }
261
262 int sis_final_context(int context)
263 {
264         int i;
265
266         for(i=0; i<MAX_CONTEXT; i++)
267           if(global_ppriv[i].used && (global_ppriv[i].context == context))
268             break;
269           
270         if(i < MAX_CONTEXT){
271           set_t *set;
272           unsigned int item;
273           int retval;
274           
275           DRM_DEBUG("find socket %d, context = %d\n", i, context);
276
277           /* Video Memory */
278           set = global_ppriv[i].sets[0];
279           retval = setFirst(set, &item);
280           while(retval){
281             DRM_DEBUG("free video memory 0x%x\n", item);
282             sis_free(item);
283             retval = setNext(set, &item);
284           }
285           setDestroy(set);
286
287           /* AGP Memory */
288           set = global_ppriv[i].sets[1];
289           retval = setFirst(set, &item);
290           while(retval){
291             DRM_DEBUG("free agp memory 0x%x\n", item);
292             mmFreeMem((PMemBlock)(unsigned long)item);
293             retval = setNext(set, &item);
294           }
295           setDestroy(set);
296           
297           global_ppriv[i].used = 0;       
298         }
299
300         /* turn-off auto-flip */
301         /* TODO */
302 #if defined(SIS_STEREO)
303         flip_final();
304 #endif
305         
306         return 1;
307 }