revert between 56095 -> 55830 in arch
[AROS.git] / arch / .unmaintained / arm-all / exec / cause.c
blobc4023e675747250cffad57dc9e4cc58931dec4fe
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Plam Version of Cause(); taken from i386native version of Cause().
6 Lang: english
7 */
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;
24 AROS_LH1(void, Cause,
25 AROS_LHA(struct Interrupt *, softint, A1),
26 struct ExecBase *, SysBase, 30, Exec)
28 AROS_LIBFUNC_INIT
30 UBYTE pri;
32 /* Check to ensure that this node is not already in a list. */
33 if( softint->is_Node.ln_Type != NT_SOFTINT )
35 /* Scale the priority down to a number between 0 and 4 inclusive
36 We can use that to index into exec's software interrupt lists. */
37 pri = (softint->is_Node.ln_Pri + 0x20) >> 4;
39 /* We are accessing an Exec list, protect ourselves. */
40 Disable();
41 AddTail((struct List *)&SysBase->SoftInts[pri], (struct Node *)softint);
42 softint->is_Node.ln_Type = NT_SOFTINT;
43 SysBase->SysFlags |= SFF_SoftInt;
44 Enable();
46 if (!softblock)
48 /* If we are in supervisor mode we simply call InterruptServer.
49 Cause software interrupt (int 0x80) otherwise */
50 #if 0
51 if (get_cs())
53 /* Called from user mode. We can do Cause in normal way */
54 __asm__ __volatile__ ("movl $0,%%eax\n\tint $0x80":::"eax","memory");
56 else
57 #endif
59 /* Cause() inside supervisor mode. We will call IntServer directly
60 no matter it is normal irq or Supervisor() call */
61 struct IntVector *iv;
62 iv = &SysBase->IntVects[INTB_SOFTINT];
64 if (iv->iv_Code)
66 AROS_UFC5(void, iv->iv_Code,
67 AROS_UFCA(ULONG, 0, D1),
68 AROS_UFCA(ULONG, 0, A0),
69 AROS_UFCA(APTR, NULL, A1),
70 AROS_UFCA(APTR, iv->iv_Code, A5),
71 AROS_UFCA(struct ExecBase *, SysBase, A6)
78 AROS_LIBFUNC_EXIT
79 } /* Cause() */
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)
90 struct IntVector *iv;
92 #if 0
93 /* Hmm, interrupts are nesting, not a good idea... */
94 if(!user_mode(regs)) {
95 #if NOISY
96 kprintf("Illegal Supervisor\n");
97 #endif
98 return;
100 #endif
101 iv = &SysBase->IntVects[INTB_SOFTINT];
103 if (iv->iv_Code)
105 /* Call it. I call with all these parameters for a reason.
107 In my `Amiga ROM Kernel Reference Manual: Libraries and
108 Devices' (the 1.3 version), interrupt servers are called
109 with the following 5 parameters.
111 D1 - Mask of INTENAR and INTREQR
112 A0 - 0xDFF000 (base of custom chips)
113 A1 - Interrupt Data
114 A5 - Interrupt Code vector
115 A6 - SysBase
117 It is quite possible that some code uses all of these, so
118 I must supply them here. Obviously I will dummy some of these
119 though.
121 AROS_UFC5(void, iv->iv_Code,
122 AROS_UFCA(ULONG, 0, D1),
123 AROS_UFCA(ULONG, 0, A0),
124 AROS_UFCA(APTR, regs, A1),
125 AROS_UFCA(APTR, iv->iv_Code, A5),
126 AROS_UFCA(struct ExecBase *, SysBase, A6)
130 /* Has an interrupt told us to dispatch when leaving */
131 if (SysBase->AttnResched & 0x8000)
133 SysBase->AttnResched &= ~0x8000;
135 /* Save registers for this task (if there is one...) */
136 if (SysBase->ThisTask && SysBase->ThisTask->tc_State != TS_REMOVED)
137 SaveRegs(SysBase->ThisTask, regs);
139 /* Tell exec that we have actually switched tasks... */
140 Dispatch ();
142 /* Get the registers of the old task */
143 RestoreRegs(SysBase->ThisTask, regs);
145 /* Make sure that the state of the interrupts is what the task
146 expects.
148 #if 0
149 if (SysBase->IDNestCnt < 0)
150 SC_ENABLE(regs);
151 else
152 SC_DISABLE(regs);
153 #endif
154 /* Ok, the next step is to either drop back to the new task, or
155 give it its Exception() if it wants one... */
157 if (SysBase->ThisTask->tc_Flags & TF_EXCEPT)
159 Disable();
160 Exception();
161 Enable();
165 #if DEBUG_TT
166 if (lastTask != SysBase->ThisTask)
168 kprintf (stderr, "TT %s\n", SysBase->ThisTask->tc_Node.ln_Name);
169 lastTask = SysBase->ThisTask;
171 #endif
174 /* Leave the interrupt. */
177 #undef SysBase
180 This is the dispatcher for software interrupts. We go through the
181 lists and remove the interrupts before calling them. Because we
182 can be interrupted we should not cache the next pointer, but
183 retreive it from ExecBase each time.
185 Note: All these arguments are passed to the structure, so you must
186 at least declare all of them. You do not however have to use any
187 of them (although that is recommended).
189 This procedure could be more efficient, and it has to be implemented
190 in the kernel.
193 AROS_UFH5(void, SoftIntDispatch,
194 AROS_UFHA(ULONG, intReady, D1),
195 AROS_UFHA(struct Custom *, custom, A0),
196 AROS_UFHA(IPTR, intData, A1),
197 AROS_UFHA(IPTR, intCode, A5),
198 AROS_UFHA(struct ExecBase *, SysBase, A6))
200 struct Interrupt *intr;
201 UBYTE i;
203 if( SysBase->SysFlags & SFF_SoftInt )
205 /* Disable software interrupts */
206 softblock = 1;
208 /* Clear the Software interrupt pending flag. */
209 SysBase->SysFlags &= ~(SFF_SoftInt);
211 for(i=0; i < 4; i++)
213 while( (intr = (struct Interrupt *)RemHead((struct List *)&SysBase->SoftInts[i])) )
215 intr->is_Node.ln_Type = NT_INTERRUPT;
217 /* Call the software interrupt. */
218 AROS_UFC3(void, intr->is_Code,
219 AROS_UFCA(APTR, intr->is_Data, A1),
220 AROS_UFCA(APTR, intr->is_Code, A5),
221 AROS_UFCA(struct ExecBase *, SysBase, A6));
225 /* We now re-enable software interrupts. */
226 softblock = 0;