First check in for DRM that splits core from personality modules
[platform/upstream/libdrm.git] / linux-core / savage_drv.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
25 #include <linux/config.h>
26 #include "drmP.h"
27 #include "savage_drm.h"
28 #include "savage_drv.h"
29
30 #define DRIVER_AUTHOR           "John Zhao, S3 Graphics Inc."
31
32 #define DRIVER_NAME             "savage"
33 #define DRIVER_DESC             "Savage4 Family"
34 #define DRIVER_DATE             "20011023"
35
36 #define DRIVER_MAJOR            1
37 #define DRIVER_MINOR            0
38 #define DRIVER_PATCHLEVEL       0
39
40 /* Currently Savage4 not implement DMA */
41 /* mark off by Jiayo Hsu, Oct. 23, 2001*/
42
43
44 #if SAVAGE_CMD_DMA /* Check the 3D driver, and we need to fix this anyway */
45
46 int savage_alloc_continuous_mem(struct inode *inode, struct file *filp,
47                 unsigned int cmd, unsigned long arg)
48 {
49   drm_savage_alloc_cont_mem_t cont_mem; 
50   unsigned long size,addr;
51   void * ret;
52   int i;
53   mem_map_t *p;
54   pgprot_t flags;
55
56   /* add to list */  
57   drm_file_t *priv = filp->private_data;
58   drm_device_t *dev = priv->dev;
59   drm_map_t *map;
60   drm_map_list_t *list;
61
62   if (copy_from_user(&cont_mem,(drm_savage_alloc_cont_mem_t *)arg,sizeof(cont_mem)))
63     return -EFAULT;
64  
65   map = savage_alloc)( sizeof(*map), DRM_MEM_MAPS );
66   if ( !map )
67     return -ENOMEM;
68   
69   /*check the parameters*/
70   if (cont_mem.size <= 0 )
71     return -EINVAL;
72   
73   size = cont_mem.type * cont_mem.size;
74   printk("[drm]JTLIsize = %lu\n",size);
75   
76   ret = (void *)__get_free_pages(GFP_KERNEL, get_order(size));
77   if (ret == NULL)
78     {
79       printk("Kalloc error\n");
80       return 0;
81     }
82   
83   /*set the reserverd flag so that the remap_page_range can map these page*/
84   for(i=0,p=virt_to_page(ret);i< size /PAGE_SIZE; i++,p++)
85     SetPageReserved(p);
86   
87   cont_mem.phyaddress = virt_to_bus(ret);
88   cont_mem.location = DRM_SAVAGE_MEM_LOCATION_PCI; /* pci only at present*/
89   
90   
91   /*Map the memory to user space*/
92   down_write(&current->mm->mmap_sem);
93   addr=do_mmap(NULL,0,size,PROT_READ|PROT_WRITE,MAP_PRIVATE,cont_mem.phyaddress);
94   if (addr<=0)
95     return -EFAULT;
96   pgprot_val(flags)=_PAGE_PRESENT | _PAGE_RW |_PAGE_USER ;
97   if (remap_page_range(addr,cont_mem.phyaddress,size,flags))
98     return -EFAULT;
99   up_write(&current->mm->mmap_sem);
100   
101   for(i=0,p=virt_to_page(ret);i< size /PAGE_SIZE; i++,p++)
102     ClearPageReserved(p);
103   
104   cont_mem.linear = addr;
105   
106   /*map list*/
107   map->handle =  ret; /* to distinguish with other*/
108   map->offset = cont_mem.phyaddress;
109   map->size = size;
110   map->mtrr=-1;
111   /*map-flags,type??*/
112   
113   list = savage_alloc)(sizeof(*list), DRM_MEM_MAPS);
114   if(!list) {
115     savage_free)(map, sizeof(*map), DRM_MEM_MAPS);
116     return -EINVAL;
117   }
118   memset(list, 0, sizeof(*list));
119   list->map = map;
120   
121   down(&dev->struct_sem);
122   list_add(&list->head, &dev->maplist->head);
123   up(&dev->struct_sem);
124   
125   if (copy_to_user((drm_savage_alloc_cont_mem_t *)arg,&cont_mem,sizeof(cont_mem)))
126     return -EFAULT;
127
128   for(i=0,p=virt_to_page(ret);i< size /PAGE_SIZE; i++,p++)
129     atomic_set(&p->count,1);
130
131   return 1;/*success*/  
132 }
133
134 int savage_get_physics_address(struct inode *inode, struct file *filp,
135                                unsigned int cmd, unsigned long arg)
136 {
137   
138   drm_savage_get_physcis_address_t req;
139   unsigned long buf;
140   pgd_t *pgd;
141   pmd_t *pmd;
142   pte_t *pte;
143   struct mm_struct *mm;
144   
145   if (copy_from_user(&req,(drm_savage_get_physcis_address_t *)arg,sizeof(req)))
146     return -EFAULT;
147   buf = req.v_address;
148   
149   /*What kind of virtual address ?*/
150   if (buf >= (unsigned long)high_memory)
151     mm = &init_mm;
152   else
153     mm = current->mm;
154   
155 #ifdef LINUX_24
156   spin_lock(&mm->page_table_lock);
157 #endif
158   
159   pgd=pgd_offset(mm,buf);
160   pmd=pmd_offset(pgd,buf);
161   pte=pte_offset_map(pmd,buf);
162   
163   if (!pte_present(*pte))
164     return -EFAULT;
165   
166   req.p_address = ((pte_val(*pte) &PAGE_MASK) |( buf&(PAGE_SIZE-1)));
167   
168   if (copy_to_user((drm_savage_get_physcis_address_t  *)arg,&req,sizeof(req)))
169     return -EFAULT;
170   return 1;
171 }
172
173 /*free the continuous memory*/
174 int savage_free_cont_mem(struct inode *inode, struct file *filp,
175                                unsigned int cmd, unsigned long arg)
176 {
177   drm_savage_alloc_cont_mem_t cont_mem; 
178   unsigned long size;
179
180   /*map  list */  
181   drm_file_t *priv = filp->private_data;
182   drm_device_t *dev = priv->dev;
183   drm_map_t *map;
184   struct list_head *list;
185   drm_map_list_t *r_list = NULL;
186
187   if (copy_from_user(&cont_mem,(drm_savage_alloc_cont_mem_t *)arg,sizeof(cont_mem)))
188     return -EFAULT;
189   size = cont_mem.type * cont_mem.size;
190   if (size <= 0)
191     return -EINVAL;
192
193   /* find the map in the list */
194   list_for_each(list,&dev->maplist->head)
195     {
196       r_list = (drm_map_list_t *) list;
197       
198       if(r_list->map &&
199          r_list->map->offset == cont_mem.phyaddress )
200          break;   
201     }
202   /*find none*/
203   if(list == (&dev->maplist->head)) {
204     up(&dev->struct_sem);
205     return -EINVAL;
206   }
207   map = r_list->map;
208   list_del(list);
209   savage_free)(list, sizeof(*list), DRM_MEM_MAPS);
210
211   /*unmap the user space */
212 #ifdef DO_MUNMAP_4_ARGS
213   if ( do_munmap(current->mm,cont_mem.linear,size,1)!=0)
214 #else
215   if ( do_munmap(current->mm,cont_mem.linear,size)!=0)
216 #endif
217     return -EFAULT;
218   /*free the page*/
219   free_pages((unsigned long)map->handle, get_order(size));
220
221   return 1;
222 }
223 #else /* SAVAGE_CMD_DMA */
224 #define DRIVER_IOCTLS
225 #endif /* SAVAGE_CMD_DMA */
226
227 #if 0
228
229 #define DRIVER_IOCTLS                                                      \
230         [DRM_IOCTL_NR(DRM_IOCTL_DMA)]         = { mga_dma_buffers, 1, 0 }, \
231         [DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)]    = { mga_dma_init,    1, 1 }, \
232         [DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)]   = { mga_dma_flush,   1, 0 }, \
233         [DRM_IOCTL_NR(DRM_IOCTL_MGA_RESET)]   = { mga_dma_reset,   1, 0 }, \
234         [DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)]    = { mga_dma_swap,    1, 0 }, \
235         [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)]   = { mga_dma_clear,   1, 0 }, \
236         [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)]  = { mga_dma_vertex,  1, 0 }, \
237         [DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, \
238         [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)]   = { mga_dma_iload,   1, 0 }, \
239         [DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)]    = { mga_dma_blit,    1, 0 },
240
241
242 #endif /* end #if 0 */
243
244 #include "drm_pciids.h"
245
246 static int postinit( struct drm_device *dev, unsigned long flags )
247 {
248         DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
249                 DRIVER_NAME,
250                 DRIVER_MAJOR,
251                 DRIVER_MINOR,
252                 DRIVER_PATCHLEVEL,
253                 DRIVER_DATE,
254                 dev->minor,
255                 pci_pretty_name(dev->pdev)
256                 );
257         return 0;
258 }
259
260 static int version( drm_version_t *version )
261 {
262         int len;
263
264         version->version_major = DRIVER_MAJOR;
265         version->version_minor = DRIVER_MINOR;
266         version->version_patchlevel = DRIVER_PATCHLEVEL;
267         DRM_COPY( version->name, DRIVER_NAME );
268         DRM_COPY( version->date, DRIVER_DATE );
269         DRM_COPY( version->desc, DRIVER_DESC );
270         return 0;
271 }
272
273 static struct pci_device_id pciidlist[] = {
274         savage_PCI_IDS
275 };
276
277 static drm_ioctl_desc_t ioctls[] = {
278 #if SAVAGE_CMD_DMA /* Check the 3D driver, and we need to fix this anyway */
279         [DRM_IOCTL_NR(DRM_SAVAGE_ALLOC_CONTINUOUS_MEM)] = {savage_alloc_continuous_mem, 1, 0},
280         [DRM_IOCTL_NR(DRM_SAVAGE_GET_PHYSICS_ADDRESS)]  = {savage_get_physics_address,  1, 0},
281         [DRM_IOCTL_NR(DRM_SAVAGE_FREE_CONTINUOUS_MEM)]  = {savage_free_cont_mem,        1, 0},
282 #endif  
283 };
284
285 static struct drm_driver_fn driver_fn = {
286         .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR,
287         .reclaim_buffers = drm_core_reclaim_buffers,
288         .get_map_ofs = drm_core_get_map_ofs,
289         .get_reg_ofs = drm_core_get_reg_ofs,
290         .preinit = savage_preinit,
291         .postinit = postinit,
292         .version = version,
293         .ioctls = ioctls,
294         .num_ioctls = DRM_ARRAY_SIZE(ioctls),
295 };
296
297 static int probe(struct pci_dev *pdev, const struct pci_device_id *ent)
298 {
299         return drm_probe(pdev, ent, &driver_fn);
300 }
301
302 static struct pci_driver driver = {
303         .name          = DRIVER_NAME,
304         .id_table      = pciidlist,
305         .probe         = probe,
306         .remove        = __devexit_p(drm_cleanup_pci),
307 };
308
309 static int __init savage_init(void)
310 {
311         return drm_init(&driver, pciidlist, &driver_fn);
312 }
313
314 static void __exit savage_exit(void)
315 {
316         drm_exit(&driver);
317 }
318
319 module_init(savage_init);
320 module_exit(savage_exit);
321
322 MODULE_AUTHOR( DRIVER_AUTHOR );
323 MODULE_DESCRIPTION( DRIVER_DESC );
324 MODULE_LICENSE("GPL and additional rights");