aboutsummaryrefslogtreecommitdiff
path: root/linux-core/xgi_linux.h
blob: 465feb3cc2900f466026cc0f2fa61b4c1474b823 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494

/****************************************************************************
 * Copyright (C) 2003-2006 by XGI Technology, Taiwan.			
 *																			*
 * All Rights Reserved.														*
 *																			*
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the	
 * "Software"), to deal in the Software without restriction, including	
 * without limitation on the rights to use, copy, modify, merge,	
 * publish, distribute, sublicense, and/or sell copies of the Software,	
 * and to permit persons to whom the Software is furnished to do so,	
 * subject to the following conditions:					
 *																			*
 * The above copyright notice and this permission notice (including the	
 * next paragraph) shall be included in all copies or substantial	
 * portions of the Software.						
 *																			*
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,	
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF	
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND		
 * NON-INFRINGEMENT.  IN NO EVENT SHALL XGI AND/OR			
 * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,		
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,		
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER			
 * DEALINGS IN THE SOFTWARE.												
 ***************************************************************************/

#ifndef _XGI_LINUX_H_
#define _XGI_LINUX_H_

#ifndef LINUX_VERSION_CODE
#include <linux/version.h>
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
#   error "This driver does not support pre-2.6 kernels!"
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
#   define XGI_REMAP_PFN_RANGE_PRESENT
#else
#   define XGI_REMAP_PAGE_RANGE_5
#endif

#if defined (CONFIG_SMP) && !defined (__SMP__)
#define __SMP__
#endif

#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
#define MODVERSIONS
#endif

#include <linux/kernel.h>	/* printk */
#include <linux/module.h>

#include <linux/init.h>		/* module_init, module_exit         */
#include <linux/types.h>	/* pic_t, size_t, __u32, etc        */
#include <linux/errno.h>	/* error codes                      */
#include <linux/list.h>		/* circular linked list             */
#include <linux/stddef.h>	/* NULL, offsetof                   */
#include <linux/wait.h>		/* wait queues                      */

#include <linux/slab.h>		/* kmalloc, kfree, etc              */
#include <linux/vmalloc.h>	/* vmalloc, vfree, etc              */

#include <linux/poll.h>		/* poll_wait                        */
#include <linux/delay.h>	/* mdelay, udelay                   */
#include <asm/msr.h>		/* rdtsc rdtscl                     */

#include <linux/sched.h>	/* suser(), capable() replacement
				   for_each_task, for_each_process  */
#ifdef for_each_process
#define XGI_SCAN_PROCESS(p) for_each_process(p)
#else
#define XGI_SCAN_PROCESS(p) for_each_task(p)
#endif

#include <linux/moduleparam.h>	/* module_param()                   */
#include <linux/smp_lock.h>	/* kernel_locked                    */
#include <asm/tlbflush.h>	/* flush_tlb(), flush_tlb_all()     */
#include <asm/kmap_types.h>	/* page table entry lookup          */

#include <linux/pci.h>		/* pci_find_class, etc              */
#include <linux/interrupt.h>	/* tasklets, interrupt helpers      */
#include <linux/timer.h>

#include <asm/system.h>		/* cli, sli, save_flags             */
#include <asm/io.h>		/* ioremap, virt_to_phys            */
#include <asm/uaccess.h>	/* access_ok                        */
#include <asm/page.h>		/* PAGE_OFFSET                      */
#include <asm/pgtable.h>	/* pte bit definitions              */

#include <linux/spinlock.h>
#include <asm/semaphore.h>
#include <linux/highmem.h>

#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
#endif

#ifdef CONFIG_DEVFS_FS
#include <linux/devfs_fs_kernel.h>
#endif

#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif

#ifdef CONFIG_PM
#include <linux/pm.h>
#endif

#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif

#ifdef CONFIG_KDB
#include <linux/kdb.h>
#include <asm/kdb.h>
#endif

#if defined (CONFIG_AGP) || defined (CONFIG_AGP_MODULE)
#define AGPGART
#include <linux/agp_backend.h>
#include <linux/agpgart.h>
#endif

#ifndef MAX_ORDER
#define MAX_ORDER 11
#endif

#ifndef module_init
#define module_init(x)  int init_module(void) { return x(); }
#define module_exit(x)  void cleanup_module(void) { x(); }
#endif

#ifndef minor
#define minor(x) MINOR(x)
#endif

#ifndef IRQ_HANDLED
typedef void irqreturn_t;
#define IRQ_NONE
#define IRQ_HANDLED
#define IRQ_RETVAL(x)
#endif

