阅读:975回复:0
linux下的fiq申请
#define FIQ_VECTOR (vectors_base() + 0x1c)
static unsigned long no_fiq_insn; #ifdef CONFIG_CPU_32 static inline void unprotect_page_0(void) { modify_domain(DOMAIN_USER, DOMAIN_MANAGER); } static inline void protect_page_0(void) { modify_domain(DOMAIN_USER, DOMAIN_CLIENT); } #else #define unprotect_page_0() #define protect_page_0() #endif /* Default reacquire function * - we always relinquish FIQ control * - we always reacquire FIQ control */ static int fiq_def_op(void *ref, int relinquish) { if (!relinquish) { unprotect_page_0(); *(unsigned long *)FIQ_VECTOR = no_fiq_insn; protect_page_0(); flush_icache_range(FIQ_VECTOR, FIQ_VECTOR + 4); } return 0; } static struct fiq_handler default_owner = { name: \"default\", fiq_op: fiq_def_op, }; static struct fiq_handler *current_fiq = &default_owner; int get_fiq_list(char *buf) { char *p = buf; if (current_fiq != &default_owner) p += sprintf(p, \"FIQ: %s\\n\", current_fiq->name); return p - buf; } void set_fiq_handler(void *start, unsigned int length) { unprotect_page_0(); memcpy((void *)FIQ_VECTOR, start, length); protect_page_0(); flush_icache_range(FIQ_VECTOR, FIQ_VECTOR + length); } /* * Taking an interrupt in FIQ mode is death, so both these functions * disable irqs for the duration. */ void set_fiq_regs(struct pt_regs *regs) { register unsigned long tmp, tmp2; __asm__ volatile ( #ifdef CONFIG_CPU_26 \"mov %0, pc bic %1, %0, #0x3 orr %1, %1, %3 teqp %1, #0 @ select FIQ mode mov r0, r0 ldmia %2, {r8 - r14} teqp %0, #0 @ return to SVC mode mov r0, r0\" #endif #ifdef CONFIG_CPU_32 \"mrs %0, cpsr mov %1, %3 msr cpsr_c, %1 @ select FIQ mode mov r0, r0 ldmia %2, {r8 - r14} msr cpsr_c, %0 @ return to SVC mode mov r0, r0\" #endif : \"=&r\" (tmp), \"=&r\" (tmp2) : \"r\" (®s->ARM_r8), \"I\" (I_BIT | F_BIT | FIQ_MODE) /* These registers aren\'t modified by the above code in a way visible to the compiler, but we mark them as clobbers anyway so that GCC won\'t put any of the input or output operands in them. */ : \"r8\", \"r9\", \"r10\", \"r11\", \"r12\", \"r13\", \"r14\"); } void get_fiq_regs(struct pt_regs *regs) { register unsigned long tmp, tmp2; __asm__ volatile ( #ifdef CONFIG_CPU_26 \"mov %0, pc bic %1, %0, #0x3 orr %1, %1, %3 teqp %1, #0 @ select FIQ mode mov r0, r0 stmia %2, {r8 - r14} teqp %0, #0 @ return to SVC mode mov r0, r0\" #endif #ifdef CONFIG_CPU_32 \"mrs %0, cpsr mov %1, %3 msr cpsr_c, %1 @ select FIQ mode mov r0, r0 stmia %2, {r8 - r14} msr cpsr_c, %0 @ return to SVC mode mov r0, r0\" #endif : \"=&r\" (tmp), \"=&r\" (tmp2) : \"r\" (®s->ARM_r8), \"I\" (I_BIT | F_BIT | FIQ_MODE) /* These registers aren\'t modified by the above code in a way visible to the compiler, but we mark them as clobbers anyway so that GCC won\'t put any of the input or output operands in them. */ : \"r8\", \"r9\", \"r10\", \"r11\", \"r12\", \"r13\", \"r14\"); } int claim_fiq(struct fiq_handler *f) { int ret = 0; if (current_fiq) { ret = -EBUSY; if (current_fiq->fiq_op != NULL) ret = current_fiq->fiq_op(current_fiq->dev_id, 1); } if (!ret) { f->next = current_fiq; current_fiq = f; } return ret; } void release_fiq(struct fiq_handler *f) { if (current_fiq != f) { printk(KERN_ERR \"%s FIQ trying to release %s FIQ\\n\", f->name, current_fiq->name); #ifdef CONFIG_DEBUG_ERRORS __backtrace(); #endif return; } do current_fiq = current_fiq->next; while (current_fiq->fiq_op(current_fiq->dev_id, 0)); } void enable_fiq(int fiq) { enable_irq(fiq + FIQ_START); } void disable_fiq(int fiq) { disable_irq(fiq + FIQ_START); } EXPORT_SYMBOL(set_fiq_handler); EXPORT_SYMBOL(set_fiq_regs); EXPORT_SYMBOL(get_fiq_regs); EXPORT_SYMBOL(claim_fiq); EXPORT_SYMBOL(release_fiq); EXPORT_SYMBOL(enable_fiq); EXPORT_SYMBOL(disable_fiq); void __init init_FIQ(void) { no_fiq_insn = *(unsigned long *)FIQ_VECTOR; set_fs(get_fs()); } 这是linux内核下的一个文件,和fiq的申请相关的 我现在想调用claim_fiq(struct fiq_handler *f) 但不知道这个f怎么定义 static struct fiq_handler default_owner = { name: \"default\", fiq_op: fiq_def_op, }; 我觉得第二想应该是一个中断处理函数fiqhander((int FIQ_NUM, void *dev_id, struct pt_regs *regs)(它的参数列表应该是这样的吧) 但这样的话,其参数列表肯定和fiq_def_op的参数列表不一致,这样在调用release_fiq时就出问题(这一句while (current_fiq->fiq_op(current_fiq->dev_id, 0));) 所以现在不知道应该怎么设置这个f 高手帮我分析一下吧!! |
|