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