#if !defined (list_for_each)
#define list_for_each(pos, head) \
    for (pos = (head)->next, prefetch(pos->next); pos != (head); \
         pos = pos->next, prefetch(pos->next))
#endif

extern struct list_head pci_devices;	/* list of all devices */
#define XGI_PCI_FOR_EACH_DEV(dev) \
    for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next))

/*
 * the following macro causes problems when used in the same module
 * as module_param(); undef it so we don't accidentally mix the two
 */
#undef  MODULE_PARM

#ifdef EXPORT_NO_SYMBOLS
EXPORT_NO_SYMBOLS;
#endif

#define XGI_IS_SUSER()                 capable(CAP_SYS_ADMIN)
#define XGI_PCI_DEVICE_NAME(dev)       ((dev)->pretty_name)
#define XGI_NUM_CPUS()                 num_online_cpus()
#define XGI_CLI()                      local_irq_disable()
#define XGI_SAVE_FLAGS(eflags)         local_save_flags(eflags)
#define XGI_RESTORE_FLAGS(eflags)      local_irq_restore(eflags)
#define XGI_MAY_SLEEP()                (!in_interrupt() && !in_atomic())
#define XGI_MODULE_PARAMETER(x)        module_param(x, int, 0)


#define XGI_PCI_DISABLE_DEVICE(dev)      pci_disable_device(dev)

/* common defines */
#define GET_MODULE_SYMBOL(mod,sym)    (const void *) inter_module_get(sym)
#define PUT_MODULE_SYMBOL(sym)        inter_module_put((char *) sym)

#define XGI_GET_PAGE_STRUCT(phys_page) virt_to_page(__va(phys_page))
#define XGI_VMA_OFFSET(vma)            (((vma)->vm_pgoff) << PAGE_SHIFT)
#define XGI_VMA_PRIVATE(vma)           ((vma)->vm_private_data)

#define XGI_DEVICE_NUMBER(x)           minor((x)->i_rdev)
#define XGI_IS_CONTROL_DEVICE(x)       (minor((x)->i_rdev) == 255)

#define XGI_PCI_RESOURCE_START(dev, bar) ((dev)->resource[bar].start)
#define XGI_PCI_RESOURCE_SIZE(dev, bar)  ((dev)->resource[bar].end - (dev)->resource[bar].start + 1)

#define XGI_PCI_BUS_NUMBER(dev)        (dev)->bus->number
#define XGI_PCI_SLOT_NUMBER(dev)       PCI_SLOT((dev)->devfn)

#define XGI_PCI_GET_CLASS_PRESENT
#ifdef XGI_PCI_GET_CLASS_PRESENT
#define XGI_PCI_DEV_PUT(dev)                    pci_dev_put(dev)
#define XGI_PCI_GET_DEVICE(vendor,device,from)  pci_get_device(vendor,device,from)
#else
#define XGI_PCI_DEV_PUT(dev)
#define XGI_PCI_GET_DEVICE(vendor,device,from)  pci_find_device(vendor,device,from)
#endif

/*
 * acpi support has been back-ported to the 2.4 kernel, but the 2.4 driver
 * model is not sufficient for full acpi support. it may work in some cases,
 * but not enough for us to officially support this configuration.
 */
#if defined(CONFIG_ACPI)
#define XGI_PM_SUPPORT_ACPI
#endif

#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
#define XGI_PM_SUPPORT_APM
#endif

#if defined(CONFIG_DEVFS_FS)
typedef void *devfs_handle_t;
#define XGI_DEVFS_REGISTER(_name, _minor) \
    ({ \
        devfs_handle_t __handle = NULL; \
        if (devfs_mk_cdev(MKDEV(XGI_DEV_MAJOR, _minor), \
                          S_IFCHR | S_IRUGO | S_IWUGO, _name) == 0) \
        { \
            __handle = (void *) 1; /* XXX Fix me! (boolean) */ \
        } \
        __handle; \
    })
/*
#define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi%d", i)
*/
#define XGI_DEVFS_REMOVE_CONTROL() devfs_remove("xgi_ctl")
#define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi")
#endif				/* defined(CONFIG_DEVFS_FS) */

#define XGI_REGISTER_CHRDEV(x...)    register_chrdev(x)
#define XGI_UNREGISTER_CHRDEV(x...)  unregister_chrdev(x)

#if defined(XGI_REMAP_PFN_RANGE_PRESENT)
#define XGI_REMAP_PAGE_RANGE(from, offset, x...) \
    remap_pfn_range(vma, from, ((offset) >> PAGE_SHIFT), x)
