📄 kernelcalls.c
字号:
/*Copyright (C) 2003 Sigma Designs, Inc.This library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2.1 of the License, or (at your option) any later version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include <linux/kernel.h>#include <linux/module.h>#include <linux/version.h>#include <linux/mm.h>#include <linux/vmalloc.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/interrupt.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)#include <linux/devfs_fs_kernel.h>#endif#include <linux/poll.h>#include <asm/page.h>#include <asm/pgtable.h>/* the main chip ids */#define EM86XX_CHIPID_MAMBO 1000#define EM86XX_CHIPID_MAMBOLIGHT 2000#define EM86XX_CHIPID_TANGO 3000#define EM86XX_CHIPID_TANGOLIGHT 4000#define EM86XX_CHIPID_TANGO15 4500#define EM86XX_CHIPID_TANGO2 5000#define EM86XX_CHIPID_TANGO3 10000#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2)#include <asm/tango2/hardware.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)#include <asm/tango2/rmdefs.h>#endif#include <asm/delay.h>#define RMPanic(x)#include "../../../init_4ke/helpers_4ke_mipsel.h"#else#include <asm/hardware.h>#endif#include <asm/irq.h>#include "kernelcalls.h"#if 0#define kcinfo(x...) kc_printk(x)#else#define kcinfo(...)#endif/* The two following macros are from Solomon Peachy They should be present in future linux 2.4 kernels See also `going to sleep without races' (linux device drivers 2nd edition ch 9) */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)#define __wait_event_interruptible_timeout(wq, condition, ret) \do { \ wait_queue_t __wait; \ init_waitqueue_entry(&__wait, current); \ \ add_wait_queue(&wq, &__wait); \ for (;;) { \ set_current_state(TASK_INTERRUPTIBLE); \ if (condition) \ break; \ if (!signal_pending(current)) { \ if (ret) ret = schedule_timeout(ret); \ if (!ret) \ break; \ continue; \ } \ ret = -ERESTARTSYS; \ break; \ } \ set_current_state(TASK_RUNNING); \ remove_wait_queue(&wq, &__wait); \} while (0)#endif/** register a kernel module using devfs*/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)EXPORT_SYMBOL(kc_devfs_register);struct kc_devfs_handle_t *kc_devfs_register(struct kc_devfs_handle_t *dir, const char *name, unsigned int flags, unsigned int major, unsigned int minor, unsigned long mode, void *ops, void *info){ devfs_handle_t true_dir; devfs_handle_t *de; if (dir == NULL) true_dir = NULL; else true_dir = *(devfs_handle_t *) dir; de = (devfs_handle_t *) vmalloc(sizeof(devfs_handle_t)); *de = devfs_register(true_dir, name, flags, major, minor, (umode_t) mode, ops, info); if (*de == NULL) { vfree(de); de = (devfs_handle_t *) NULL; } return (struct kc_devfs_handle_t *) de;}/** unregister a kernel module using devfs*/EXPORT_SYMBOL(kc_devfs_unregister);void kc_devfs_unregister(struct kc_devfs_handle_t *de){ if (de != NULL) { devfs_unregister(*(devfs_handle_t *) de); vfree(de); }}#endif/** remap_page_range abstraction * ... */EXPORT_SYMBOL(kc_remap_page_range);int kc_remap_page_range(struct kc_vm_area_struct *kc_vma, unsigned long from, unsigned long to, unsigned long size,struct kc_pgprot_t *prot){ int ret = 0; struct vm_area_struct *vma = (struct vm_area_struct *)kc_vma; /* Disable caching of VMAs (position _CACHE_MASK and _CACHE_UNCACHED bits accordingly) see linux/include/asm/pgtable-32.h */ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)#ifdef REMAP_PAGE_RANGE_FIVE_ARGS ret = remap_page_range((struct vm_area_struct *) vma, from, to, size, *(pgprot_t *) prot);#else ret = remap_page_range(from, to, size, *(pgprot_t *) prot);#endif /* REMAP_PAGE_RANGE_FIVE_ARGS */#else /* linux-2.6.x always have five args */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ret = remap_page_range((struct vm_area_struct *) vma, from, to, size, *(pgprot_t *) prot);#else /* starting from linux-2.6.10 remap_page_range is deprecated to remap_pfn_range */ ret = remap_pfn_range((struct vm_area_struct *) vma, from, to >> PAGE_SHIFT, size, *(pgprot_t *) prot);#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) */#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */ return ret;}/** copy_from_user abstraction * ... */EXPORT_SYMBOL(kc_copy_from_user);unsigned long kc_copy_from_user(void *to, const void *from,unsigned long n){ memcpy(to,from,n); return 0;}/** copy_to_user abstraction * ... */EXPORT_SYMBOL(kc_copy_to_user);unsigned long kc_copy_to_user(void *to, const void *from, unsigned long n){ memcpy(to,from,n); return 0;}/** poll_wait * ... */EXPORT_SYMBOL(kc_poll_wait);void kc_poll_wait(void *filp, struct kc_wait_queue_head_t *q, void *wait){ poll_wait((struct file *) filp, (wait_queue_head_t *) q, (struct poll_table_struct *) wait);}/** printk abstraction * ... */EXPORT_SYMBOL(kc_printk);int kc_printk(const char *fmt, ...){#ifdef WITH_LOGGING char dest[1024]; /* hope it's enough */ int rc; va_list ap; va_start(ap, fmt); rc = vsprintf(dest, fmt, ap); va_end(ap); if (rc >= 0) rc = printk(dest); return rc;#else return 0;#endif /* WITH_LOGGING */}/** sprintf abstraction * ... */EXPORT_SYMBOL(kc_sprintf);int kc_sprintf(char * buf, const char * fmt, ...){ int rc; va_list ap; va_start(ap,fmt); rc=vsprintf(buf,fmt,ap); va_end(ap); return rc;}/** sscanf abstraction * ... */EXPORT_SYMBOL(kc_sscanf);int kc_sscanf(const char * buf, const char * fmt, ...){ va_list args; int i; va_start(args,fmt); i = vsscanf(buf,fmt,args); va_end(args); return i;}/** vmalloc abstraction * ... */EXPORT_SYMBOL(kc_vmalloc);void *kc_vmalloc(unsigned long size){ return (void *) vmalloc(size);}/** vfree abstraction * ... */EXPORT_SYMBOL(kc_vfree);void kc_vfree(void *addr){ vfree(addr);}//// spinlocks///** spin_lock_init abstraction * ... */EXPORT_SYMBOL(kc_spin_lock_init);void kc_spin_lock_init(struct kc_spinlock_t **lock){ spinlock_t *truelock; /* in some cases, spinlock_t is just an empty struct. So, do not try to allocate it (it will never be dereferenced of course) */ if (sizeof(spinlock_t) > 0) truelock = (spinlock_t *) vmalloc(sizeof(spinlock_t)); else truelock = (spinlock_t *) NULL; spin_lock_init(truelock); *lock = (struct kc_spinlock_t *) truelock;}/** spin_lock_deinit free the memory used by a spinlock * @param lock a pointer to a struct kc_spinlock_t to free */EXPORT_SYMBOL(kc_spin_lock_deinit);void kc_spin_lock_deinit(struct kc_spinlock_t *lock){ if (sizeof(spinlock_t) > 0) vfree(lock);}/** spin_lock abstraction * ... */EXPORT_SYMBOL(kc_spin_lock);void kc_spin_lock(struct kc_spinlock_t *lock){ spin_lock((spinlock_t *) lock);}/** spin_unlock abstraction * ... */EXPORT_SYMBOL(kc_spin_unlock);void kc_spin_unlock(struct kc_spinlock_t *lock){ spin_unlock((spinlock_t *) lock);}/** spin_lock_bh abstraction * ... */EXPORT_SYMBOL(kc_spin_lock_bh);void kc_spin_lock_bh(struct kc_spinlock_t *lock){ spin_lock_bh((spinlock_t *) lock);}/** spin_unlock_bh abstraction * ... */EXPORT_SYMBOL(kc_spin_unlock_bh);void kc_spin_unlock_bh(struct kc_spinlock_t *lock){ spin_unlock_bh((spinlock_t *) lock);}/** spin_lock_irq abstraction * ... */EXPORT_SYMBOL(kc_spin_lock_irq);void kc_spin_lock_irq(struct kc_spinlock_t *lock){ spin_lock_irq((spinlock_t *) lock);}/** spin_unlock_irq abstraction * ... */EXPORT_SYMBOL(kc_spin_unlock_irq);void kc_spin_unlock_irq(struct kc_spinlock_t *lock){ spin_unlock_irq((spinlock_t *) lock);}/** spin_lock_irqsave abstraction * ... */EXPORT_SYMBOL(kc_spin_lock_irqsave);void kc_spin_lock_irqsave(struct kc_spinlock_t *lock, unsigned long *flags){ /* ! this is a macro */ spin_lock_irqsave((spinlock_t *) lock, *flags);}/** spin_unlock_irqrestore abstraction * ... */EXPORT_SYMBOL(kc_spin_unlock_irqrestore);void kc_spin_unlock_irqrestore(struct kc_spinlock_t *lock, unsigned long flags){ spin_unlock_irqrestore((spinlock_t *) lock, flags);}//// semaphores///** semaphore_init abstraction * ... */EXPORT_SYMBOL(kc_semaphore_init);void kc_semaphore_init(struct kc_semaphore_t **sem, int val){ struct semaphore *truesem; truesem = (struct semaphore *) vmalloc(sizeof(struct semaphore)); sema_init(truesem, val); *sem = (struct kc_semaphore_t *) truesem;}/** semaphore_deinit abstraction * ... */EXPORT_SYMBOL(kc_semaphore_deinit);void kc_semaphore_deinit(struct kc_semaphore_t *sem){ vfree(sem);}/** down abstraction * ... */EXPORT_SYMBOL(kc_down);void kc_down(struct kc_semaphore_t *sem){ down((struct semaphore *)sem);}/** down_interruptible abstraction * ... */EXPORT_SYMBOL(kc_down_interruptible);int kc_down_interruptible(struct kc_semaphore_t *sem){ return down_interruptible((struct semaphore *)sem);}/** down_trylock abstraction * ... */EXPORT_SYMBOL(kc_down_trylock);int kc_down_trylock(struct kc_semaphore_t *sem){ return down_trylock((struct semaphore *)sem);}/** up abstraction * ... */EXPORT_SYMBOL(kc_up);void kc_up(struct kc_semaphore_t *sem){ up((struct semaphore *)sem);}//// wait queues// /** init_waitqueue_head abstraction * ... */EXPORT_SYMBOL(kc_init_waitqueue_head);void kc_init_waitqueue_head(struct kc_wait_queue_head_t **q){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -