00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#ifdef INCLUDED_BY_HAL_C
00021
00022
#include <linux/mc146818rtc.h>
00023
00024
00025
#define MIN_RTC_FREQ 2
00026
#define MAX_RTC_FREQ 8192
00027
#define RTC_FREQ MAX_RTC_FREQ
00028
00029
static void rt_broadcast_rtc_interrupt(
void)
00030 {
00031
#ifdef CONFIG_SMP
00032
apic_wait_icr_idle();
00033 apic_write_around(APIC_ICR, APIC_DM_FIXED | APIC_DEST_ALLINC | RTAI_APIC_TIMER_VECTOR | APIC_DEST_LOGICAL);
00034
#endif
00035
}
00036
00037
static void (*usr_rtc_handler)(
void);
00038
00039
#if CONFIG_RTAI_DONT_DISPATCH_CORE_IRQS // && defined(CONFIG_RTAI_RTC_FREQ) && CONFIG_RTAI_RTC_FREQ
00040
00041
int _rtai_rtc_timer_handler(
void)
00042 {
00043
unsigned long cpuid = rtai_cpuid();
00044 rt_switch_to_real_time(cpuid);
00045
RTAI_SCHED_ISR_LOCK();
00046
00047
rt_mask_and_ack_irq(RTC_IRQ);
00048 CMOS_READ(RTC_INTR_FLAGS);
00049
rt_enable_irq(RTC_IRQ);
00050 usr_rtc_handler();
00051
00052
RTAI_SCHED_ISR_UNLOCK();
00053 rt_switch_to_linux(cpuid);
00054
#if 1 //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00055
if (!test_bit(IPIPE_STALL_FLAG, &
hal_root_domain->cpudata[cpuid].status)) {
00056
rtai_sti();
00057 hal_fast_flush_pipeline(cpuid);
00058
#if defined(CONFIG_SMP) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,32)
00059
set_bit(IPIPE_STALL_FLAG, &
hal_root_domain->cpudata[cpuid].status);
00060
#endif
00061
return 1;
00062 }
00063
#endif
00064
return 0;
00065 }
00066
00067
void rtai_rtc_timer_handler (
void);
00068 __asm__ ( \
00069
"\n" __ALIGN_STR
"\n\t" \
00070 SYMBOL_NAME_STR(rtai_rtc_timer_handler)
":\n\t" \
00071
"pushl $-1\n\t" \
00072
"cld\n\t" \
00073
"pushl %es\n\t" \
00074
"pushl %ds\n\t" \
00075
"pushl %eax\n\t" \
00076
"pushl %ebp\n\t" \
00077
"pushl %edi\n\t" \
00078
"pushl %esi\n\t" \
00079
"pushl %edx\n\t" \
00080
"pushl %ecx\n\t" \
00081
"pushl %ebx\n\t" \
00082 __LXRT_GET_DATASEG(ecx) \
00083
"movl %ecx, %ds\n\t" \
00084
"movl %ecx, %es\n\t" \
00085
"call "SYMBOL_NAME_STR(_rtai_rtc_timer_handler)
"\n\t" \
00086
"testl %eax,%eax\n\t" \
00087
"jnz ret_from_intr\n\t" \
00088
"popl %ebx\n\t" \
00089
"popl %ecx\n\t" \
00090
"popl %edx\n\t" \
00091
"popl %esi\n\t" \
00092
"popl %edi\n\t" \
00093
"popl %ebp\n\t" \
00094
"popl %eax\n\t" \
00095
"popl %ds\n\t" \
00096
"popl %es\n\t" \
00097
"addl $4,%esp\n\t" \
00098
"iret");
00099
00100
static struct desc_struct rtai_rtc_timer_sysvec;
00101
00102
#endif
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
static void rtc_handler(
int irq,
int rtc_freq)
00113 {
00114
#ifdef TEST_RTC
00115
static int stp, cnt;
00116
if (++cnt == rtc_freq) {
00117
rt_printk(
"<> IRQ %d, %d: CNT %d <>\n", irq, ++stp, cnt);
00118 cnt = 0;
00119 }
00120
#endif
00121
CMOS_READ(RTC_INTR_FLAGS);
00122
rt_enable_irq(RTC_IRQ);
00123
if (usr_rtc_handler) {
00124 usr_rtc_handler();
00125 }
00126 }
00127
00128
int fusion_timer_running;
00129
#ifdef RTAI_TRIOSS
00130
static void fusion_rtc_handler(
void)
00131 {
00132
#ifdef CONFIG_X86_LOCAL_APIC
00133
#include <asm/apic.h>
00134
#include <mach_ipi.h>
00135
int cpuid;
00136
for (
cpuid = 0;
cpuid < num_online_cpus();
cpuid++) {
00137 hal_pend_domain_uncond(RTAI_APIC_TIMER_VECTOR, fusion_domain, cpuid);
00138 }
00139
#ifdef CONFIG_SMP
00140
send_IPI_allbutself(RESCHEDULE_VECTOR);
00141
#endif
00142
#else
00143
hal_pend_domain_uncond(RTAI_TIMER_8254_IRQ, fusion_domain, rtai_cpuid());
00144
#endif
00145
}
00146
EXPORT_SYMBOL(fusion_timer_running);
00147
#endif
00148
00149
void rt_request_rtc(
long rtc_freq,
void *handler)
00150 {
00151
int pwr2;
00152
00153
if (rtc_freq <= 0) {
00154 rtc_freq = RTC_FREQ;
00155 }
00156
if (rtc_freq > MAX_RTC_FREQ) {
00157 rtc_freq = MAX_RTC_FREQ;
00158 }
else if (rtc_freq < MIN_RTC_FREQ) {
00159 rtc_freq = MIN_RTC_FREQ;
00160 }
00161 pwr2 = 1;
00162
if (rtc_freq > MIN_RTC_FREQ) {
00163
while (rtc_freq > (1 << pwr2)) {
00164 pwr2++;
00165 }
00166
if (rtc_freq <= ((3*(1 << (pwr2 - 1)) + 1)>>1)) {
00167 pwr2--;
00168 }
00169 }
00170
00171
rt_disable_irq(RTC_IRQ);
00172
rt_release_irq(RTC_IRQ);
00173
rtai_cli();
00174 CMOS_WRITE(CMOS_READ(RTC_FREQ_SELECT), RTC_FREQ_SELECT);
00175 CMOS_WRITE(CMOS_READ(RTC_CONTROL), RTC_CONTROL);
00176 CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - pwr2), RTC_FREQ_SELECT);
00177 CMOS_WRITE((CMOS_READ(RTC_CONTROL) & 0x8F) | RTC_PIE, RTC_CONTROL);
00178
rtai_sti();
00179
#ifdef RTAI_TRIOSS
00180
usr_rtc_handler = fusion_rtc_handler;
00181
#else
00182
usr_rtc_handler =
handler ?
handler : rt_broadcast_rtc_interrupt;
00183
#endif
00184
SET_FUSION_TIMER_RUNNING();
00185
#ifdef TEST_RTC
00186
rt_printk(
"<%s>\n", fusion_timer_running ?
"FUSION TIMER RUNNING" :
"");
00187
#endif
00188
rt_request_irq(RTC_IRQ, (
void *)rtc_handler, (
void *)rtc_freq, 0);
00189 SET_INTR_GATE(ext_irq_vector(RTC_IRQ), rtai_rtc_timer_handler, rtai_rtc_timer_sysvec);
00190
rt_enable_irq(RTC_IRQ);
00191 CMOS_READ(RTC_INTR_FLAGS);
00192
return;
00193 }
00194
00195
void rt_release_rtc(
void)
00196 {
00197
rt_disable_irq(RTC_IRQ);
00198 usr_rtc_handler = NULL;
00199
CLEAR_FUSION_TIMER_RUNNING();
00200 RESET_INTR_GATE(ext_irq_vector(RTC_IRQ), rtai_rtc_timer_sysvec);
00201
rt_release_irq(RTC_IRQ);
00202
rtai_cli();
00203 CMOS_WRITE(CMOS_READ(RTC_FREQ_SELECT), RTC_FREQ_SELECT);
00204 CMOS_WRITE(CMOS_READ(RTC_CONTROL), RTC_CONTROL);
00205
rtai_sti();
00206
return;
00207 }
00208
00209
EXPORT_SYMBOL(rt_request_rtc);
00210
EXPORT_SYMBOL(rt_release_rtc);
00211
00212
#endif