📄 rtai_hal.h
字号:
/** * @ingroup hal * @file * * ARTI -- RTAI-compatible Adeos-based Real-Time Interface. Based on * the original RTAI layer for x86. * * Original RTAI/x86 layer implementation: \n * Copyright © 2000 Paolo Mantegazza, \n * Copyright © 2000 Steve Papacharalambous, \n * Copyright © 2000 Stuart Hughes, \n * and others. * * RTAI/x86 rewrite over Adeos: \n * Copyright © 2002 Philippe Gerum. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, * USA; either version 2 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//** * @addtogroup hal *@{*/#ifndef _RTAI_ASM_I386_HAL_H#define _RTAI_ASM_I386_HAL_H#include <asm/rtai_vectors.h>#include <rtai_types.h>#ifdef CONFIG_SMP#define RTAI_NR_CPUS CONFIG_RTAI_CPUS#else /* !CONFIG_SMP */#define RTAI_NR_CPUS 1#endif /* CONFIG_SMP */static __inline__ unsigned long ffnz (unsigned long word) { /* Derived from bitops.h's ffs() */ __asm__("bsfl %1, %0" : "=r" (word) : "r" (word)); return word;}static inline unsigned long long rtai_ulldiv (unsigned long long ull, unsigned long uld, unsigned long *r) { /* * Fixed by Marco Morandini <morandini@aero.polimi.it> to work * with the -fnostrict-aliasing and -O2 combination using GCC * 3.x. */ unsigned long long qf, rf; unsigned long tq, rh; union { unsigned long long ull; unsigned long ul[2]; } p, q; p.ull = ull; q.ull = 0; rf = 0x100000000ULL - (qf = 0xFFFFFFFFUL / uld) * uld; while (p.ull >= uld) { q.ul[1] += (tq = p.ul[1] / uld); rh = p.ul[1] - tq * uld; q.ull += rh * qf + (tq = p.ul[0] / uld); p.ull = rh * rf + (p.ul[0] - tq * uld); } if (r) *r = p.ull; return q.ull;}static inline int rtai_imuldiv (int i, int mult, int div) { /* Returns (int)i = (int)i*(int)(mult)/(int)div. */ int dummy; __asm__ __volatile__ ( \ "mull %%edx\t\n" \ "div %%ecx\t\n" \ : "=a" (i), "=d" (dummy) : "a" (i), "d" (mult), "c" (div)); return i;}static inline long long rtai_llimd(long long ll, int mult, int div) { /* Returns (long long)ll = (int)ll*(int)(mult)/(int)div. */ __asm__ __volatile ( \ "movl %%edx,%%ecx\t\n" \ "mull %%esi\t\n" \ "movl %%eax,%%ebx\n\t" \ "movl %%ecx,%%eax\t\n" \ "movl %%edx,%%ecx\t\n" \ "mull %%esi\n\t" \ "addl %%ecx,%%eax\t\n" \ "adcl $0,%%edx\t\n" \ "divl %%edi\n\t" \ "movl %%eax,%%ecx\t\n" \ "movl %%ebx,%%eax\t\n" \ "divl %%edi\n\t" \ "sal $1,%%edx\t\n" \ "cmpl %%edx,%%edi\t\n" \ "movl %%ecx,%%edx\n\t" \ "jge 1f\t\n" \ "addl $1,%%eax\t\n" \ "adcl $0,%%edx\t\n" \ "1:\t\n" \ : "=A" (ll) \ : "A" (ll), "S" (mult), "D" (div) \ : "%ebx", "%ecx"); return ll;}/* * u64div32c.c is a helper function provided, 2003-03-03, by: * Copyright (C) 2003 Nils Hagge <hagge@rts.uni-hannover.de> */static inline unsigned long long rtai_u64div32c(unsigned long long a, unsigned long b, int *r) { __asm__ __volatile( "\n movl %%eax,%%ebx" "\n movl %%edx,%%eax" "\n xorl %%edx,%%edx" "\n divl %%ecx" "\n xchgl %%eax,%%ebx" "\n divl %%ecx" "\n movl %%edx,%%ecx" "\n movl %%ebx,%%edx" : "=a" (((unsigned long *)((void *)&a))[0]), "=d" (((unsigned long *)((void *)&a))[1]) : "a" (((unsigned long *)((void *)&a))[0]), "d" (((unsigned long *)((void *)&a))[1]), "c" (b) : "%ebx" ); return a;}#if defined(__KERNEL__) && !defined(__cplusplus)#include <linux/sched.h>#include <linux/interrupt.h>#include <asm/system.h>#include <asm/io.h>#include <asm/rtai_atomic.h>#include <asm/rtai_fpu.h>#ifdef __USE_APIC__#include <asm/fixmap.h>#include <asm/apic.h>#endif /* __USE_APIC__ */#include <rtai_trace.h>#define RTAI_DOMAIN_ID 0x52544149#define RTAI_NR_SRQS 32#define RTAI_SMP_NOTIFY_VECTOR RTAI_APIC1_VECTOR#define RTAI_SMP_NOTIFY_IPI RTAI_APIC1_IPI#define RTAI_APIC_TIMER_VECTOR RTAI_APIC2_VECTOR#define RTAI_APIC_TIMER_IPI RTAI_APIC2_IPI#define RTAI_TIMER_8254_IRQ 0#define RTAI_FREQ_8254 1193180#define RTAI_APIC_ICOUNT ((RTAI_FREQ_APIC + HZ/2)/HZ)#define RTAI_COUNTER_2_LATCH 0xfffe#define RTAI_LATENCY_8254 CONFIG_RTAI_SCHED_8254_LATENCY#define RTAI_SETUP_TIME_8254 2011 #define RTAI_CALIBRATED_APIC_FREQ 0#define RTAI_FREQ_APIC (rtai_tunables.apic_freq)#define RTAI_LATENCY_APIC CONFIG_RTAI_SCHED_APIC_LATENCY#define RTAI_SETUP_TIME_APIC 1000#define RTAI_TIME_LIMIT 0x7FFFFFFFFFFFFFFFLL#define RTAI_IFLAG 9#define rtai_cli() adeos_stall_pipeline_from(&rtai_domain)#define rtai_sti() adeos_unstall_pipeline_from(&rtai_domain)#define rtai_local_irq_save(x) ((x) = adeos_test_and_stall_pipeline_from(&rtai_domain))#define rtai_local_irq_restore(x) adeos_restore_pipeline_from(&rtai_domain,(x))#define rtai_local_irq_flags(x) ((x) = adeos_test_pipeline_from(&rtai_domain))#define rtai_local_irq_test() adeos_test_pipeline_from(&rtai_domain)#define rtai_get_iflag_and_cli() ((!adeos_test_and_stall_pipeline_from(&rtai_domain)) << RTAI_IFLAG)/* Use these ones when fiddling with the (local A)PIC */#define rtai_hw_lock(flags) adeos_hw_local_irq_save(flags)#define rtai_hw_unlock(flags) adeos_hw_local_irq_restore(flags)#define rtai_hw_enable() adeos_hw_sti()#define rtai_hw_disable() adeos_hw_cli()#define rtai_linux_sti() adeos_unstall_pipeline_from(adp_root)#define rtai_linux_cli() adeos_stall_pipeline_from(adp_root)#define rtai_linux_local_irq_save(x) ((x) = adeos_test_and_stall_pipeline_from(adp_root))#define rtai_linux_local_irq_restore(x) adeos_restore_pipeline_from(adp_root,x)#define rtai_linux_local_irq_restore_nosync(x,cpuid) adeos_restore_pipeline_nosync(adp_root,x,cpuid)typedef void (*rt_irq_handler_t)(unsigned irq, void *cookie);/* Bits from rtai_status. */#define RTAI_USE_APIC 0#ifdef CONFIG_X86_TSC#define RTAI_CALIBRATED_CPU_FREQ 0#define RTAI_CPU_FREQ (rtai_tunables.cpu_freq)static inline unsigned long long rtai_rdtsc (void) { unsigned long long t; __asm__ __volatile__( "rdtsc" : "=A" (t)); return t;}#else /* !CONFIG_X86_TSC */#define RTAI_CPU_FREQ RTAI_FREQ_8254#define RTAI_CALIBRATED_CPU_FREQ RTAI_FREQ_8254#define rtai_rdtsc() rd_8254_ts()#endif /* CONFIG_X86_TSC */struct calibration_data { unsigned long cpu_freq; unsigned long apic_freq; int latency; int setup_time_TIMER_CPUNIT; int setup_time_TIMER_UNIT; int timers_tol[RTAI_NR_CPUS];};struct apic_timer_setup_data { int mode; int count;};extern struct rt_times rt_times;extern struct rt_times rt_smp_times[RTAI_NR_CPUS];extern struct calibration_data rtai_tunables;extern volatile unsigned long rtai_status;extern volatile unsigned long rtai_cpu_realtime;extern volatile unsigned long rtai_cpu_lock;extern volatile unsigned long rtai_cpu_lxrt;extern struct rtai_switch_data { struct task_struct *oldtask; unsigned long oldflags;} rtai_linux_context[RTAI_NR_CPUS];extern adomain_t rtai_domain;extern int rtai_adeos_ptdbase;/* rtai_get_current() is Adeos-specific. Since real-time interrupt handlers are called on behalf of the RTAI domain stack, we cannot infere the "current" Linux task address using %esp. We must use the suspended Linux domain's stack pointer instead. */static inline struct task_struct *rtai_get_root_current (int cpuid) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) return (struct task_struct *)(((u_long)adp_root->esp[cpuid]) & (~8191UL));#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */ return ((struct thread_info *)(((u_long)adp_root->esp[cpuid]) & (~8191UL)))->task;#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */}static inline struct task_struct *rtai_get_current (int cpuid){ int *esp; __asm__ volatile("movl %%esp, %0" : "=r" (esp)); if (esp >= rtai_domain.estackbase[cpuid] && esp < rtai_domain.estackbase[cpuid] + 2048) return rtai_get_root_current(cpuid); return get_current();}#define rt_spin_lock(lock) spin_lock(lock)#define rt_spin_unlock(lock) spin_unlock(lock)static inline void rt_spin_lock_irq(spinlock_t *lock) { rtai_cli(); rt_spin_lock(lock);}static inline void rt_spin_unlock_irq(spinlock_t *lock) { rt_spin_unlock(lock); rtai_sti();}static inline unsigned long rt_spin_lock_irqsave(spinlock_t *lock) { unsigned long flags; rtai_local_irq_save(flags); rt_spin_lock(lock); return flags;}static inline void rt_spin_unlock_irqrestore(unsigned long flags, spinlock_t *lock) { rt_spin_unlock(lock); rtai_local_irq_restore(flags);}#ifdef CONFIG_SMP#define CPU_RELAX(x) \do { \ int i = 0; \ do \ cpu_relax(); \ while (++i < x); \} while(0)#else /* !CONFIG_SMP */#define CPU_RELAX(x)#endif /* CONFIG_SMP */irqreturn_t rtai_broadcast_to_local_timers(int irq, void *dev_id, struct pt_regs *regs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -