make the linux-ppc packags be in synch with other platforms
[tangerine.git] / arch / m68k-mac / exec / cause.c
blob390ab0036af62e1cb17a8bc1ab9ccae3340f6c94
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;
23 #if 0
24 #define get_cs() \
25 ({ short __value; \
26 __asm__ __volatile__ ("mov %%ds,%%ax":"=a"(__value)); \
27 (__value & 0x03); })
28 #endif
30 AROS_LH1(void, Cause,
31 AROS_LHA(struct Interrupt *, softint, A1),
32 struct ExecBase *, SysBase, 30, Exec)
34 AROS_LIBFUNC_INIT
36 UBYTE pri;
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. */
46 Disable();
47 AddTail((struct List *)&SysBase->SoftInts[pri], (struct Node *)softint);
48 softint->is_Node.ln_Type = NT_SOFTINT;
49 SysBase->SysFlags |= SFF_SoftInt;
50 Enable();
52 if (!softblock)
54 /* If we are in supervisor mode we simply call InterruptServer.
55 Cause software interrupt (int 0x80) otherwise */
56 #if 0
57 if (get_cs())
59 /* Called from user mode. We can do Cause in normal way */
60 __asm__ __volatile__ ("movl $0,%%eax\n\tint $0x80":::"eax","memory");
62 else
63 #endif
65 /* Cause() inside supervisor mode. We will call IntServer directly
66 no matter it is normal irq or Supervisor() call */
67 struct IntVector *iv;
68 iv = &SysBase->IntVects[INTB_SOFTINT];
70 if (iv->iv_Code)
72 AROS_UFC5(void, iv->iv_Code,
73 AROS_UFCA(ULONG, 0, D1),
74 AROS_UFCA(ULONG, 0, A0),
75 AROS_UFCA(APTR, NULL, A1),
76 AROS_UFCA(APTR, iv->iv_Code, A5),
77 AROS_UFCA(struct ExecBase *, SysBase, A6)
84 AROS_LIBFUNC_EXIT
85 } /* Cause() */
87 extern void SaveRegs(struct Task *task, struct pt_regs *regs);
88 extern void RestoreRegs(struct Task *task, struct pt_regs *regs);
90 //#define SC_ENABLE(regs) (regs.eflags |= 0x200)
91 //#define SC_DISABLE(regs) (regs.eflags &= ~0x200)
94 /*asmlinkage*/ void sys_Cause(struct pt_regs * regs)
96 struct IntVector *iv;
98 struct ExecBase * SysBase = 0x04;
100 /* Hmm, interrupts are nesting, not a good idea... */
101 if(!user_mode(regs)) {
102 #if NOISY
103 kprintf("Illegal Supervisor\n");
104 #endif
105 return;
108 iv = &SysBase->IntVects[INTB_SOFTINT];
110 if (iv->iv_Code)
112 /* Call it. I call with all these parameters for a reason.
114 In my `Amiga ROM Kernel Reference Manual: Libraries and
115 Devices' (the 1.3 version), interrupt servers are called
116 with the following 5 parameters.
118 D1 - Mask of INTENAR and INTREQR
119 A0 - 0xDFF000 (base of custom chips)
120 A1 - Interrupt Data
121 A5 - Interrupt Code vector
122 A6 - SysBase
124 It is quite possible that some code uses all of these, so
125 I must supply them here. Obviously I will dummy some of these
126 though.
128 AROS_UFC5(void, iv->iv_Code,
129 AROS_UFCA(ULONG, 0, D1),
130 AROS_UFCA(ULONG, 0, A0),
131 AROS_UFCA(APTR, regs, A1),
132 AROS_UFCA(APTR, iv->iv_Code, A5),
133 AROS_UFCA(struct ExecBase *, SysBase, A6)
137 /* Has an interrupt told us to dispatch when leaving */
138 if (SysBase->AttnResched & 0x8000)
140 SysBase->AttnResched &= ~0x8000;
142 /* Save registers for this task (if there is one...) */
143 if (SysBase->ThisTask && SysBase->ThisTask->tc_State != TS_REMOVED)
144 SaveRegs(SysBase->ThisTask, regs);
146 /* Tell exec that we have actually switched tasks... */
147 Dispatch ();
149 /* Get the registers of the old task */
150 RestoreRegs(SysBase->ThisTask, regs);
152 /* Make sure that the state of the interrupts is what the task
153 expects.
155 #if 0
156 if (SysBase->IDNestCnt < 0)
157 SC_ENABLE(regs);
158 else
159 SC_DISABLE(regs);
160 #endif
161 /* Ok, the next step is to either drop back to the new task, or
162 give it its Exception() if it wants one... */
164 if (SysBase->ThisTask->tc_Flags & TF_EXCEPT)
166 Disable();
167 Exception();
168 Enable();
172 #if DEBUG_TT
173 if (lastTask != SysBase->ThisTask)
175 kprintf (stderr, "TT %s\n", SysBase->ThisTask->tc_Node.ln_Name);
176 lastTask = SysBase->ThisTask;
178 #endif
181 /* Leave the interrupt. */
184 #undef SysBase
187 This is the dispatcher for software interrupts. We go through the
188 lists and remove the interrupts before calling them. Because we
189 can be interrupted we should not cache the next pointer, but
190 retreive it from ExecBase each time.
192 Note: All these arguments are passed to the structure, so you must
193 at least declare all of them. You do not however have to use any
194 of them (although that is recommended).
196 This procedure could be more efficient, and it has to be implemented
197 in the kernel.
200 AROS_UFH5(void, SoftIntDispatch,
201 AROS_UFHA(ULONG, intReady, D1),
202 AROS_UFHA(struct Custom *, custom, A0),
203 AROS_UFHA(IPTR, intData, A1),
204 AROS_UFHA(IPTR, intCode, A5),
205 AROS_UFHA(struct ExecBase *, SysBase, A6))
207 AROS_USERFUNC_INIT
209 struct Interrupt *intr;
210 UBYTE i;
212 if( SysBase->SysFlags & SFF_SoftInt )
214 /* Disable software interrupts */
215 softblock = 1;
217 /* Clear the Software interrupt pending flag. */
218 SysBase->SysFlags &= ~(SFF_SoftInt);
220 for(i=0; i < 4; i++)
222 while( (intr = (struct Interrupt *)RemHead((struct List *)&SysBase->SoftInts[i])) )
224 intr->is_Node.ln_Type = NT_INTERRUPT;
226 /* Call the software interrupt. */
227 AROS_UFC3(void, intr->is_Code,
228 AROS_UFCA(APTR, intr->is_Data, A1),
229 AROS_UFCA(APTR, intr->is_Code, A5),
230 AROS_UFCA(struct ExecBase *, SysBase, A6));
234 /* We now re-enable software interrupts. */
235 softblock = 0;
237 AROS_USERFUNC_EXIT