[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re:[rtl] Astonished?
- To: rtl@rtlinux.org
- Subject: Re:[rtl] Astonished?
- From: Kulwinder Atwal <kalatwal@home.com>
- Date: Wed, 01 Mar 2000 07:34:00 -0700
- Organization: @Home Network Member
Also, the loop kernel_patch preceding the 'astonished' can be optimized
from:
+ for(i=0; i < MAX_FAKE_DEPTH;i++){
+ if(fake_regs[cpu_id][i].orig_eax)continue;
+ else{
+ r = &fake_regs[cpu_id][i];
+ r->orig_eax = -1;
+ break;}
+ }
+ if(!r)printk("RTL is astonished to announce out of fake regs\n");
+ return r;
to:
+ for(i=0; i < MAX_FAKE_DEPTH;i++){
+ if(fake_regs[cpu_id][i].orig_eax != 0)
+ {
+ r = &fake_regs[cpu_id][i];
+ r->orig_eax = -1;
+ break;
+ }
+ }
+ if(!r)printk("RTL is astonished to announce out of fake regs\n");
+ return r;
The != (not equal) will be translated into a single 'branch on not
equal' instruction in assembly.
It conditional 'friends' are:
<= less than or equal
>= greater than or equal
== equal
Cheers, Kal.
Index: linux22/Makefile
diff -u linux22/Makefile:1.1.1.4 linux22/Makefile:1.21
--- linux22/Makefile:1.1.1.4 Wed Jan 5 19:27:22 2000
+++ linux22/Makefile Fri Feb 11 20:02:22 2000
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 2
SUBLEVEL = 14
-EXTRAVERSION =
+EXTRAVERSION =-rtl2.2
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -95,6 +95,10 @@
ifdef CONFIG_SMP
CFLAGS += -D__SMP__
AFLAGS += -D__SMP__
+endif
+ifdef CONFIG_RTL
+CFLAGS += -D__RTL__
+AFLAGS += -D__RTL__
endif
#
Index: linux22/arch/i386/config.in
diff -u linux22/arch/i386/config.in:1.1.1.2 linux22/arch/i386/config.in:1.4
--- linux22/arch/i386/config.in:1.1.1.2 Wed Jan 5 19:30:15 2000
+++ linux22/arch/i386/config.in Wed Jan 5 23:57:16 2000
@@ -2,7 +2,9 @@
# For a description of the syntax of this configuration file,
# see the Configure script.
#
-mainmenu_name "Linux Kernel Configuration"
+mainmenu_name "RTLinux Kernel Configuration"
+#RTLinux is mandatory.
+define_bool CONFIG_RTL y
mainmenu_option next_comment
comment 'Code maturity level options'
Index: linux22/arch/i386/defconfig
diff -u linux22/arch/i386/defconfig:1.1.1.2 linux22/arch/i386/defconfig:1.2
--- linux22/arch/i386/defconfig:1.1.1.2 Wed Sep 1 20:10:18 1999
+++ linux22/arch/i386/defconfig Thu Sep 2 08:24:14 1999
@@ -26,6 +26,7 @@
# CONFIG_MATH_EMULATION is not set
# CONFIG_MTRR is not set
CONFIG_SMP=y
+CONFIG_RTL=y
#
# Loadable module support
Index: linux22/arch/i386/kernel/entry.S
diff -u linux22/arch/i386/kernel/entry.S:1.1.1.1 linux22/arch/i386/kernel/entry.S:1.2
--- linux22/arch/i386/kernel/entry.S:1.1.1.1 Thu Aug 12 22:06:29 1999
+++ linux22/arch/i386/kernel/entry.S Thu Aug 12 22:12:36 1999
@@ -190,6 +190,9 @@
jne reschedule
cmpl $0,sigpending(%ebx)
jne signal_return
+#ifdef __RTL__
+ call __sti #VY just checking
+#endif
restore_all:
RESTORE_ALL
Index: linux22/arch/i386/kernel/i386_ksyms.c
diff -u linux22/arch/i386/kernel/i386_ksyms.c:1.1.1.2 linux22/arch/i386/kernel/i386_ksyms.c:1.7
--- linux22/arch/i386/kernel/i386_ksyms.c:1.1.1.2 Wed Oct 20 23:16:03 1999
+++ linux22/arch/i386/kernel/i386_ksyms.c Wed Jan 12 23:41:57 2000
@@ -116,6 +116,13 @@
EXPORT_SYMBOL(mca_is_adapter_used);
#endif
+/* #ifndef CONFIG_X86_TSC */
+unsigned long (*do_gettimeoffset)(void);
+unsigned int use_tsc;
+EXPORT_SYMBOL(do_gettimeoffset);
+EXPORT_SYMBOL(use_tsc);
+/* #endif */
+
#ifdef CONFIG_VT
EXPORT_SYMBOL(screen_info);
#endif
Index: linux22/arch/i386/kernel/io_apic.c
diff -u linux22/arch/i386/kernel/io_apic.c:1.1.1.3 linux22/arch/i386/kernel/io_apic.c:1.5
--- linux22/arch/i386/kernel/io_apic.c:1.1.1.3 Wed Jan 5 19:30:20 2000
+++ linux22/arch/i386/kernel/io_apic.c Wed Jan 5 23:57:17 2000
@@ -1040,7 +1040,11 @@
if (irq < 16) {
disable_8259A_irq(irq);
if (i8259A_irq_pending(irq))
+#ifndef __RTL__
irq_desc[irq].status |= IRQ_PENDING;
+#else
+ rtl_global_pend_irq(irq);
+#endif
}
enable_edge_ioapic_irq(irq);
}
@@ -1069,7 +1073,9 @@
* Edge triggered IRQs can be acknowledged immediately
* and do not need to be masked.
*/
+#ifndef __RTL__
ack_APIC_irq();
+#endif
status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
status |= IRQ_PENDING;
@@ -1106,9 +1112,28 @@
spin_unlock(&irq_controller_lock);
}
desc->status &= ~IRQ_INPROGRESS;
+#ifdef __RTL__
+ if (!(desc->status & IRQ_DISABLED))/* need this cause RTL has soft_disabled*/
+ rtl_emulate_enable_irq(irq);
+#endif
spin_unlock(&irq_controller_lock);
}
+#ifdef __RTL__
+/* RTL
+ moved this out of the do_level_ioapic code
+ called by rtl_intercept
+ */
+static void mask_and_ack_edge_ioapic(unsigned int irq){
+ ack_APIC_irq();
+}
+static void mask_and_ack_level_ioapic(unsigned int irq)
+{
+ mask_IO_APIC_irq(irq);
+ ack_APIC_irq();
+}
+#endif /* __RTL__ */
+
static void do_level_ioapic_IRQ(unsigned int irq, struct pt_regs * regs)
{
irq_desc_t *desc = irq_desc + irq;
@@ -1124,7 +1149,9 @@
* disable has to happen before the ACK, to avoid IRQ storms.
* So this all has to be within the spinlock.
*/
+#ifndef __RTL__
mask_IO_APIC_irq(irq);
+#endif
status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
/*
@@ -1138,7 +1165,9 @@
}
desc->status = status;
+#ifndef __RTL__
ack_APIC_irq();
+#endif
spin_unlock(&irq_controller_lock);
/* Exit early if we had no action or it was disabled */
@@ -1150,7 +1179,11 @@
spin_lock(&irq_controller_lock);
desc->status &= ~IRQ_INPROGRESS;
if (!(desc->status & IRQ_DISABLED))
+#ifndef __RTL__
unmask_IO_APIC_irq(irq);
+#else
+ rtl_emulate_enable_irq(irq);/* RTL: can't touch hdwr*/
+#endif
spin_unlock(&irq_controller_lock);
}
@@ -1170,6 +1203,9 @@
do_edge_ioapic_IRQ,
enable_edge_ioapic_irq,
disable_edge_ioapic_irq
+#ifdef __RTL__
+ ,mask_and_ack_edge_ioapic
+#endif
};
static struct hw_interrupt_type ioapic_level_irq_type = {
@@ -1179,6 +1215,9 @@
do_level_ioapic_IRQ,
enable_level_ioapic_irq,
disable_level_ioapic_irq
+#ifdef __RTL__
+ ,mask_and_ack_level_ioapic
+#endif
};
static inline void init_IO_APIC_traps(void)
Index: linux22/arch/i386/kernel/irq.c
diff -u linux22/arch/i386/kernel/irq.c:1.1.1.2 linux22/arch/i386/kernel/irq.c:1.29
--- linux22/arch/i386/kernel/irq.c:1.1.1.2 Wed Oct 20 23:16:03 1999
+++ linux22/arch/i386/kernel/irq.c Tue Jan 11 00:01:14 2000
@@ -39,9 +39,136 @@
#include <asm/pgtable.h>
#include <asm/delay.h>
#include <asm/desc.h>
+#include <asm/rtl_sync.h>
+
#include "irq.h"
+#include <linux/cons.h>
+
+/* tracer */
+#ifdef CONFIG_RTL_TRACER
+void rtl_trace_default(int event_id, long event_data, long eip) { }
+void (*rtl_trace)(int event_id, long event_data, long eip) = rtl_trace_default;
+#endif
+
+/* Real Time Linux support */
+unsigned int rtl_intercept(struct pt_regs r);
+void rtl_emulate_enable_irq(unsigned int irq);
+void rtl_emulate_disable_irq(unsigned int irq);
+void rtl_emulate_shutdown_irq(unsigned int irq);
+void rtl_emulate_startup_irq(unsigned int irq);
+void rtl_make_sure_real_sti(const char *);
+
+#define RTL_L_IDLE_BIT 1
+#define RTL_L_IENABLE_BIT 4
+#define RTL_L_SINCE_STI_BIT 8
+#define RTL_L_IDLE_POS 0
+#define RTL_L_IENABLE_POS 2
+#define RTL_L_SINCE_STI_POS 3
+#define is_soft_sti() (RTL_LOCAL.flags & RTL_L_IENABLE_BIT)
+#define is_idle_realtime_system() (RTL_LOCAL.flags & RTL_L_IDLE_BIT)
+#define set_idle_realtime_system() set_bit(RTL_L_IDLE_POS,&RTL_LOCAL.flags)
+#define clear_idle_realtime_system() clear_bit(RTL_L_IDLE_POS,&RTL_LOCAL.flags)
+#define soft_cli() clear_bit(RTL_L_IENABLE_POS,&RTL_LOCAL.flags)
+#define soft_sti() set_bit(RTL_L_IENABLE_POS,&RTL_LOCAL.flags)
+
+/* assuming 255 global irqs and 31 max local smp vectors */
+#define IRQ_ARRAY_SIZE 4
+#define IRQ_ZINIT {0}
+#define IRQ_NZINIT {0xffffffff,0xffffffff,0xffffffff,0xffffffff}
+/* fix if IRQ_ARRAY_SIZE !=4 */
+#define irq_to_index(x) ((x>>5)&3)
+#define irq_to_pos(x) ((x)& 0x1fUL)
+#define irq_to_bit(x) (1UL<< ((x) & 0x1f))
+#define pos_and_index_to_irq(p,i) ( (p) + (i*32))
+#ifdef __SMP__
+struct rtl_local {
+ __u32 flags;
+ __u32 pending;
+}rtl_local[NR_CPUS] = { {RTL_L_IDLE_BIT ,0},{RTL_L_IDLE_BIT,0}};
+#define RTL_LOCAL rtl_local[cpu_id]
+#define active_local_irqs() (RTL_LOCAL.pending)
+#define active_irqs() (active_local_irqs() || active_global_irqs())
+#define DeclareAndInit(cpu_id) unsigned int cpu_id = smp_processor_id()
+#define HardDeclareAndInit(cpu_id) unsigned int cpu_id = hard_smp_processor_id()
+void rtl_local_pend_vec(int vector,int cpu_id) {
+ int i = VECTOR_TO_LOCAL_PND(vector);
+ set_bit(i,&(RTL_LOCAL.pending));
+ set_bit(RTL_L_SINCE_STI_POS, &RTL_LOCAL.flags);
+}
+#else
+#define DeclareAndInit(cpu_id)
+#define HardDeclareAndInit(cpu_id)
+struct rtl_local {
+ __u32 flags;
+} rtl_local = {RTL_L_IENABLE_BIT | RTL_L_IDLE_BIT};
+#define RTL_LOCAL rtl_local
+#endif
+
+
+struct rtl_global{
+ spinlock_t hard_irq_controller_lock;
+ unsigned int rtl_off;
+ unsigned int pending[IRQ_ARRAY_SIZE];
+ unsigned int soft_enabled[IRQ_ARRAY_SIZE];
+ unsigned int rt_system_is_idle;
+ unsigned int rtirq[IRQ_ARRAY_SIZE];
+ unsigned int pended_since_sti;
+};
+struct rtl_global rtl_global ={ SPIN_LOCK_UNLOCKED,1,IRQ_ZINIT,IRQ_NZINIT,1,IRQ_ZINIT,0} ;
+
+/* macros for touching the global structure */
+#define test_g(ix,y) test_bit(irq_to_pos(ix),&y[irq_to_index(ix)])
+#define global_is_pending_irq(ix) test_g(ix,rtl_global.pending)
+#define global_is_enabled_irq(ix) test_g(ix,rtl_global.soft_enabled)
+#define there_is_a_rt_handler(ix) test_g(ix,rtl_global.rtirq)
+#define global_pend_irq(ix)\
+ set_bit(irq_to_pos(ix),&rtl_global.pending[irq_to_index(ix)])
+#define global_unpend_irq(ix) \
+ {clear_bit(irq_to_pos(ix),&rtl_global.pending[irq_to_index(ix)]);}
+#define atomic_global_soft_disable(x) \
+ clear_bit(irq_to_pos(x),&rtl_global.soft_enabled[irq_to_index(x)]);
+#define global_soft_enable(x) \
+ set_bit(irq_to_pos(x),&rtl_global.soft_enabled[irq_to_index(x)]);
+
+
+/* this are exported so that they can be called by rt drivers */
+void rtl_global_pend_irq(int ix) { global_pend_irq(ix);}
+int rtl_global_ispending_irq(int ix) { return global_is_pending_irq(ix);}
+
+void rtl_hard_enable_irq(unsigned int ix) {
+ int flags;
+ rtl_hard_savef_and_cli(flags);
+ rtl_spin_lock(&rtl_global.hard_irq_controller_lock);
+ irq_desc[ix].handler->enable(ix);
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ rtl_hard_restore_flags(flags);
+}
+void rtl_hard_disable_irq(unsigned int ix) {
+ int flags;
+ rtl_hard_savef_and_cli(flags);
+ rtl_spin_lock(&rtl_global.hard_irq_controller_lock);
+ irq_desc[ix].handler->disable(ix);
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ rtl_hard_restore_flags(flags);
+}
+
+unsigned int rtl_rt_system_is_idle(){
+ HardDeclareAndInit(cpu_id);
+ return is_idle_realtime_system();
+}
+/* needs to be called with irqs disabled */
+void rtl_make_rt_system_active(){
+ HardDeclareAndInit(cpu_id);
+ clear_idle_realtime_system();
+}
+/* needs to be called with irqs disabled */
+void rtl_make_rt_system_idle(){
+ HardDeclareAndInit(cpu_id);
+ set_idle_realtime_system();
+}
+
unsigned int local_bh_count[NR_CPUS];
unsigned int local_irq_count[NR_CPUS];
@@ -111,7 +238,36 @@
shutdown_none,
do_none,
enable_none,
- disable_none
+ disable_none,0
+};
+
+/*
+ * Dummy controller type for RTL soft interrupts
+ */
+static void rtl_do_none(unsigned int irq, struct pt_regs * regs)
+{
+ struct irqaction * action;
+ irq_desc_t *desc = irq_desc + irq;
+
+ action = desc->action;
+ if (!action)
+ return;
+ handle_IRQ_event(irq, regs, action);
+}
+static void rtl_enable_none(unsigned int irq) { }
+static void rtl_disable_none(unsigned int irq) { }
+
+/* startup is the same as "enable", shutdown is same as "disable" */
+#define rtl_startup_none rtl_enable_none
+#define rtl_shutdown_none rtl_disable_none
+
+struct hw_interrupt_type rtl_soft_irq_type = {
+ "rtl-soft",
+ rtl_startup_none,
+ rtl_shutdown_none,
+ rtl_do_none,
+ rtl_enable_none,
+ rtl_disable_none,0
};
/*
@@ -126,14 +282,15 @@
/* startup is the same as "enable", shutdown is same as "disable" */
#define startup_8259A_irq enable_8259A_irq
#define shutdown_8259A_irq disable_8259A_irq
-
+static inline void mask_and_ack_8259A(unsigned int irq);
static struct hw_interrupt_type i8259A_irq_type = {
"XT-PIC",
startup_8259A_irq,
shutdown_8259A_irq,
do_8259A_IRQ,
enable_8259A_irq,
- disable_8259A_irq
+ disable_8259A_irq,
+ mask_and_ack_8259A
};
/*
@@ -215,7 +372,8 @@
* first, _then_ send the EOI, and the order of EOI
* to the two 8259s is important!
*/
-static inline void mask_and_ack_8259A(unsigned int irq)
+/* RTL can't inline this yet, since we put the pointer in the desc */
+static void mask_and_ack_8259A(unsigned int irq)
{
cached_irq_mask |= 1 << irq;
if (irq & 8) {
@@ -238,7 +396,6 @@
spin_lock(&irq_controller_lock);
{
unsigned int status;
- mask_and_ack_8259A(irq);
status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
action = NULL;
if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
@@ -252,15 +409,16 @@
/* Exit early if we had no action or it was disabled */
if (!action)
return;
-
handle_IRQ_event(irq, regs, action);
+ __cli(); /* RTL just to make sure */
spin_lock(&irq_controller_lock);
{
unsigned int status = desc->status & ~IRQ_INPROGRESS;
desc->status = status;
- if (!(status & IRQ_DISABLED))
- enable_8259A_irq(irq);
+ if (!(status & IRQ_DISABLED)){
+ rtl_emulate_enable_irq(irq);/* RTL: can't touch hdwr*/
+ }
}
spin_unlock(&irq_controller_lock);
}
@@ -319,11 +477,13 @@
* is no hardware IRQ pin equivalent for them, they are triggered
* through the ICC by us (IPIs)
*/
-BUILD_SMP_INTERRUPT(reschedule_interrupt)
-BUILD_SMP_INTERRUPT(invalidate_interrupt)
-BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
-BUILD_SMP_INTERRUPT(call_function_interrupt)
-BUILD_SMP_INTERRUPT(spurious_interrupt)
+BUILD_COMMON_SMP_IRQ() /* RTL needs to have a common path */
+BUILD_SMP_INTERRUPT(RESCHEDULE_VECTOR,reschedule_interrupt)
+BUILD_SMP_INTERRUPT(INVALIDATE_TLB_VECTOR,invalidate_interrupt)
+BUILD_SMP_INTERRUPT(STOP_CPU_VECTOR,stop_cpu_interrupt)
+BUILD_SMP_INTERRUPT(SPURIOUS_APIC_VECTOR,spurious_interrupt)
+BUILD_SMP_INTERRUPT(CALL_FUNCTION_VECTOR,call_function_interrupt)
+
/*
* every pentium local APIC has two 'local interrupts', with a
@@ -332,7 +492,8 @@
* overflow. Linux uses the local APIC timer interrupt to get
* a much simpler SMP time architecture:
*/
-BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt)
+BUILD_SMP_TIMER_INTERRUPT(LOCAL_TIMER_VECTOR,apic_timer_interrupt)
+BUILD_SMP_TIMER_INTERRUPT(RTL_RESCHEDULE_VECTOR,rtl_resched_interrupt)
#endif
@@ -349,10 +510,10 @@
IRQLIST_16(0x0),
#ifdef CONFIG_X86_IO_APIC
- IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
- IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
+ IRQLIST_16(0x1)/*, IRQLIST_16(0x2), IRQLIST_16(0x3),
+ IRQLIST_16(0x4) , IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
- IRQLIST_16(0xc), IRQLIST_16(0xd)
+ IRQLIST_16(0xc), IRQLIST_16(0xd) */
#endif
};
@@ -758,7 +919,7 @@
spin_lock_irqsave(&irq_controller_lock, flags);
if (!irq_desc[irq].depth++) {
irq_desc[irq].status |= IRQ_DISABLED;
- irq_desc[irq].handler->disable(irq);
+ rtl_emulate_disable_irq(irq); /* RTL: hands off hdwr*/
}
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
@@ -781,12 +942,13 @@
void enable_irq(unsigned int irq)
{
unsigned long flags;
+ DeclareAndInit(cpu_id);
spin_lock_irqsave(&irq_controller_lock, flags);
switch (irq_desc[irq].depth) {
case 1:
irq_desc[irq].status &= ~IRQ_DISABLED;
- irq_desc[irq].handler->enable(irq);
+ rtl_emulate_enable_irq(irq); /*RTL: hands off hrdwr */
/* fall throught */
default:
irq_desc[irq].depth--;
@@ -796,6 +958,7 @@
__builtin_return_address(0));
}
spin_unlock_irqrestore(&irq_controller_lock, flags);
+ if(is_soft_sti())__sti();
}
/*
@@ -803,23 +966,15 @@
* SMP cross-CPU interrupts have their own specific
* handlers).
*/
-asmlinkage void do_IRQ(struct pt_regs regs)
+/* For RTL call with pointer to regs and with irq number already
+ calculated by rtl_intercept or by fake_irq
+ */
+void do_IRQ(unsigned int irq, struct pt_regs *regs)
{
- /*
- * We ack quickly, we don't want the irq controller
- * thinking we're snobs just because some other CPU has
- * disabled global interrupts (we have already done the
- * INT_ACK cycles, it's too late to try to pretend to the
- * controller that we aren't taking the interrupt).
- *
- * 0 return value means that this irq is already being
- * handled by some other CPU. (or is disabled)
- */
- int irq = regs.orig_eax & 0xff; /* subtle, see irq.h */
int cpu = smp_processor_id();
kstat.irqs[cpu][irq]++;
- irq_desc[irq].handler->handle(irq, ®s);
+ irq_desc[irq].handler->handle(irq, regs);
/*
* This should be conditional: we should really get
@@ -881,12 +1036,32 @@
if (!shared) {
irq_desc[irq].depth = 0;
irq_desc[irq].status &= ~IRQ_DISABLED;
- irq_desc[irq].handler->startup(irq);
+ rtl_emulate_startup_irq(irq); /* RTL: hands off hardware*/
}
spin_unlock_irqrestore(&irq_controller_lock,flags);
return 0;
}
+/* VY: needs some synchronization here. Doesn't request_irq also
+ have a problem? */
+int rtl_get_soft_irq (void (*handler) (int, void *, struct pt_regs *),
+ const char *devname)
+{
+ int i;
+ for (i = NR_IRQS - 1; i > 15; i--) {
+ if (!irq_desc[i].action) {
+ irq_desc[i].handler = &rtl_soft_irq_type;
+ if (request_irq (i, handler, 0, devname, 0)) {
+ return -EBUSY;
+ } else {
+ global_soft_enable(i);
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
int request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
@@ -949,7 +1124,7 @@
kfree(action);
if (!irq_desc[irq].action) {
irq_desc[irq].status |= IRQ_DISABLED;
- irq_desc[irq].handler->shutdown(irq);
+ rtl_emulate_shutdown_irq(irq);/*RTL hands off hardware*/
}
goto out;
}
@@ -978,7 +1153,7 @@
for (i = NR_IRQS-1; i > 0; i--) {
if (!irq_desc[i].action) {
irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING;
- irq_desc[i].handler->startup(i);
+ rtl_emulate_startup_irq(i); /* RTL hands off hardware*/
}
}
spin_unlock_irq(&irq_controller_lock);
@@ -1002,7 +1177,8 @@
/* It triggered already - consider it spurious. */
if (!(status & IRQ_WAITING)) {
irq_desc[i].status = status & ~IRQ_AUTODETECT;
- irq_desc[i].handler->shutdown(i);
+ rtl_emulate_shutdown_irq(i);
+/* conpr("SSh"); conprn(i); */
}
}
spin_unlock_irq(&irq_controller_lock);
@@ -1032,7 +1208,7 @@
nr_irqs++;
}
irq_desc[i].status = status & ~IRQ_AUTODETECT;
- irq_desc[i].handler->shutdown(i);
+ rtl_emulate_shutdown_irq(i);
}
spin_unlock_irq(&irq_controller_lock);
@@ -1064,6 +1240,16 @@
}
}
+#ifdef __SMP__
+/* RTL needs this */
+void smp_reschedule_interrupt(void);
+void smp_invalidate_interrupt(void);
+void smp_stop_cpu_interrupt(void);
+void smp_apic_timer_interrupt(struct pt_regs *);
+void smp_spurious_interrupt(void);
+void smp_call_function_interrupt(void);
+#endif /* SMP */
+
__initfunc(void init_IRQ(void))
{
int i;
@@ -1112,6 +1298,9 @@
/* IPI vector for APIC spurious interrupts */
set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
+#ifdef __RTL__
+ set_intr_gate(RTL_RESCHEDULE_VECTOR, rtl_resched_interrupt);
+#endif
#endif
request_region(0x20,0x20,"pic1");
request_region(0xa0,0x20,"pic2");
@@ -1138,5 +1327,525 @@
if (IO_APIC_VECTOR(i) > 0)
set_intr_gate(IO_APIC_VECTOR(i), interrupt[i]);
}
+#endif
+
+
+
+/* these should only be called from Linux kernel so they need
+ to hard cli/sti -- I'm saving out of sloppiness, they should never
+ be called with hard cli.
+ */
+void rtl_emulate_shutdown_irq(unsigned int irq){ rtl_emulate_disable_irq(irq);}
+
+void rtl_emulate_disable_irq(unsigned int irq){
+ if(rtl_global.rtl_off){
+ irq_desc[irq].handler->disable(irq);
+ return;
+ }
+
+ /* don't actually disable here. We are optimistic and
+ only mask/disable in intercept */
+ atomic_global_soft_disable(irq);
+}
+void rtl_emulate_startup_irq(unsigned int irq){
+ int flags;
+ if(rtl_global.rtl_off){
+ irq_desc[irq].handler->startup(irq);
+ global_soft_enable(irq);
+ return;
+ }
+ rtl_hard_savef_and_cli(flags);
+ rtl_spin_lock(&rtl_global.hard_irq_controller_lock);
+ global_soft_enable(irq);
+ irq_desc[irq].handler->startup(irq); /* start it whether pending or
+ not */
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ rtl_hard_restore_flags(flags);
+}
+void rtl_emulate_enable_irq(unsigned int irq){
+ int flags;
+ if(rtl_global.rtl_off){
+ irq_desc[irq].handler->enable(irq);
+ global_soft_enable(irq);
+ return;
+ }
+ rtl_hard_savef_and_cli(flags);
+ rtl_spin_lock(&rtl_global.hard_irq_controller_lock);
+ global_soft_enable(irq);
+ if(!global_is_pending_irq(irq)){
+ irq_desc[irq].handler->enable(irq);
+ }
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ rtl_hard_restore_flags(flags);
+}
+
+void rtl_test_cli(unsigned int *);
+#define IENABLE 0x200 /* need to have the actual bit set since global_cli and
+ global_save_flags etc look at it */
+void __cli(void) {
+ DeclareAndInit(cpu_id);
+ if(rtl_global.rtl_off)rtl_hard_cli();
+ soft_cli();
+}
+void __restore_flags(unsigned int x) {
+ DeclareAndInit(cpu_id);
+ if(rtl_global.rtl_off){
+ if(x& IENABLE) {
+ soft_sti();
+ rtl_hard_sti();
+ }
+ else {
+ soft_cli();
+ rtl_hard_cli();
+ }
+ return;
+ }
+ if(x)__sti();
+ else __cli();
+}
+unsigned int __return_flags(void) {
+ DeclareAndInit(cpu_id);
+ if(rtl_global.rtl_off) {
+ unsigned int y;
+ rtl_hard_save_flags(y);
+ if(y & 0x200) soft_sti();
+ else soft_cli();
+ }
+ return ((RTL_LOCAL.flags & RTL_L_IENABLE_BIT)? IENABLE:0);
+}
+/* DIAGNOSTICS */
+
+/* Diagnostics */
+void rtl_test_cli(unsigned int *x)
+{
+ unsigned long g,j;
+ HardDeclareAndInit(cpu_id);
+ rtl_hard_save_flags(g);
+ g = (g&0x200? 1: 0);
+ j = (RTL_LOCAL.flags & RTL_L_IENABLE_BIT ? 1: 0);
+ if( g != j)
+ {
+ printk("RTL g: x %p x-1:%x x-2:%x\n",x,*( (int *)x -1),*((int *)x -2));
+ }
+ return;
+}
+
+void do_rtl_debug(void){
+ unsigned long g;
+ HardDeclareAndInit(cpu_id);
+ rtl_hard_save_flags(g);
+ rtl_hard_cli();
+ conpr("\nflags="); conprn(g);
+#ifdef __SMP__
+ conpr("\nProcessor="); conprn(cpu_id);
+ conpr("\nGlobal hard_irq_controller_lock=");
+ conprn(rtl_global.hard_irq_controller_lock.lock);
+#endif // __SMP__
+conpr("\npending 0;"); conprn(rtl_global.pending[0]);
+conpr("\nrtl_off;"); conprn(rtl_global.rtl_off);
+conpr("\nsoft_enabled 0 ;"); conprn(rtl_global.soft_enabled[0]);
+conpr("\nrtirq 0;"); conprn(rtl_global.rtirq[0]);
+conpr("\nlocal flags;"); conprn(RTL_LOCAL.flags);
+conpr("\ncached irq flags="); conprn(cached_irq_mask);
+conpr("----------------\n");
+ //outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
+// outb_p(LATCH & 0xff , 0x40); /* LSB */
+// outb(LATCH >> 8 , 0x40); /* MSB */
+rtl_hard_restore_flags(g);
+
+}
+
+void rtl_panic(const char *x)
+{
+ conpr("\nPANIC "); conpr(x);
+ do_rtl_debug();
+ while(1);
+}
+void rtl_test_timer(unsigned char *s)
+{
+ unsigned long g;
+ if(rtl_global.rtl_off)return;
+ rtl_hard_save_flags(g);
+ conpr(s);
+ g = (g&0x200? 1: 0);
+ if(!g)
+ {
+ conpr("real cli in "); conpr(s); conpr("\n");
+ }
+ if(!(rtl_global.soft_enabled[0] & 1)){
+ conpr("no timer enable:"); conpr(s); conpr("\n");
+ conpr("pending=:"); conprn(rtl_global.pending[0]); conpr("\n");
+ }
+
+}
+void rtl_make_sure_real_sti(const char *s){
+ unsigned long g;
+ if(rtl_global.rtl_off)return;
+ rtl_hard_save_flags(g);
+ g = (g&0x200? 1: 0);
+ if(!g)
+ {
+ conpr("real cli in "); conpr(s); conpr("\n");
+ }
+ return;
+}
+
+int rtltc(void)
+{
+ unsigned long g;
+ rtl_hard_save_flags(g);
+ return (g&0x200? 1: 0);
+}
+
+
+/* INTERCEPTS */
+/* this intercepts SMP irqs */
+#ifdef __SMP__
+
+static inline void do_local_irq(int , struct pt_regs *);
+
+static unsigned int default_local_timer_handler(struct pt_regs *r)
+{
+ HardDeclareAndInit(cpu_id);
+ rtl_local_pend_vec(LOCAL_TIMER_VECTOR,cpu_id);
+ return 0;
+}
+
+static unsigned int default_local_resched_handler(struct pt_regs *r)
+{
+ return 0;
+}
+
+struct rtl_local_handlers local_timer_handler[NR_CPUS] = {{default_local_timer_handler}, {default_local_timer_handler}};
+struct rtl_local_handlers local_resched_handler[NR_CPUS] = {{default_local_resched_handler}, {default_local_resched_handler}};
+
+unsigned int rtl_smp_intercept(struct pt_regs regs){
+ unsigned int vector = regs.orig_eax & 0xff;
+ HardDeclareAndInit(cpu_id);
+ ack_APIC_irq();
+
+ rtl_trace(RTL_TRACE_SMP_INTERCEPT, vector, regs.eip);
+
+ if(rtl_global.rtl_off){
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ soft_cli();
+ do_local_irq(vector,®s);
+ soft_sti();
+ return 0;
+ }
+
+ switch (vector) {
+ case RTL_RESCHEDULE_VECTOR:
+ local_resched_handler[cpu_id].handler(®s);
+ rtl_trace(RTL_TRACE_SMP_INTERCEPT_EXIT, vector, regs.eip);
+ return 1;
+ case LOCAL_TIMER_VECTOR:
+ local_timer_handler[cpu_id].handler(®s);
+ break;
+ case INVALIDATE_TLB_VECTOR:
+ case STOP_CPU_VECTOR:
+ case CALL_FUNCTION_VECTOR:
+ case RESCHEDULE_VECTOR:
+ rtl_local_pend_vec(vector,cpu_id);
+ break;
+ default:
+ conpr("RTL unexpected local vector: ");
+ conprn(vector);
+ return 1;
+ }
+
+
+ if((regs.eflags & 0x200) && is_idle_realtime_system() && is_soft_sti())
+ {
+ soft_cli();
+ rtl_hard_sti(); /* yikes */
+ __sti(); /* handle any pending interrupts */
+ rtl_trace(RTL_TRACE_SMP_INTERCEPT_EXIT, vector, regs.eip);
+ return 0;
+ }
+ else return 1;
+}
+static inline void do_local_irq(int vector, struct pt_regs *regs){
+ switch(vector){
+ /* IPI for rescheduling */
+ case RESCHEDULE_VECTOR:
+ smp_reschedule_interrupt();
+ break;
+ /* IPI for invalidation */
+ case INVALIDATE_TLB_VECTOR:
+ smp_invalidate_interrupt();
+ break;
+ /* IPI for CPU halt */
+ case STOP_CPU_VECTOR:
+ smp_stop_cpu_interrupt();
+ break;
+ /* self generated IPI for local APIC timer */
+ case LOCAL_TIMER_VECTOR:
+ smp_apic_timer_interrupt(regs);
+ break;
+ /* IPI for function call control */
+ case CALL_FUNCTION_VECTOR:
+ smp_call_function_interrupt();
+ break;
+ /* IPI vector for APIC spurious interrupts */
+ case SPURIOUS_APIC_VECTOR:
+ smp_spurious_interrupt();
+ break;
+ default:
+ printk("RTL: bad smp vector %x\n",vector);
+ break;
+ }
+}
+
+#endif
+
+unsigned int rtl_intercept(struct pt_regs regs)
+{
+ unsigned int irq = regs.orig_eax & 0xff;
+ HardDeclareAndInit(cpu_id);
+
+ rtl_trace(RTL_TRACE_INTERCEPT, irq, regs.eip);
+ /*
+ * We ack quickly, we don't want the irq controller
+ * thinking we're snobs just because some other CPU has
+ * disabled global interrupts (we have already done the
+ * INT_ACK cycles, it's too late to try to pretend to the
+ * controller that we aren't taking the interrupt).
+ *
+ * 0 return value means that this irq is already being
+ * handled by some other CPU. (or is disabled)
+ */
+ rtl_spin_lock(&rtl_global.hard_irq_controller_lock);
+ irq_desc[irq].handler->mask_and_ack(irq);
+ if(rtl_global.rtl_off){
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ soft_cli();
+ do_IRQ(irq,®s);
+ soft_sti();
+ return 0;
+ }
+ /* if there is a real time handler, call it and see if it is
+ willing to share the interrupt */
+ if(there_is_a_rt_handler(irq) && rtl_global_handlers[irq].handler)
+ {
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ rtl_global_handlers[irq].handler(irq,®s);
+ rtl_hard_cli(); /* driver may have hard sti'd */
+ rtl_spin_lock(&rtl_global.hard_irq_controller_lock);
+ if(!global_is_pending_irq(irq)){/* does linux need it? */
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ rtl_trace2(RTL_TRACE_INTERCEPT_EXIT, irq);
+ return 1;
+ }
+ }
+ else {
+ global_pend_irq(irq); /*note structure is locked */
+ }
+ if( is_soft_sti() && is_idle_realtime_system()
+ && global_is_enabled_irq(irq))
+ {
+ global_unpend_irq(irq); /* because we call do_IRQ */
+ soft_cli(); /*soft disable interrupts */
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ rtl_hard_sti(); /* yikes */
+ do_IRQ(irq,®s);
+ __sti(); /* take care of any left over irqs */
+
+ rtl_trace2(RTL_TRACE_INTERCEPT_EXIT, irq);
+ return 0;
+ }
+ rtl_global.pended_since_sti = 1;
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ rtl_trace2(RTL_TRACE_INTERCEPT_EXIT, irq);
+ return 1;
+
+}
+
+
+
+/* pt_regs
+long ebx= 0, long ecx=0, long edx=0, long esi=0, long edi=0,
+long ebp=0, long eax=0, int xds= __KERNEL_DS, int xes=0, long orig_eax=0,
+long eip= (long)__sti, int xcs= __KERNEL_CS, long eflags= IENABLE,
+long esp=0, int xss=0
+*/
+#define FAKE_REGS { 0, 0, 0, 0, 0, 0, 0, __KERNEL_DS, 0, 0, (long)__sti, __KERNEL_CS, IENABLE, 0, 0 }
+
+#define MAX_FAKE_DEPTH 200
+struct pt_regs fake_regs[NR_CPUS][MAX_FAKE_DEPTH];
+struct pt_regs *fake_top[NR_CPUS];
+struct pt_regs *next_fake_top(void){
+ int i;
+ struct pt_regs *r = 0;
+#ifdef __SMP__
+ DeclareAndInit(cpu_id);
+#else
+ unsigned int cpu_id = 0;
+#endif
+ for(i=0; i < MAX_FAKE_DEPTH;i++){
+ if(fake_regs[cpu_id][i].orig_eax)continue;
+ else{
+ r = &fake_regs[cpu_id][i];
+ r->orig_eax = -1;
+ break;}
+ }
+ if(!r)printk("RTL is astonished to announce out of fake regs\n");
+ return r;
+
+}
+
+void pop_fake(struct pt_regs *r){ r->orig_eax = 0; }
+
+
+
+#ifdef __SMP__
+static inline int fake_local_irq(unsigned int);
+static inline int fake_local_irq(unsigned int cpu_id){
+ struct pt_regs *r;
+ unsigned int pos;
+ rtl_hard_cli();
+ if( !(r= next_fake_top())) {
+ rtl_hard_sti();
+ return 0;
+ }
+ if(RTL_LOCAL.pending){
+ pos = ffz(~RTL_LOCAL.pending);
+ clear_bit(pos,&RTL_LOCAL.pending);
+ r->orig_eax = -1;
+ rtl_hard_sti(); /* yikes */
+ do_local_irq(LOCAL_PND_TO_VECTOR(pos),r);
+ pop_fake(r);
+ return 1;
+ }
+ rtl_hard_sti(); /* yikes */
+ pop_fake(r);
+ return 0; /* didn't find anything to emulate */
+}
+#else
+#define fake_local_irq(x) 0
+#endif
+
+static inline int fake_global_irq(void);
+static inline int fake_global_irq(){
+ int i,pos,active;
+ struct pt_regs *r;
+ rtl_hard_cli();
+ if(!(r= next_fake_top())){
+ rtl_hard_sti();
+ return 0;
+ }
+ rtl_spin_lock(&rtl_global.hard_irq_controller_lock);
+ for(i=0; i < IRQ_ARRAY_SIZE;i++){
+ if((active= (rtl_global.pending[i]&rtl_global.soft_enabled[i])))
+ {
+ pos = ffz(~active);
+ clear_bit(pos,&rtl_global.pending[i]);
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ rtl_hard_sti(); /* yikes */
+ r->orig_eax = pos_and_index_to_irq(pos,i);
+ do_IRQ(pos_and_index_to_irq(pos,i),r);
+ pop_fake(r);
+ return 1;
+ }
+ }
+ rtl_spin_unlock(&rtl_global.hard_irq_controller_lock);
+ rtl_hard_sti(); /* yikes */
+ pop_fake(r);
+ return 0; /* didn't find anything to emulate */
+}
+
+void __sti(){
+ unsigned int faked_an_interrupt = 0;
+ DeclareAndInit(cpu_id);
+
+ soft_sti();
+ rtl_hard_sti();
+ if(rtl_global.rtl_off) return;
+ do{
+ soft_cli();
+ faked_an_interrupt = fake_global_irq()| fake_local_irq(cpu_id);
+ soft_sti();
+ } while((faked_an_interrupt > 0)
+ || (test_and_clear_bit(0,&rtl_global.pended_since_sti))
+ || test_and_clear_bit(RTL_L_SINCE_STI_POS, &RTL_LOCAL.flags));
+ /* the point of this loop is to make sure that IRQs are not
+ stranded pending.
+ fake_irq may return 0, indicating no irqs pending (nothing to
+ fake) and then a new irq may pend. If so, pended_since_sti will
+ be true. If an irq occurs after the test for pended_since, it
+ will simply roll into a second invocation of __sti since we
+ only do the test with IENABLE and in_sti=0;
+ Might need a MB, but it should be doable more simply.
+ */
+
+}
+
+void rtl_init(void)
+{
+ DeclareAndInit(cpu_id);
+#ifdef CONFIG_RTL
+ printk("RTL start");
+ soft_cli();
+ if(test_and_clear_bit(0,&rtl_global.rtl_off)) {
+ // rtl time stuff is now in a module
+ }
+ printk("ed\n");
+#endif
+ rtl_hard_sti();
+ return;
+}
+
+int rtl_request_global_irq(unsigned int irq,
+ unsigned int (*handler)(unsigned int, struct pt_regs *))
+{
+ if (!test_and_set_bit(irq,&rtl_global.rtirq)) {
+ rtl_global_handlers[irq].handler =handler;
+/* rtl_hard_enable_irq (irq); */
+ return 0;
+ }
+ return -EBUSY;
+}
+
+int rtl_free_global_irq(unsigned int irq )
+{
+ if (!test_bit(irq,&rtl_global.rtirq)) {
+ return -EINVAL;
+ } else {
+ rtl_global_handlers[irq].handler = 0;
+ clear_bit(irq,&rtl_global.rtirq);
+ return 0;
+ }
+}
+
+
+
+#ifdef __SMP__
+/* spinlock_t rtl_lock; */
+int rtl_request_local_irq(int i, unsigned int (*handler)(struct pt_regs *r), unsigned int cpu) {
+ if (i == LOCAL_TIMER_VECTOR) {
+ local_timer_handler[cpu].handler = handler;
+ return 0;
+ }
+ if (i == RTL_RESCHEDULE_VECTOR) {
+ local_resched_handler[cpu].handler = handler;
+ return 0;
+ }
+ printk("rtl_request_local_irq not implemented yet\n");
+ return -EINVAL;
+}
+
+int rtl_free_local_irq(int i, unsigned int cpu){
+ if (i == LOCAL_TIMER_VECTOR) {
+ local_timer_handler[cpu].handler = default_local_timer_handler;
+ return 0;
+ }
+ if (i == RTL_RESCHEDULE_VECTOR) {
+ local_resched_handler[cpu].handler = default_local_resched_handler;
+ return 0;
+ }
+ printk("rtl_free_local_irq not implemented yet\n");
+ return -EINVAL;
+}
+
#endif
Index: linux22/arch/i386/kernel/irq.h
diff -u linux22/arch/i386/kernel/irq.h:1.1.1.2 linux22/arch/i386/kernel/irq.h:1.3
--- linux22/arch/i386/kernel/irq.h:1.1.1.2 Wed Jan 5 19:30:20 2000
+++ linux22/arch/i386/kernel/irq.h Wed Jan 5 23:57:17 2000
@@ -2,7 +2,19 @@
#define __irq_h
#include <asm/irq.h>
+#include <linux/rtl.h>
+extern void rtl_emulate_enable_irq(unsigned int irq);
+
+/* RTL real time interrupt handlers */
+struct rtl_global_handlers{
+ unsigned int (*handler)(unsigned int irq, struct pt_regs *r);
+}rtl_global_handlers[64];
+
+struct rtl_local_handlers{
+ unsigned int (*handler)(struct pt_regs *r);
+};
+
/*
* Interrupt controller descriptor. This is all we need
* to describe about the low-level hardware.
@@ -14,6 +26,7 @@
void (*handle)(unsigned int irq, struct pt_regs * regs);
void (*enable)(unsigned int irq);
void (*disable)(unsigned int irq);
+ void (*mask_and_ack)(unsigned int irq);
};
extern struct hw_interrupt_type no_irq_type;
@@ -67,13 +80,27 @@
#define STOP_CPU_VECTOR 0x40
#define LOCAL_TIMER_VECTOR 0x41
#define CALL_FUNCTION_VECTOR 0x50
+#define RTL_RESCHEDULE_VECTOR 0x51
+
+#define VECTOR_TO_LOCAL_PND(x) (((x)>>3)|((x)&1)) /* ok, it's stupid */
+#define LOCAL_PND_TO_VECTOR(x) ((((x)&0xe)<<3)|((x)&1)) /* ok, it's stupid */
+ /* but 0x30 -> 6
+ 0x31 -> 7
+ 0x40 -> 8
+ 0x41 -> 9
+ 0x50 -> A
+ etc
+ only a problem if use more than one bit
+ in the low order 4 bits or more than
+ 31 vectors total!
+ */
+ /*
+ * First APIC vector available to drivers: (vectors 0x61-0xfe)
+ */
+#define IRQ0_TRAP_VECTOR 0x61
+
/*
- * First APIC vector available to drivers: (vectors 0x51-0xfe)
- */
-#define IRQ0_TRAP_VECTOR 0x51
-
-/*
* This IRQ should never happen, but we print a message nevertheless.
*/
#define SPURIOUS_APIC_VECTOR 0xff
@@ -190,38 +217,59 @@
* SMP has a few special interrupts for IPI messages
*/
-#define BUILD_SMP_INTERRUPT(x) \
-asmlinkage void x(void); \
+#define BUILD_COMMON_SMP_IRQ() \
__asm__( \
-"\n"__ALIGN_STR"\n" \
-SYMBOL_NAME_STR(x) ":\n\t" \
- "pushl $-1\n\t" \
+ "\n" __ALIGN_STR"\n" \
+ "common_smp_interrupt:\n\t" \
SAVE_ALL \
- "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
- "jmp ret_from_intr\n");
+ "call "SYMBOL_NAME_STR(rtl_smp_intercept)"\n\t"\
+ "testl %eax,%eax;\n\t"\
+ "jz ret_from_intr;\n\t" \
+ "popl %ebx; \n\t" \
+ "popl %ecx; \n\t" \
+ "popl %edx; \n\t" \
+ "popl %esi; \n\t" \
+ "popl %edi; \n\t" \
+ "popl %ebp; \n\t" \
+ "popl %eax; \n\t" \
+ "popl %ds; \n\t" \
+ "popl %es; \n\t" \
+ "addl $4,%esp; \n\t" \
+ "iret; \n\t" );
-#define BUILD_SMP_TIMER_INTERRUPT(x) \
-asmlinkage void x(struct pt_regs * regs); \
+#define BUILD_SMP_INTERRUPT(vctr,f) \
+asmlinkage void f(void); \
__asm__( \
"\n"__ALIGN_STR"\n" \
-SYMBOL_NAME_STR(x) ":\n\t" \
- "pushl $-1\n\t" \
- SAVE_ALL \
- "movl %esp,%eax\n\t" \
- "pushl %eax\n\t" \
- "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
- "addl $4,%esp\n\t" \
- "jmp ret_from_intr\n");
+SYMBOL_NAME_STR(f) ":\n\t" \
+ "pushl $"SYMBOL_NAME_STR(vctr)"\n\t" \
+ "jmp common_smp_interrupt");
+/* RTL the difference is taken care of in the intercept routine */
+#define BUILD_SMP_TIMER_INTERRUPT(x,y) BUILD_SMP_INTERRUPT(x,y)
#endif /* __SMP__ */
+/* The restore state part of this better change if
+ SAVE_ALL changes or things will not look good VY*/
#define BUILD_COMMON_IRQ() \
__asm__( \
"\n" __ALIGN_STR"\n" \
"common_interrupt:\n\t" \
SAVE_ALL \
- "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
- "jmp ret_from_intr\n");
+ "call "SYMBOL_NAME_STR(rtl_intercept)"\n\t"\
+ "testl %eax,%eax;\n\t"\
+ "jz ret_from_intr;\n\t" \
+ "popl %ebx; \n\t" \
+ "popl %ecx; \n\t" \
+ "popl %edx; \n\t" \
+ "popl %esi; \n\t" \
+ "popl %edi; \n\t" \
+ "popl %ebp; \n\t" \
+ "popl %eax; \n\t" \
+ "popl %ds; \n\t" \
+ "popl %es; \n\t" \
+ "addl $4,%esp; \n\t" \
+ "iret; \n\t" );
/*
* subtle. orig_eax is used by the signal code to distinct between
Index: linux22/arch/i386/kernel/smp.c
diff -u linux22/arch/i386/kernel/smp.c:1.1.1.3 linux22/arch/i386/kernel/smp.c:1.7
--- linux22/arch/i386/kernel/smp.c:1.1.1.3 Wed Jan 5 19:30:19 2000
+++ linux22/arch/i386/kernel/smp.c Wed Jan 5 23:57:17 2000
@@ -1586,6 +1586,14 @@
#endif
}
+
+#ifdef __RTL__
+void rtl_reschedule(unsigned int cpu){
+ send_IPI_single(cpu,RTL_RESCHEDULE_VECTOR);
+}
+#endif
+
+
/*
* This is fraught with deadlocks. Probably the situation is not that
* bad as in the early days of SMP, so we might ease some of the
@@ -1630,7 +1638,7 @@
* Spin waiting for completion
*/
- stuck = 50000000;
+ stuck = 250000000;
while (smp_invalidate_needed) {
/*
* Take care of "crossing" invalidates
@@ -1845,7 +1853,10 @@
* want to be able to accept NMI tlb invalidates
* during this time.
*/
+#ifndef __RTL__
ack_APIC_irq();
+ /* RTL -- no ack here, ack in intercept */
+#endif
smp_local_timer_interrupt(regs);
}
@@ -1856,7 +1867,10 @@
*/
asmlinkage void smp_reschedule_interrupt(void)
{
+#ifndef __RTL__
ack_APIC_irq();
+ /* RTL -- no ack here, ack in intercept */
+#endif
}
/*
@@ -1866,9 +1880,9 @@
{
if (test_and_clear_bit(smp_processor_id(), &smp_invalidate_needed))
local_flush_tlb();
-
+#ifndef __RTL__
ack_APIC_irq();
-
+#endif
}
static void stop_this_cpu (void)
@@ -1897,7 +1911,9 @@
void *info = smp_call_function_data->info;
int wait = smp_call_function_data->wait;
+#ifndef __RTL__
ack_APIC_irq ();
+#endif
/* Notify initiating CPU that I've grabbed the data and am about to
execute the function */
atomic_dec (&smp_call_function_data->unstarted_count);
@@ -2130,8 +2146,8 @@
/*
* We ACK the APIC, just in case there is something pending.
*/
+ ack_APIC_irq(); /* RTL ok to ack in an initialization routine*/
- ack_APIC_irq ();
__restore_flags(flags);
}
Index: linux22/arch/i386/kernel/time.c
diff -u linux22/arch/i386/kernel/time.c:1.1.1.1 linux22/arch/i386/kernel/time.c:1.5
--- linux22/arch/i386/kernel/time.c:1.1.1.1 Thu Aug 12 22:06:29 1999
+++ linux22/arch/i386/kernel/time.c Wed Jan 12 23:41:57 2000
@@ -110,7 +110,7 @@
#define TICK_SIZE tick
-#ifndef CONFIG_X86_TSC
+/* #ifndef CONFIG_X86_TSC */
/* This function must be called with interrupts disabled
* It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
@@ -223,13 +223,13 @@
return count;
}
-static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
+unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
-#else
+/* #else */
-#define do_gettimeoffset() do_fast_gettimeoffset()
+/* #define do_gettimeoffset() do_fast_gettimeoffset() */
-#endif
+/* #endif */
/*
* This version of gettimeofday has microsecond resolution
@@ -409,7 +409,7 @@
#endif
}
-static int use_tsc = 0;
+int use_tsc = 0;
/*
* This is the same as the above, except we _also_ save the current
Index: linux22/drivers/block/ide.c
diff -u linux22/drivers/block/ide.c:1.1.1.3 linux22/drivers/block/ide.c:1.2
--- linux22/drivers/block/ide.c:1.1.1.3 Wed Jan 5 19:29:01 2000
+++ linux22/drivers/block/ide.c Mon Jan 10 22:19:45 2000
@@ -161,6 +161,7 @@
*/
static unsigned long read_timer(void)
{
+#ifndef CONFIG_RTL
unsigned long t, flags;
int i;
@@ -172,6 +173,9 @@
i |= inb(0x40) << 8;
__restore_flags(flags); /* local CPU only */
return (t - i);
+#else
+ return 0;
+#endif
}
#endif /* DISK_RECOVERY_TIME */
Index: linux22/fs/proc/array.c
diff -u linux22/fs/proc/array.c:1.1.1.4 linux22/fs/proc/array.c:1.5
--- linux22/fs/proc/array.c:1.1.1.4 Wed Jan 5 19:27:24 2000
+++ linux22/fs/proc/array.c Wed Jan 5 23:57:21 2000
@@ -75,6 +75,9 @@
int get_malloc(char * buffer);
#endif
+#ifdef CONFIG_RTL
+extern int get_rtl_status(char *buf);
+#endif
static int open_kcore(struct inode * inode, struct file * filp)
{
@@ -1393,6 +1396,10 @@
#ifdef CONFIG_RTC
case PROC_RTC:
return get_rtc_status(page);
+#endif
+#ifdef CONFIG_RTL
+ case PROC_RTLINUX:
+ return get_rtl_status(page);
#endif
#ifdef CONFIG_SGI_DS1286
case PROC_RTC:
Index: linux22/fs/proc/root.c
diff -u linux22/fs/proc/root.c:1.1.1.2 linux22/fs/proc/root.c:1.3
--- linux22/fs/proc/root.c:1.1.1.2 Wed Oct 20 23:13:43 1999
+++ linux22/fs/proc/root.c Wed Oct 20 23:24:41 1999
@@ -633,6 +633,13 @@
0, &proc_array_inode_operations
};
#endif
+#ifdef CONFIG_RTL
+static struct proc_dir_entry proc_root_rtlinux = {
+ PROC_RTLINUX, 7, "rtlinux",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_array_inode_operations
+ };
+#endif
#ifdef CONFIG_SGI_DS1286
static struct proc_dir_entry proc_root_ds1286 = {
PROC_RTC, 3, "rtc",
@@ -686,6 +693,9 @@
proc_register(&proc_root, &proc_root_version);
proc_register(&proc_root, &proc_root_cpuinfo);
proc_register(&proc_root, &proc_root_self);
+#ifdef CONFIG_RTL
+ proc_register(&proc_root, &proc_root_rtlinux);
+#endif
proc_net = create_proc_entry("net", S_IFDIR, 0);
proc_scsi = create_proc_entry("scsi", S_IFDIR, 0);
#ifdef CONFIG_SYSCTL
Index: linux22/include/asm-i386/irq.h
diff -u linux22/include/asm-i386/irq.h:1.1.1.1 linux22/include/asm-i386/irq.h:1.2
--- linux22/include/asm-i386/irq.h:1.1.1.1 Thu Aug 12 22:05:36 1999
+++ linux22/include/asm-i386/irq.h Thu Aug 12 22:12:37 1999
@@ -21,7 +21,13 @@
* Since vectors 0x00-0x1f are used/reserved for the CPU,
* the usable vector space is 0x20-0xff (224 vectors)
*/
+
+#ifndef __RTL__
#define NR_IRQS 224
+#else
+/* RTL quick hack */
+#define NR_IRQS 64
+#endif
static __inline__ int irq_cannonicalize(int irq)
{
Index: linux22/include/asm-i386/rtl_sync.h
diff -u /dev/null linux22/include/asm-i386/rtl_sync.h:1.5
--- /dev/null Fri Feb 11 20:03:57 2000
+++ linux22/include/asm-i386/rtl_sync.h Thu Oct 21 00:35:56 1999
@@ -0,0 +1,69 @@
+#ifndef __RTL_LINUX_SYNC_H__
+#define __RTL_LINUX_SYNC_H__
+
+#include <linux/rtl_trace.h>
+#include <asm/spinlock.h>
+
+/* DO NOT USE THESE OUTSIDE OF THE RTLINUX CODE!!! */
+/* (c) Victor Yodaiken 1999. */
+
+#ifndef CONFIG_RTL_TRACER
+
+#define rtl_allow_interrupts() __asm__ __volatile__ ("sti": : :"memory")
+#define rtl_stop_interrupts() __asm__ __volatile__ ("cli": : :"memory")
+#define rtl_save_interrupts(x) \
+__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")
+#define rtl_restore_interrupts(x) \
+__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
+#define rtl_no_interrupts(x) \
+__asm__ __volatile__("pushfl ; cli; popl %0": "=g" (x): /* no input */ :"memory")
+/* I wonder if the code above is slower because the cli gives the pushed
+ value a chance to disappear from some forwarding register? VY */
+
+
+#else
+
+#define rtl_allow_interrupts() do { rtl_trace2a(RTL_TRACE_ALLOW_INTERRUPTS, 0); __asm__ __volatile__ ("sti": : :"memory"); } while (0)
+#define rtl_stop_interrupts() do { __asm__ __volatile__ ("cli": : :"memory"); rtl_trace2(RTL_TRACE_STOP_INTERRUPTS, 0); } while (0)
+#define rtl_save_interrupts(x) \
+do { __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory"); rtl_trace2(RTL_TRACE_SAVE_INTERRUPTS, x); } while (0)
+#define rtl_restore_interrupts(x) \
+do { __asm__ __volatile__ ("cli": : :"memory"); rtl_trace2a(RTL_TRACE_RESTORE_INTERRUPTS, x); __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory"); } while (0)
+#define rtl_no_interrupts(x) \
+do { __asm__ __volatile__("pushfl ; cli; popl %0": "=g" (x): /* no input */ :"memory"); rtl_trace2(RTL_TRACE_NO_INTERRUPTS, x); } while (0)
+
+#endif
+
+#define rtl_hard_savef_and_cli(x) rtl_no_interrupts(x)
+#define rtl_hard_restore_flags(x) rtl_restore_interrupts(x)
+#define rtl_hard_sti() rtl_allow_interrupts()
+#define rtl_hard_cli() rtl_stop_interrupts()
+#define rtl_hard_save_flags(x) rtl_save_interrupts(x)
+
+#ifdef __SMP__
+/*
+#define rtl_spin_lock(x) { static int z;\
+ for(z=0;z<100000000;z++)\
+ if(!test_and_set_bit(0,x.lock))break;\
+ rtl_trace2(RTL_TRACE_SPIN_LOCK, (long ) x); \
+ if(! rtl_global.rtl_off){ \
+ if(z==100000000) { \
+ conpr("\nRTLBADSpin=");\
+ conprn((unsigned int)&z);\
+ panic("badspin"); }}}
+
+
+#define rtl_spin_unlock(x) do { rtl_trace2a(RTL_TRACE_SPIN_UNLOCK, (long) x); clear_bit(0,x.lock); } while (0)
+*/
+
+#define rtl_spin_lock(x) do { spin_lock(x); rtl_trace2(RTL_TRACE_SPIN_LOCK, (long)x); } while (0)
+#define rtl_spin_unlock(x) do { rtl_trace2a(RTL_TRACE_SPIN_UNLOCK, (long) x); spin_unlock(x); } while (0)
+
+#else
+
+#define rtl_spin_lock(x)
+#define rtl_spin_unlock(x)
+
+#endif
+
+#endif
Index: linux22/include/asm-i386/system.h
diff -u linux22/include/asm-i386/system.h:1.1.1.1 linux22/include/asm-i386/system.h:1.2
--- linux22/include/asm-i386/system.h:1.1.1.1 Thu Aug 12 22:05:36 1999
+++ linux22/include/asm-i386/system.h Thu Aug 12 22:12:37 1999
@@ -174,6 +174,8 @@
#define wmb() __asm__ __volatile__ ("": : :"memory")
/* interrupt control.. */
+/* RTL: these are all defined in irq.c for now */
+#if 0 /* ! __RTL__ */
#define __sti() __asm__ __volatile__ ("sti": : :"memory")
#define __cli() __asm__ __volatile__ ("cli": : :"memory")
#define __save_flags(x) \
@@ -181,6 +183,13 @@
#define __restore_flags(x) \
__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
+#else
+extern void __sti(void);
+extern void __cli(void);
+extern void __restore_flags(unsigned int);
+extern unsigned int __return_flags(void);
+#define __save_flags(x) {x = __return_flags();}
+#endif
#ifdef __SMP__
Index: linux22/include/linux/cons.h
diff -u /dev/null linux22/include/linux/cons.h:1.6
--- /dev/null Fri Feb 11 20:04:19 2000
+++ linux22/include/linux/cons.h Mon Jan 3 10:15:49 2000
@@ -0,0 +1,92 @@
+#ifndef __RTL_CONS_H__
+#define __RTL_CONS_H__
+/*
+ * debugging routines for RT-Linux
+ *
+ * Copyright (C) Michael Barabanov 1997
+ * Copyright (C) VJY Associates 1999
+ * Released under the terms of the GPL
+ *
+ */
+
+#include <asm/system.h>
+
+extern void conpr(const char * b);
+
+static inline void conprn(const unsigned int hexnum)
+{
+ int i;
+ unsigned int d;
+ unsigned int n = hexnum;
+ char s[10];
+ s[9] = 0;
+ s[8] = ' ';
+ for (i=7; i>=0; i--) {
+ d = n % 16;
+ if (d < 10) {
+ d += '0';
+ } else {
+ d += 'a' - 10;
+ }
+ s[i] = d;
+ n = n / 16;
+ }
+ conpr(s);
+}
+
+static inline void conprd(const unsigned int num)
+{
+ int i;
+ unsigned int d;
+ unsigned int n = num;
+ char s[12];
+ s[11] = 0;
+ s[10] = ' ';
+ for (i=9; i>=0; i--) {
+ d = n % 10;
+ if (d < 10) {
+ d += '0';
+ } else {
+ d += 'a' - 10;
+ }
+ s[i] = d;
+ n = n / 10;
+ }
+ conpr(s);
+}
+
+#define rt_check_cli() { long flags; r_save_flags(flags); \
+ if (flags & 0x200) { \
+ conpr("interrupts are enabled!\n"); \
+ } \
+}
+
+#define CONPRX(a,b) {conpr(a); conprn((int)(b)); conpr("\n");}
+#define conprll(ll) { conprn((int)((ll) >> 32)); conprn((int) (ll)); }
+#define conprtime(ts) { conprd((ts).tv_sec); conprd((ts).tv_nsec); }
+
+#define PRINTAX \
+ "pushl %%eax\n\t" \
+ "pushl %%ebp\n\t" \
+ "pushl %%edi\n\t" \
+ "pushl %%esi\n\t" \
+ "pushl %%edx\n\t" \
+ "pushl %%ecx\n\t" \
+ "pushl %%ebx\n\t" \
+ "pushl %%eax\n\t" \
+ "call "SYMBOL_NAME_STR(conprn)"\n\t" \
+ "add $4, %%esp\n\t" \
+ "popl %%ebx\n\t \
+ popl %%ecx\n\t \
+ popl %%edx\n\t \
+ popl %%esi\n\t \
+ popl %%edi\n\t \
+ popl %%ebp\n\t \
+ popl %%eax\n\t"
+
+extern inline void conf(void) {
+ int i;
+ for ( i=0; i< 10000000; i++);
+}
+
+#endif
Index: linux22/include/linux/major.h
diff -u linux22/include/linux/major.h:1.1.1.3 linux22/include/linux/major.h:1.4
--- linux22/include/linux/major.h:1.1.1.3 Wed Jan 5 19:27:40 2000
+++ linux22/include/linux/major.h Wed Jan 5 23:57:21 2000
@@ -83,6 +83,7 @@
#define IDE4_MAJOR 56
#define IDE5_MAJOR 57
+#define RTF_MAJOR 150 /* real time fifos RTL */
#define SCSI_DISK1_MAJOR 65
#define SCSI_DISK2_MAJOR 66
#define SCSI_DISK3_MAJOR 67
Index: linux22/include/linux/proc_fs.h
diff -u linux22/include/linux/proc_fs.h:1.1.1.4 linux22/include/linux/proc_fs.h:1.5
--- linux22/include/linux/proc_fs.h:1.1.1.4 Wed Jan 5 19:27:39 2000
+++ linux22/include/linux/proc_fs.h Wed Jan 5 23:57:21 2000
@@ -53,6 +53,9 @@
PROC_SOUND,
PROC_MTRR, /* whether enabled or not */
PROC_FS
+#ifdef CONFIG_RTL
+ ,PROC_RTLINUX
+#endif
};
enum pid_directory_inos {
Index: linux22/include/linux/rtl.h
diff -u /dev/null linux22/include/linux/rtl.h:1.6
--- /dev/null Fri Feb 11 20:04:21 2000
+++ linux22/include/linux/rtl.h Tue Jan 11 00:01:17 2000
@@ -0,0 +1,36 @@
+/* Copyright Victor Yodaiken 1999.
+ Released under the terms of the GNU Library GPL
+ */
+
+#ifndef __rtl_h
+#define __rtl_h
+
+extern void rtl_make_rt_system_active(void);
+extern unsigned int rtl_rt_system_is_idle(void);
+extern void rtl_make_rt_system_idle(void);
+extern unsigned int rtl_hard_smp_processor_id(void);
+extern void rtl_reschedule(unsigned int);
+
+extern int rtl_get_soft_irq( void (*handler)(int, void *, struct pt_regs *),
+ const char * devname);
+
+extern int rtl_request_global_irq(unsigned int irq,
+ unsigned int (*handler)(unsigned int, struct pt_regs *));
+extern int rtl_free_global_irq(unsigned int irq);
+extern void rtl_global_pend_irq(int ix);
+extern int rtl_global_ispending_irq(int ix);
+
+/* if you don't say local, you mean global */
+#define rtl_request_irq(x, y) rtl_request_global_irq(x, y)
+#define rtl_free_irq(x) rtl_free_global_irq(x)
+
+#ifdef __SMP__
+int rtl_request_local_irq(int i, unsigned int (*handler)(struct pt_regs *r),
+ unsigned int cpu);
+int rtl_free_local_irq(int i, unsigned int cpu);
+
+extern void rtl_local_pend_vec(int intvec,int cpu_id);
+
+#endif
+
+#endif
Index: linux22/include/linux/rtl_trace.h
diff -u /dev/null linux22/include/linux/rtl_trace.h:1.5
--- /dev/null Fri Feb 11 20:04:21 2000
+++ linux22/include/linux/rtl_trace.h Sun Sep 19 18:54:15 1999
@@ -0,0 +1,43 @@
+#ifndef __RTL_TRACE_H__
+#define __RTL_TRACE_H__
+
+/* #undef to leave no trace */
+/* #define CONFIG_RTL_TRACER */
+
+/* event ids */
+enum { RTL_TRACE_STOP_INTERRUPTS = 1, RTL_TRACE_ALLOW_INTERRUPTS = 2,
+ RTL_TRACE_SAVE_INTERRUPTS = 4, RTL_TRACE_RESTORE_INTERRUPTS = 8,
+ RTL_TRACE_NO_INTERRUPTS = 16,
+ RTL_TRACE_SMP_INTERCEPT = 32, RTL_TRACE_SMP_INTERCEPT_EXIT = 64,
+ RTL_TRACE_USER = 128, RTL_TRACE_SPIN_LOCK = 256, RTL_TRACE_SPIN_UNLOCK = 512, RTL_TRACE_INTERCEPT = 1024, RTL_TRACE_INTERCEPT_EXIT = 2048,
+ RTL_TRACE_USER2 = 4096};
+
+#define RTL_TRACE_ALL 0xffffffff
+
+
+#ifdef CONFIG_RTL_TRACER
+extern void (*rtl_trace)(int event_id, long event_data, long eip);
+
+#define rtl_trace2(event_id, event_data) \
+do { \
+ long eip; \
+ __asm__("1: mov $1b, %%eax" : "=a" (eip) : ); \
+ rtl_trace(event_id, event_data, eip); \
+} while (0)
+
+#define rtl_trace2a(event_id, event_data) \
+do { \
+ long eip; \
+ __asm__("mov $1f, %%eax" : "=a" (eip) : ); \
+ rtl_trace(event_id, event_data, eip); \
+ __asm__("1:" : : ); \
+} while (0)
+
+#else
+
+#define rtl_trace(event_id, event_data, eip)
+#define rtl_trace2(event_id, event_data)
+#define rtl_trace2a(event_id, event_data)
+#endif
+
+#endif
Index: linux22/init/main.c
diff -u linux22/init/main.c:1.1.1.3 linux22/init/main.c:1.4
--- linux22/init/main.c:1.1.1.3 Wed Jan 5 19:27:34 2000
+++ linux22/init/main.c Wed Jan 5 23:57:21 2000
@@ -1202,6 +1202,9 @@
#endif
extern void initialize_secondary(void);
+#ifdef CONFIG_RTL
+extern void rtl_init(void);
+#endif
/*
* Activate the first processor.
@@ -1292,6 +1295,10 @@
* make syscalls (and thus be locked).
*/
smp_init();
+#ifdef CONFIG_RTL
+ rtl_init();
+ sti();
+#endif
kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
current->need_resched = 1;
cpu_idle(NULL);
Index: linux22/kernel/Makefile
diff -u linux22/kernel/Makefile:1.1.1.1 linux22/kernel/Makefile:1.2
--- linux22/kernel/Makefile:1.1.1.1 Thu Aug 12 22:05:32 1999
+++ linux22/kernel/Makefile Thu Aug 12 22:12:37 1999
@@ -15,6 +15,10 @@
module.o exit.o itimer.o info.o time.o softirq.o resource.o \
sysctl.o acct.o capability.o
+ifdef CONFIG_RTL
+O_OBJS += rtl.o
+endif
+
OX_OBJS += signal.o
ifeq ($(CONFIG_KMOD),y)
Index: linux22/kernel/ksyms.c
diff -u linux22/kernel/ksyms.c:1.1.1.3 linux22/kernel/ksyms.c:1.10
--- linux22/kernel/ksyms.c:1.1.1.3 Wed Jan 5 19:27:34 2000
+++ linux22/kernel/ksyms.c Tue Jan 11 00:01:17 2000
@@ -422,5 +422,53 @@
/* library functions */
EXPORT_SYMBOL(strnicmp);
+#ifdef __RTL__
+/* functions needed for RTL */
+#include <linux/rtl_trace.h>
+
+#ifdef CONFIG_RTL_TRACER
+EXPORT_SYMBOL(rtl_trace);
+#endif
+
+#include <asm/system.h>
+#include <linux/rtl.h>
+EXPORT_SYMBOL(__cli);
+EXPORT_SYMBOL(__sti);
+EXPORT_SYMBOL(__return_flags);
+EXPORT_SYMBOL(__restore_flags);
+
+#ifdef __SMP__
+EXPORT_SYMBOL(smp_found_config);
+#endif
+
+extern void conpr(const char * b);
+extern void rtl_hard_enable_irq(int );
+extern void rtl_hard_disable_irq(int );
+EXPORT_SYMBOL(conpr);
+EXPORT_SYMBOL(rtl_request_global_irq);
+EXPORT_SYMBOL(rtl_free_global_irq);
+EXPORT_SYMBOL(rtl_global_pend_irq);
+EXPORT_SYMBOL(rtl_global_ispending_irq);
+EXPORT_SYMBOL(tick);
+EXPORT_SYMBOL(rtl_get_soft_irq);
+EXPORT_SYMBOL(rtl_hard_enable_irq);
+EXPORT_SYMBOL(rtl_hard_disable_irq);
+#ifdef __SMP__
+EXPORT_SYMBOL(rtl_request_local_irq);
+EXPORT_SYMBOL(rtl_free_local_irq);
+EXPORT_SYMBOL(rtl_local_pend_vec);
+#endif
+
+#include <linux/vt_kern.h>
+EXPORT_SYMBOL(kd_mksound);
+
+EXPORT_SYMBOL(rtl_rt_system_is_idle);
+EXPORT_SYMBOL(rtl_make_rt_system_active);
+EXPORT_SYMBOL(rtl_make_rt_system_idle);
+#ifdef __SMP__
+EXPORT_SYMBOL(rtl_reschedule);
+#endif
+#endif /* __RTL__ */
+
/* init task, for moving kthread roots - ought to export a function ?? */
EXPORT_SYMBOL(init_task_union);
Index: linux22/kernel/rtl.c
diff -u /dev/null linux22/kernel/rtl.c:1.3
--- /dev/null Fri Feb 11 20:04:25 2000
+++ linux22/kernel/rtl.c Mon Jan 3 10:15:49 2000
@@ -0,0 +1,52 @@
+
+/* REAL TIME LINUX
+ Right now this is just for the proc entry
+
+ (c) Victor Yodaiken August 1998, GPL
+ */
+#include <linux/kernel.h>
+/* #include <linux/rtl_version.h> */
+#include <linux/version.h>
+
+#include <linux/mm.h>
+#include <linux/tty_driver.h>
+#include <linux/smp_lock.h>
+#include <linux/console.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <linux/cons.h>
+#include <linux/console.h>
+#include <asm/spinlock.h>
+#include <asm/rtl_sync.h>
+#include <stdarg.h>
+
+
+int get_rtl_status(char *buf)
+{
+ return(sprintf(buf, "RT-Linux version %s\n", UTS_RELEASE));
+}
+
+
+extern struct console *console_drivers;
+
+void conpr(const char *s)
+{
+ long flags;
+ static spinlock_t rtl_conpr_lock = SPIN_LOCK_UNLOCKED;
+ struct console *c;
+ int len = strlen(s);
+
+ rtl_hard_savef_and_cli(flags);
+ spin_lock(&rtl_conpr_lock);
+
+ c = console_drivers;
+ while(c) {
+ if ((c->flags & CON_ENABLED) && c->write)
+ c->write(c, s, len);
+ c = c->next;
+ }
+ spin_unlock(&rtl_conpr_lock);
+ rtl_hard_restore_flags(flags);
+}
+