#elif defined(XGI_REMAP_PAGE_RANGE_5)
#define XGI_REMAP_PAGE_RANGE(x...)      remap_page_range(vma, x)
#elif defined(XGI_REMAP_PAGE_RANGE_4)
#define XGI_REMAP_PAGE_RANGE(x...)      remap_page_range(x)
#else
#warning "xgi_configure.sh failed, assuming remap_page_range(5)!"
#define XGI_REMAP_PAGE_RANGE(x...)      remap_page_range(vma, x)
#endif

#if defined(pmd_offset_map)
#define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \
    { \
        pg_mid_dir = pmd_offset_map(pg_dir, address); \
    }
#define XGI_PMD_UNMAP(pg_mid_dir) \
    { \
        pmd_unmap(pg_mid_dir); \
    }
#else
#define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \
    { \
        pg_mid_dir = pmd_offset(pg_dir, address); \
    }
#define XGI_PMD_UNMAP(pg_mid_dir)
#endif

#define XGI_PMD_PRESENT(pg_mid_dir) \
    ({ \
        if ((pg_mid_dir) && (pmd_none(*pg_mid_dir))) \
        { \
            XGI_PMD_UNMAP(pg_mid_dir); \
            pg_mid_dir = NULL; \
        } \
        pg_mid_dir != NULL; \
    })

#if defined(pte_offset_atomic)
#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \
    { \
        pte = pte_offset_atomic(pg_mid_dir, address); \
        XGI_PMD_UNMAP(pg_mid_dir); \
    }
#define XGI_PTE_UNMAP(pte) \
    { \
        pte_kunmap(pte); \
    }
#elif defined(pte_offset)
#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \
    { \
        pte = pte_offset(pg_mid_dir, address); \
        XGI_PMD_UNMAP(pg_mid_dir); \
    }
#define XGI_PTE_UNMAP(pte)
#else
#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \
    { \
        pte = pte_offset_map(pg_mid_dir, address); \
        XGI_PMD_UNMAP(pg_mid_dir); \
    }
#define XGI_PTE_UNMAP(pte) \
    { \
        pte_unmap(pte); \
    }
#endif

#define XGI_PTE_PRESENT(pte) \
    ({ \
        if (pte) \
        { \
            if (!pte_present(*pte)) \
            { \
                XGI_PTE_UNMAP(pte); pte = NULL; \
            } \
        } \
        pte != NULL; \
    })

#define XGI_PTE_VALUE(pte) \
    ({ \
        unsigned long __pte_value = pte_val(*pte); \
        XGI_PTE_UNMAP(pte); \
        __pte_value; \
    })

#define XGI_PAGE_ALIGN(addr)             (((addr) + PAGE_SIZE - 1) / PAGE_SIZE)
#define XGI_MASK_OFFSET(addr)            ((addr) & (PAGE_SIZE - 1))

#if !defined (pgprot_noncached)
static inline pgprot_t pgprot_noncached(pgprot_t old_prot)
{
	pgprot_t new_prot = old_prot;
	if (boot_cpu_data.x86 > 3)
		new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_PCD);
	return new_prot;
}
#endif

#if defined(XGI_BUILD_XGI_PAT_SUPPORT) && !defined (pgprot_writecombined)
/* Added define for write combining page, only valid if pat enabled. */
#define _PAGE_WRTCOMB _PAGE_PWT
#define __PAGE_KERNEL_WRTCOMB \
    (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_WRTCOMB | _PAGE_ACCESSED)
#define PAGE_KERNEL_WRTCOMB MAKE_GLOBAL(__PAGE_KERNEL_WRTCOMB)

static inline pgprot_t pgprot_writecombined(pgprot_t old_prot)
{
	pgprot_t new_prot = old_prot;
	if (boot_cpu_data.x86 > 3) {
		pgprot_val(old_prot) &= ~(_PAGE_PCD | _PAGE_PWT);
		new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_WRTCOMB);
	}
	return new_prot;
}
#endif

#if !defined(page_to_pfn)
#define page_to_pfn(page)  ((page) - mem_map)
#endif

#define XGI_VMALLOC(ptr, size) \
    { \
        (ptr) = vmalloc_32(size); \
    }

#define XGI_VFREE(ptr, size) \
    { \
        vfree((void *) (ptr)); \
    }

#define XGI_IOREMAP(ptr, physaddr, size) \
    { \
        (ptr) = ioremap(physaddr, size); \
    }

