2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
5 Desc: Cause() - Cause a software interrupt.
9 #include <exec/execbase.h>
10 #include <aros/asmcall.h>
11 #include <hardware/custom.h>
12 #include <hardware/intbits.h>
13 #include <proto/kernel.h>
15 #include "exec_intern.h"
17 /*****************************************************************************
20 #include <exec/interrupts.h>
21 #include <proto/exec.h>
26 AROS_LHA(struct Interrupt
*, softint
, A1
),
29 struct ExecBase
*, SysBase
, 30, Exec
)
32 Schedule a software interrupt to occur. If the processor is
33 currently running a user task, then the software interrupt will
34 prempt the current task and run itself. From a real interrupt, it
35 will queue the software interrupt for a later time.
37 Software interrupts are useful from hardware interrupts if you
38 wish to defer your processing down to a lower level. They can
39 also be used in some special cases of device I/O. The timer.device
40 and audio.device allow software interrupt driven timing and
41 audio output respectively.
43 Software interrupts are restricted to 5 different priority levels,
44 +32, +16, 0, -16, -32.
46 Software interrupts can only be scheduled once.
48 The software interrupt is called with the following prototype:
50 AROS_UFH3(void, YourIntCode,
51 AROS_UFHA(APTR, interruptData, A1),
52 AROS_UFHA(APTR, interruptCode, A5),
53 AROS_UFHA(struct ExecBase *, SysBase, A6))
55 The interruptData is the value of the is_Data field, interruptCode
56 is the value of the is_Code field - it is included for historical
57 and compatibility reasons. You can ignore the value of interruptCode,
58 but you must declare it.
61 softint - The interrupt you wish to schedule. When setting up
62 you should set the type of the interrupt to either
63 NT_INTERRUPT or NT_UNKNOWN.
66 The software interrupt will be delivered, or queued for later
70 No bounds checking on the software interrupt priority is done.
71 Passing a bad priority to the system can have a strange effect.
76 Older versions of the Amiga operating system require that the
77 software interrupts preserve the A6 register.
79 Software interrupts which are added from a software interrupt of
80 lower priority may not be called immediately.
86 ******************************************************************************/
93 /* Check to ensure that this node is not already in a list. */
94 if( softint
->is_Node
.ln_Type
!= NT_SOFTINT
)
96 /* Scale the priority down to a number between 0 and 4 inclusive
97 We can use that to index into exec's software interrupt lists. */
98 pri
= (softint
->is_Node
.ln_Pri
+ 0x20)>>4;
100 /* We are accessing an Exec list, protect ourselves. */
101 ADDTAIL(&SysBase
->SoftInts
[pri
].sh_List
, &softint
->is_Node
);
102 softint
->is_Node
.ln_Type
= NT_SOFTINT
;
103 SysBase
->SysFlags
|= SFF_SoftInt
;
104 #if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT) && defined(__mc68000)
106 /* Quick soft int request. For optimal performance m68k-amiga
107 * Enable() does not do any extra SFF_SoftInt checks */
108 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
109 custom
->intreq
= INTF_SETCLR
| INTF_SOFTINT
;
112 /* If we are in usermode the software interrupt will end up
113 being triggered in Enable(). See Enable() code */
122 This is the dispatcher for software interrupts. We go through the
123 lists and remove the interrupts before calling them. Because we
124 can be interrupted we should not cache the next pointer, but
125 retreive it from ExecBase each time.
127 Note: All these arguments are passed to the function, so you must
128 at least declare all of them. You do not however have to use any
129 of them (although that is recommended).
131 This procedure could be more efficient.
134 AROS_UFH5(void, SoftIntDispatch
,
135 AROS_UFHA(ULONG
, intReady
, D1
),
136 AROS_UFHA(volatile struct Custom
*, custom
, A0
),
137 AROS_UFHA(IPTR
, intData
, A1
),
138 AROS_UFHA(ULONG_FUNC
, intCode
, A5
),
139 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
143 struct Interrupt
*intr
= NULL
;
146 #if defined(__mc68000)
147 /* If we are working on classic Amiga(tm), we have valid custom chip pointer */
150 /* disable soft ints temporarily */
151 custom
->intena
= INTF_SOFTINT
;
153 custom
->intreq
= INTF_SOFTINT
;
157 /* Don't bother if there are no software ints queued. */
158 if( SysBase
->SysFlags
& SFF_SoftInt
)
160 /* Clear Software interrupt pending flag. */
161 SysBase
->SysFlags
&= ~(SFF_SoftInt
);
168 * This KrnCli() is needed because we could re-enter here after one handler has already
169 * been executed. In this case interrupts have been enabled before calling the handler.
172 intr
= (struct Interrupt
*)RemHead(&SysBase
->SoftInts
[i
].sh_List
);
176 intr
->is_Node
.ln_Type
= NT_INTERRUPT
;
179 * SoftInt handlers are called with interrupts enabled,
180 * this is how original AmigaOS(tm) works
184 /* Call the software interrupt. */
185 AROS_UFC3(void, intr
->is_Code
,
186 AROS_UFCA(APTR
, intr
->is_Data
, A1
),
187 AROS_UFCA(APTR
, intr
->is_Code
, A5
),
188 AROS_UFCA(struct ExecBase
*, SysBase
, A6
));
190 /* Get out and start loop *all* over again *from scratch*! */
197 * We executed KrnCli() and attempted to fetch a request from the list,
198 * but the list was empty.
199 * We are going to exit, but before this we need to re-enable
200 * interrupts. Otherwise we exit this vector with disabled interrupts,
201 * screwing things up.
209 #if defined(__mc68000)
210 /* re-enable soft ints */
212 custom
->intena
= INTF_SETCLR
| INTF_SOFTINT
;