jackadandy
驱动牛犊
驱动牛犊
  • 注册日期2004-03-04
  • 最后登录2016-01-09
  • 粉丝1
  • 关注1
  • 积分5分
  • 威望30点
  • 贡献值0点
  • 好评度19点
  • 原创分0分
  • 专家分0分
阅读:975回复:0

linux下的fiq申请

楼主#
更多 发布于:2004-06-02 08:51
#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\" (&regs->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\" (&regs->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
高手帮我分析一下吧!!
游客

返回顶部