#define XGI_IOREMAP_NOCACHE(ptr, physaddr, size) \
    { \
        (ptr) = ioremap_nocache(physaddr, size); \
    }

#define XGI_IOUNMAP(ptr, size) \
    { \
        iounmap(ptr); \
    }

/*
 * only use this because GFP_KERNEL may sleep..
 * GFP_ATOMIC is ok, it won't sleep
 */
#define XGI_KMALLOC(ptr, size) \
    { \
        (ptr) = kmalloc(size, GFP_KERNEL); \
    }

#define XGI_KMALLOC_ATOMIC(ptr, size) \
    { \
        (ptr) = kmalloc(size, GFP_ATOMIC); \
    }

#define XGI_KFREE(ptr, size) \
    { \
        kfree((void *) (ptr)); \
    }

#define XGI_GET_FREE_PAGES(ptr, order) \
    { \
        (ptr) = __get_free_pages(GFP_KERNEL, order); \
    }

#define XGI_FREE_PAGES(ptr, order) \
    { \
        free_pages(ptr, order); \
    }

typedef struct xgi_pte_s {
	unsigned long phys_addr;
	unsigned long virt_addr;
} xgi_pte_t;

/*
 * AMD Athlon processors expose a subtle bug in the Linux
 * kernel, that may lead to AGP memory corruption. Recent
 * kernel versions had a workaround for this problem, but
 * 2.4.20 is the first kernel to address it properly. The
 * page_attr API provides the means to solve the problem.
 */
static inline void XGI_SET_PAGE_ATTRIB_UNCACHED(xgi_pte_t * page_ptr)
{
	struct page *page = virt_to_page(__va(page_ptr->phys_addr));
	change_page_attr(page, 1, PAGE_KERNEL_NOCACHE);
}
static inline void XGI_SET_PAGE_ATTRIB_CACHED(xgi_pte_t * page_ptr)
{
	struct page *page = virt_to_page(__va(page_ptr->phys_addr));
	change_page_attr(page, 1, PAGE_KERNEL);
}

/* add for SUSE 9, Jill*/
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 4)
#define XGI_INC_PAGE_COUNT(page)    atomic_inc(&(page)->count)
#define XGI_DEC_PAGE_COUNT(page)    atomic_dec(&(page)->count)
#define XGI_PAGE_COUNT(page)		atomic_read(&(page)->count)
#define XGI_SET_PAGE_COUNT(page,v) 	atomic_set(&(page)->count, v)
#else
#define XGI_INC_PAGE_COUNT(page)    atomic_inc(&(page)->_count)
#define XGI_DEC_PAGE_COUNT(page)    atomic_dec(&(page)->_count)
#define XGI_PAGE_COUNT(page)		atomic_read(&(page)->_count)
#define XGI_SET_PAGE_COUNT(page,v) 	atomic_set(&(page)->_count, v)
#endif
#define XGILockPage(page)           SetPageLocked(page)
#define XGIUnlockPage(page)         ClearPageLocked(page)

/*
 * hide a pointer to struct xgi_info_t in a file-private info
 */

typedef struct {
	void *info;
	U32 num_events;
	spinlock_t fp_lock;
	wait_queue_head_t wait_queue;
} xgi_file_private_t;

#define FILE_PRIVATE(filp)      ((filp)->private_data)

#define XGI_GET_FP(filp)        ((xgi_file_private_t *) FILE_PRIVATE(filp))

/* for the card devices */
#define XGI_INFO_FROM_FP(filp)  (XGI_GET_FP(filp)->info)

#define INODE_FROM_FP(filp) ((filp)->f_dentry->d_inode)

#define XGI_ATOMIC_SET(data,val)         atomic_set(&(data), (val))
#define XGI_ATOMIC_INC(data)             atomic_inc(&(data))
#define XGI_ATOMIC_DEC(data)             atomic_dec(&(data))
#define XGI_ATOMIC_DEC_AND_TEST(data)    atomic_dec_and_test(&(data))
#define XGI_ATOMIC_READ(data)            atomic_read(&(data))

/*
 * lock-related functions that should only be called from this file
 */
#define xgi_init_lock(lock)             spin_lock_init(&lock)
#define xgi_lock(lock)                  spin_lock(&lock)
#define xgi_unlock(lock)                spin_unlock(&lock)
#define xgi_down(lock)                  down(&lock)
#define xgi_up(lock)                    up(&lock)

#define xgi_lock_irqsave(lock,flags)    spin_lock_irqsave(&lock,flags)
#define xgi_unlock_irqsave(lock,flags)  spin_unlock_irqrestore(&lock,flags)

#endif