465feb3cc2900f466026cc0f2fa61b4c1474b823
[platform/upstream/libdrm.git] / linux-core / xgi_linux.h
1
2 /****************************************************************************
3  * Copyright (C) 2003-2006 by XGI Technology, Taiwan.                   
4  *                                                                                                                                                      *
5  * All Rights Reserved.                                                                                                         *
6  *                                                                                                                                                      *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files (the      
9  * "Software"), to deal in the Software without restriction, including  
10  * without limitation on the rights to use, copy, modify, merge,        
11  * publish, distribute, sublicense, and/or sell copies of the Software, 
12  * and to permit persons to whom the Software is furnished to do so,    
13  * subject to the following conditions:                                 
14  *                                                                                                                                                      *
15  * The above copyright notice and this permission notice (including the 
16  * next paragraph) shall be included in all copies or substantial       
17  * portions of the Software.                                            
18  *                                                                                                                                                      *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      
20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                
22  * NON-INFRINGEMENT.  IN NO EVENT SHALL XGI AND/OR                      
23  * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,           
24  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,           
25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER                        
26  * DEALINGS IN THE SOFTWARE.                                                                                            
27  ***************************************************************************/
28
29 #ifndef _XGI_LINUX_H_
30 #define _XGI_LINUX_H_
31
32 #ifndef LINUX_VERSION_CODE
33 #include <linux/version.h>
34 #endif
35
36 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
37 #   error "This driver does not support pre-2.6 kernels!"
38 #endif
39
40 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
41 #   define XGI_REMAP_PFN_RANGE_PRESENT
42 #else
43 #   define XGI_REMAP_PAGE_RANGE_5
44 #endif
45
46 #if defined (CONFIG_SMP) && !defined (__SMP__)
47 #define __SMP__
48 #endif
49
50 #if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
51 #define MODVERSIONS
52 #endif
53
54 #include <linux/kernel.h>       /* printk */
55 #include <linux/module.h>
56
57 #include <linux/init.h>         /* module_init, module_exit         */
58 #include <linux/types.h>        /* pic_t, size_t, __u32, etc        */
59 #include <linux/errno.h>        /* error codes                      */
60 #include <linux/list.h>         /* circular linked list             */
61 #include <linux/stddef.h>       /* NULL, offsetof                   */
62 #include <linux/wait.h>         /* wait queues                      */
63
64 #include <linux/slab.h>         /* kmalloc, kfree, etc              */
65 #include <linux/vmalloc.h>      /* vmalloc, vfree, etc              */
66
67 #include <linux/poll.h>         /* poll_wait                        */
68 #include <linux/delay.h>        /* mdelay, udelay                   */
69 #include <asm/msr.h>            /* rdtsc rdtscl                     */
70
71 #include <linux/sched.h>        /* suser(), capable() replacement
72                                    for_each_task, for_each_process  */
73 #ifdef for_each_process
74 #define XGI_SCAN_PROCESS(p) for_each_process(p)
75 #else
76 #define XGI_SCAN_PROCESS(p) for_each_task(p)
77 #endif
78
79 #include <linux/moduleparam.h>  /* module_param()                   */
80 #include <linux/smp_lock.h>     /* kernel_locked                    */
81 #include <asm/tlbflush.h>       /* flush_tlb(), flush_tlb_all()     */
82 #include <asm/kmap_types.h>     /* page table entry lookup          */
83
84 #include <linux/pci.h>          /* pci_find_class, etc              */
85 #include <linux/interrupt.h>    /* tasklets, interrupt helpers      */
86 #include <linux/timer.h>
87
88 #include <asm/system.h>         /* cli, sli, save_flags             */
89 #include <asm/io.h>             /* ioremap, virt_to_phys            */
90 #include <asm/uaccess.h>        /* access_ok                        */
91 #include <asm/page.h>           /* PAGE_OFFSET                      */
92 #include <asm/pgtable.h>        /* pte bit definitions              */
93
94 #include <linux/spinlock.h>
95 #include <asm/semaphore.h>
96 #include <linux/highmem.h>
97
98 #ifdef CONFIG_PROC_FS
99 #include <linux/proc_fs.h>
100 #endif
101
102 #ifdef CONFIG_DEVFS_FS
103 #include <linux/devfs_fs_kernel.h>
104 #endif
105
106 #ifdef CONFIG_KMOD
107 #include <linux/kmod.h>
108 #endif
109
110 #ifdef CONFIG_PM
111 #include <linux/pm.h>
112 #endif
113
114 #ifdef CONFIG_MTRR
115 #include <asm/mtrr.h>
116 #endif
117
118 #ifdef CONFIG_KDB
119 #include <linux/kdb.h>
120 #include <asm/kdb.h>
121 #endif
122
123 #if defined (CONFIG_AGP) || defined (CONFIG_AGP_MODULE)
124 #define AGPGART
125 #include <linux/agp_backend.h>
126 #include <linux/agpgart.h>
127 #endif
128
129 #ifndef MAX_ORDER
130 #define MAX_ORDER 11
131 #endif
132
133 #ifndef module_init
134 #define module_init(x)  int init_module(void) { return x(); }
135 #define module_exit(x)  void cleanup_module(void) { x(); }
136 #endif
137
138 #ifndef minor
139 #define minor(x) MINOR(x)
140 #endif
141
142 #ifndef IRQ_HANDLED
143 typedef void irqreturn_t;
144 #define IRQ_NONE
145 #define IRQ_HANDLED
146 #define IRQ_RETVAL(x)
147 #endif
148
149 #if !defined (list_for_each)
150 #define list_for_each(pos, head) \
151     for (pos = (head)->next, prefetch(pos->next); pos != (head); \
152          pos = pos->next, prefetch(pos->next))
153 #endif
154
155 extern struct list_head pci_devices;    /* list of all devices */
156 #define XGI_PCI_FOR_EACH_DEV(dev) \
157     for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next))
158
159 /*
160  * the following macro causes problems when used in the same module
161  * as module_param(); undef it so we don't accidentally mix the two
162  */
163 #undef  MODULE_PARM
164
165 #ifdef EXPORT_NO_SYMBOLS
166 EXPORT_NO_SYMBOLS;
167 #endif
168
169 #define XGI_IS_SUSER()                 capable(CAP_SYS_ADMIN)
170 #define XGI_PCI_DEVICE_NAME(dev)       ((dev)->pretty_name)
171 #define XGI_NUM_CPUS()                 num_online_cpus()
172 #define XGI_CLI()                      local_irq_disable()
173 #define XGI_SAVE_FLAGS(eflags)         local_save_flags(eflags)
174 #define XGI_RESTORE_FLAGS(eflags)      local_irq_restore(eflags)
175 #define XGI_MAY_SLEEP()                (!in_interrupt() && !in_atomic())
176 #define XGI_MODULE_PARAMETER(x)        module_param(x, int, 0)
177
178
179 #define XGI_PCI_DISABLE_DEVICE(dev)      pci_disable_device(dev)
180
181 /* common defines */
182 #define GET_MODULE_SYMBOL(mod,sym)    (const void *) inter_module_get(sym)
183 #define PUT_MODULE_SYMBOL(sym)        inter_module_put((char *) sym)
184
185 #define XGI_GET_PAGE_STRUCT(phys_page) virt_to_page(__va(phys_page))
186 #define XGI_VMA_OFFSET(vma)            (((vma)->vm_pgoff) << PAGE_SHIFT)
187 #define XGI_VMA_PRIVATE(vma)           ((vma)->vm_private_data)
188
189 #define XGI_DEVICE_NUMBER(x)           minor((x)->i_rdev)
190 #define XGI_IS_CONTROL_DEVICE(x)       (minor((x)->i_rdev) == 255)
191
192 #define XGI_PCI_RESOURCE_START(dev, bar) ((dev)->resource[bar].start)
193 #define XGI_PCI_RESOURCE_SIZE(dev, bar)  ((dev)->resource[bar].end - (dev)->resource[bar].start + 1)
194
195 #define XGI_PCI_BUS_NUMBER(dev)        (dev)->bus->number
196 #define XGI_PCI_SLOT_NUMBER(dev)       PCI_SLOT((dev)->devfn)
197
198 #define XGI_PCI_GET_CLASS_PRESENT
199 #ifdef XGI_PCI_GET_CLASS_PRESENT
200 #define XGI_PCI_DEV_PUT(dev)                    pci_dev_put(dev)
201 #define XGI_PCI_GET_DEVICE(vendor,device,from)  pci_get_device(vendor,device,from)
202 #else
203 #define XGI_PCI_DEV_PUT(dev)
204 #define XGI_PCI_GET_DEVICE(vendor,device,from)  pci_find_device(vendor,device,from)
205 #endif
206
207 /*
208  * acpi support has been back-ported to the 2.4 kernel, but the 2.4 driver
209  * model is not sufficient for full acpi support. it may work in some cases,
210  * but not enough for us to officially support this configuration.
211  */
212 #if defined(CONFIG_ACPI)
213 #define XGI_PM_SUPPORT_ACPI
214 #endif
215
216 #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
217 #define XGI_PM_SUPPORT_APM
218 #endif
219
220 #if defined(CONFIG_DEVFS_FS)
221 typedef void *devfs_handle_t;
222 #define XGI_DEVFS_REGISTER(_name, _minor) \
223     ({ \
224         devfs_handle_t __handle = NULL; \
225         if (devfs_mk_cdev(MKDEV(XGI_DEV_MAJOR, _minor), \
226                           S_IFCHR | S_IRUGO | S_IWUGO, _name) == 0) \
227         { \
228             __handle = (void *) 1; /* XXX Fix me! (boolean) */ \
229         } \
230         __handle; \
231     })
232 /*
233 #define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi%d", i)
234 */
235 #define XGI_DEVFS_REMOVE_CONTROL() devfs_remove("xgi_ctl")
236 #define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi")
237 #endif                          /* defined(CONFIG_DEVFS_FS) */
238
239 #define XGI_REGISTER_CHRDEV(x...)    register_chrdev(x)
240 #define XGI_UNREGISTER_CHRDEV(x...)  unregister_chrdev(x)
241
242 #if defined(XGI_REMAP_PFN_RANGE_PRESENT)
243 #define XGI_REMAP_PAGE_RANGE(from, offset, x...) \
244     remap_pfn_range(vma, from, ((offset) >> PAGE_SHIFT), x)
245 #elif defined(XGI_REMAP_PAGE_RANGE_5)
246 #define XGI_REMAP_PAGE_RANGE(x...)      remap_page_range(vma, x)
247 #elif defined(XGI_REMAP_PAGE_RANGE_4)
248 #define XGI_REMAP_PAGE_RANGE(x...)      remap_page_range(x)
249 #else
250 #warning "xgi_configure.sh failed, assuming remap_page_range(5)!"
251 #define XGI_REMAP_PAGE_RANGE(x...)      remap_page_range(vma, x)
252 #endif
253
254 #if defined(pmd_offset_map)
255 #define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \
256     { \
257         pg_mid_dir = pmd_offset_map(pg_dir, address); \
258     }
259 #define XGI_PMD_UNMAP(pg_mid_dir) \
260     { \
261         pmd_unmap(pg_mid_dir); \
262     }
263 #else
264 #define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \
265     { \
266         pg_mid_dir = pmd_offset(pg_dir, address); \
267     }
268 #define XGI_PMD_UNMAP(pg_mid_dir)
269 #endif
270
271 #define XGI_PMD_PRESENT(pg_mid_dir) \
272     ({ \
273         if ((pg_mid_dir) && (pmd_none(*pg_mid_dir))) \
274         { \
275             XGI_PMD_UNMAP(pg_mid_dir); \
276             pg_mid_dir = NULL; \
277         } \
278         pg_mid_dir != NULL; \
279     })
280
281 #if defined(pte_offset_atomic)
282 #define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \
283     { \
284         pte = pte_offset_atomic(pg_mid_dir, address); \
285         XGI_PMD_UNMAP(pg_mid_dir); \
286     }
287 #define XGI_PTE_UNMAP(pte) \
288     { \
289         pte_kunmap(pte); \
290     }
291 #elif defined(pte_offset)
292 #define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \
293     { \
294         pte = pte_offset(pg_mid_dir, address); \
295         XGI_PMD_UNMAP(pg_mid_dir); \
296     }
297 #define XGI_PTE_UNMAP(pte)
298 #else
299 #define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \
300     { \
301         pte = pte_offset_map(pg_mid_dir, address); \
302         XGI_PMD_UNMAP(pg_mid_dir); \
303     }
304 #define XGI_PTE_UNMAP(pte) \
305     { \
306         pte_unmap(pte); \
307     }
308 #endif
309
310 #define XGI_PTE_PRESENT(pte) \
311     ({ \
312         if (pte) \
313         { \
314             if (!pte_present(*pte)) \
315             { \
316                 XGI_PTE_UNMAP(pte); pte = NULL; \
317             } \
318         } \
319         pte != NULL; \
320     })
321
322 #define XGI_PTE_VALUE(pte) \
323     ({ \
324         unsigned long __pte_value = pte_val(*pte); \
325         XGI_PTE_UNMAP(pte); \
326         __pte_value; \
327     })
328
329 #define XGI_PAGE_ALIGN(addr)             (((addr) + PAGE_SIZE - 1) / PAGE_SIZE)
330 #define XGI_MASK_OFFSET(addr)            ((addr) & (PAGE_SIZE - 1))
331
332 #if !defined (pgprot_noncached)
333 static inline pgprot_t pgprot_noncached(pgprot_t old_prot)
334 {
335         pgprot_t new_prot = old_prot;
336         if (boot_cpu_data.x86 > 3)
337                 new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_PCD);
338         return new_prot;
339 }
340 #endif
341
342 #if defined(XGI_BUILD_XGI_PAT_SUPPORT) && !defined (pgprot_writecombined)
343 /* Added define for write combining page, only valid if pat enabled. */
344 #define _PAGE_WRTCOMB _PAGE_PWT
345 #define __PAGE_KERNEL_WRTCOMB \
346     (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_WRTCOMB | _PAGE_ACCESSED)
347 #define PAGE_KERNEL_WRTCOMB MAKE_GLOBAL(__PAGE_KERNEL_WRTCOMB)
348
349 static inline pgprot_t pgprot_writecombined(pgprot_t old_prot)
350 {
351         pgprot_t new_prot = old_prot;
352         if (boot_cpu_data.x86 > 3) {
353                 pgprot_val(old_prot) &= ~(_PAGE_PCD | _PAGE_PWT);
354                 new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_WRTCOMB);
355         }
356         return new_prot;
357 }
358 #endif
359
360 #if !defined(page_to_pfn)
361 #define page_to_pfn(page)  ((page) - mem_map)
362 #endif
363
364 #define XGI_VMALLOC(ptr, size) \
365     { \
366         (ptr) = vmalloc_32(size); \
367     }
368
369 #define XGI_VFREE(ptr, size) \
370     { \
371         vfree((void *) (ptr)); \
372     }
373
374 #define XGI_IOREMAP(ptr, physaddr, size) \
375     { \
376         (ptr) = ioremap(physaddr, size); \
377     }
378
379 #define XGI_IOREMAP_NOCACHE(ptr, physaddr, size) \
380     { \
381         (ptr) = ioremap_nocache(physaddr, size); \
382     }
383
384 #define XGI_IOUNMAP(ptr, size) \
385     { \
386         iounmap(ptr); \
387     }
388
389 /*
390  * only use this because GFP_KERNEL may sleep..
391  * GFP_ATOMIC is ok, it won't sleep
392  */
393 #define XGI_KMALLOC(ptr, size) \
394     { \
395         (ptr) = kmalloc(size, GFP_KERNEL); \
396     }
397
398 #define XGI_KMALLOC_ATOMIC(ptr, size) \
399     { \
400         (ptr) = kmalloc(size, GFP_ATOMIC); \
401     }
402
403 #define XGI_KFREE(ptr, size) \
404     { \
405         kfree((void *) (ptr)); \
406     }
407
408 #define XGI_GET_FREE_PAGES(ptr, order) \
409     { \
410         (ptr) = __get_free_pages(GFP_KERNEL, order); \
411     }
412
413 #define XGI_FREE_PAGES(ptr, order) \
414     { \
415         free_pages(ptr, order); \
416     }
417
418 typedef struct xgi_pte_s {
419         unsigned long phys_addr;
420         unsigned long virt_addr;
421 } xgi_pte_t;
422
423 /*
424  * AMD Athlon processors expose a subtle bug in the Linux
425  * kernel, that may lead to AGP memory corruption. Recent
426  * kernel versions had a workaround for this problem, but
427  * 2.4.20 is the first kernel to address it properly. The
428  * page_attr API provides the means to solve the problem.
429  */
430 static inline void XGI_SET_PAGE_ATTRIB_UNCACHED(xgi_pte_t * page_ptr)
431 {
432         struct page *page = virt_to_page(__va(page_ptr->phys_addr));
433         change_page_attr(page, 1, PAGE_KERNEL_NOCACHE);
434 }
435 static inline void XGI_SET_PAGE_ATTRIB_CACHED(xgi_pte_t * page_ptr)
436 {
437         struct page *page = virt_to_page(__va(page_ptr->phys_addr));
438         change_page_attr(page, 1, PAGE_KERNEL);
439 }
440
441 /* add for SUSE 9, Jill*/
442 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 4)
443 #define XGI_INC_PAGE_COUNT(page)    atomic_inc(&(page)->count)
444 #define XGI_DEC_PAGE_COUNT(page)    atomic_dec(&(page)->count)
445 #define XGI_PAGE_COUNT(page)            atomic_read(&(page)->count)
446 #define XGI_SET_PAGE_COUNT(page,v)      atomic_set(&(page)->count, v)
447 #else
448 #define XGI_INC_PAGE_COUNT(page)    atomic_inc(&(page)->_count)
449 #define XGI_DEC_PAGE_COUNT(page)    atomic_dec(&(page)->_count)
450 #define XGI_PAGE_COUNT(page)            atomic_read(&(page)->_count)
451 #define XGI_SET_PAGE_COUNT(page,v)      atomic_set(&(page)->_count, v)
452 #endif
453 #define XGILockPage(page)           SetPageLocked(page)
454 #define XGIUnlockPage(page)         ClearPageLocked(page)
455
456 /*
457  * hide a pointer to struct xgi_info_t in a file-private info
458  */
459
460 typedef struct {
461         void *info;
462         U32 num_events;
463         spinlock_t fp_lock;
464         wait_queue_head_t wait_queue;
465 } xgi_file_private_t;
466
467 #define FILE_PRIVATE(filp)      ((filp)->private_data)
468
469 #define XGI_GET_FP(filp)        ((xgi_file_private_t *) FILE_PRIVATE(filp))
470
471 /* for the card devices */
472 #define XGI_INFO_FROM_FP(filp)  (XGI_GET_FP(filp)->info)
473
474 #define INODE_FROM_FP(filp) ((filp)->f_dentry->d_inode)
475
476 #define XGI_ATOMIC_SET(data,val)         atomic_set(&(data), (val))
477 #define XGI_ATOMIC_INC(data)             atomic_inc(&(data))
478 #define XGI_ATOMIC_DEC(data)             atomic_dec(&(data))
479 #define XGI_ATOMIC_DEC_AND_TEST(data)    atomic_dec_and_test(&(data))
480 #define XGI_ATOMIC_READ(data)            atomic_read(&(data))
481
482 /*
483  * lock-related functions that should only be called from this file
484  */
485 #define xgi_init_lock(lock)             spin_lock_init(&lock)
486 #define xgi_lock(lock)                  spin_lock(&lock)
487 #define xgi_unlock(lock)                spin_unlock(&lock)
488 #define xgi_down(lock)                  down(&lock)
489 #define xgi_up(lock)                    up(&lock)
490
491 #define xgi_lock_irqsave(lock,flags)    spin_lock_irqsave(&lock,flags)
492 #define xgi_unlock_irqsave(lock,flags)  spin_unlock_irqrestore(&lock,flags)
493
494 #endif