2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Plam Version of Cause(); taken from i386native version of Cause().
9 #include <exec/execbase.h>
10 #include <aros/asmcall.h>
11 #include <exec/interrupts.h>
12 #include <hardware/custom.h>
13 #include <hardware/intbits.h>
14 #include <proto/exec.h>
16 #include <exec_intern.h>
19 #include <exec/ptrace.h>
21 static char softblock
;
26 __asm__ __volatile__ ("mov %%ds,%%ax":"=a"(__value)); \
31 AROS_LHA(struct Interrupt
*, softint
, A1
),
32 struct ExecBase
*, SysBase
, 30, Exec
)
38 /* Check to ensure that this node is not already in a list. */
39 if( softint
->is_Node
.ln_Type
!= NT_SOFTINT
)
41 /* Scale the priority down to a number between 0 and 4 inclusive
42 We can use that to index into exec's software interrupt lists. */
43 pri
= (softint
->is_Node
.ln_Pri
+ 0x20) >> 4;
45 /* We are accessing an Exec list, protect ourselves. */
47 AddTail((struct List
*)&SysBase
->SoftInts
[pri
], (struct Node
*)softint
);
48 softint
->is_Node
.ln_Type
= NT_SOFTINT
;
49 SysBase
->SysFlags
|= SFF_SoftInt
;
54 /* If we are in supervisor mode we simply call InterruptServer.
55 Cause software interrupt (int 0x80) otherwise */
59 /* Called from user mode. We can do Cause in normal way */
60 __asm__
__volatile__ ("movl $0,%%eax\n\tint $0x80":::"eax","memory");
65 /* Cause() inside supervisor mode. We will call IntServer directly
66 no matter it is normal irq or Supervisor() call */
68 iv
= &SysBase
->IntVects
[INTB_SOFTINT
];
72 AROS_INTC1(iv
->iv_Code
, iv
->iv_Data
);
81 extern void SaveRegs(struct Task
*task
, struct pt_regs
*regs
);
82 extern void RestoreRegs(struct Task
*task
, struct pt_regs
*regs
);
84 //#define SC_ENABLE(regs) (regs.eflags |= 0x200)
85 //#define SC_DISABLE(regs) (regs.eflags &= ~0x200)
88 /*asmlinkage*/ void sys_Cause(struct pt_regs
* regs
)
92 struct ExecBase
* SysBase
= 0x04;
94 /* Hmm, interrupts are nesting, not a good idea... */
95 if(!user_mode(regs
)) {
97 kprintf("Illegal Supervisor\n");
102 iv
= &SysBase
->IntVects
[INTB_SOFTINT
];
107 AROS_INTC1(iv
->iv_Code
, regs
);
110 /* Has an interrupt told us to dispatch when leaving */
111 if (SysBase
->AttnResched
& 0x8000)
113 SysBase
->AttnResched
&= ~0x8000;
115 /* Save registers for this task (if there is one...) */
116 if (SysBase
->ThisTask
&& SysBase
->ThisTask
->tc_State
!= TS_REMOVED
)
117 SaveRegs(SysBase
->ThisTask
, regs
);
119 /* Tell exec that we have actually switched tasks... */
122 /* Get the registers of the old task */
123 RestoreRegs(SysBase
->ThisTask
, regs
);
125 /* Make sure that the state of the interrupts is what the task
129 if (SysBase
->IDNestCnt
< 0)
134 /* Ok, the next step is to either drop back to the new task, or
135 give it its Exception() if it wants one... */
137 if (SysBase
->ThisTask
->tc_Flags
& TF_EXCEPT
)
146 if (lastTask
!= SysBase
->ThisTask
)
148 kprintf (stderr
, "TT %s\n", SysBase
->ThisTask
->tc_Node
.ln_Name
);
149 lastTask
= SysBase
->ThisTask
;
154 /* Leave the interrupt. */
160 This is the dispatcher for software interrupts. We go through the
161 lists and remove the interrupts before calling them. Because we
162 can be interrupted we should not cache the next pointer, but
163 retreive it from ExecBase each time.
165 Note: All these arguments are passed to the structure, so you must
166 at least declare all of them. You do not however have to use any
167 of them (although that is recommended).
169 This procedure could be more efficient, and it has to be implemented
173 AROS_INTH0(SoftIntDispatch
)
177 struct Interrupt
*intr
;
180 if( SysBase
->SysFlags
& SFF_SoftInt
)
182 /* Disable software interrupts */
185 /* Clear the Software interrupt pending flag. */
186 SysBase
->SysFlags
&= ~(SFF_SoftInt
);
190 while( (intr
= (struct Interrupt
*)RemHead((struct List
*)&SysBase
->SoftInts
[i
])) )
192 intr
->is_Node
.ln_Type
= NT_INTERRUPT
;
194 /* Call the software interrupt. */
195 AROS_INTC1(intr
->is_Code
, intr
->is_Data
);
199 /* We now re-enable software interrupts. */