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_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
)
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
)
98 struct ExecBase
* SysBase
= 0x04;
100 /* Hmm, interrupts are nesting, not a good idea... */
101 if(!user_mode(regs
)) {
103 kprintf("Illegal Supervisor\n");
108 iv
= &SysBase
->IntVects
[INTB_SOFTINT
];
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)
121 A5 - Interrupt Code vector
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
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... */
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
156 if (SysBase
->IDNestCnt
< 0)
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
)
173 if (lastTask
!= SysBase
->ThisTask
)
175 kprintf (stderr
, "TT %s\n", SysBase
->ThisTask
->tc_Node
.ln_Name
);
176 lastTask
= SysBase
->ThisTask
;
181 /* Leave the interrupt. */
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
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
))
209 struct Interrupt
*intr
;
212 if( SysBase
->SysFlags
& SFF_SoftInt
)
214 /* Disable software interrupts */
217 /* Clear the Software interrupt pending flag. */
218 SysBase
->SysFlags
&= ~(SFF_SoftInt
);
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. */