we aren't in forbid state on the smp build..
[AROS.git] / rom / exec / cause.c
blob5974ce915c7764ae41f2c56fde8f33dc8be8b43d
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Cause() - Cause a software interrupt.
6 Lang: english
7 */
9 #include <aros/asmcall.h>
10 #include <exec/execbase.h>
11 #include <hardware/intbits.h>
13 #include "chipset.h"
14 #include "exec_intern.h"
16 /*****************************************************************************
18 NAME */
19 #include <exec/interrupts.h>
20 #include <proto/exec.h>
22 AROS_LH1(void, Cause,
24 /* SYNOPSIS */
25 AROS_LHA(struct Interrupt *, softint, A1),
27 /* LOCATION */
28 struct ExecBase *, SysBase, 30, Exec)
30 /* FUNCTION
31 Schedule a software interrupt to occur. If the processor is
32 currently running a user task, then the software interrupt will
33 prempt the current task and run itself. From a real interrupt, it
34 will queue the software interrupt for a later time.
36 Software interrupts are useful from hardware interrupts if you
37 wish to defer your processing down to a lower level. They can
38 also be used in some special cases of device I/O. The timer.device
39 and audio.device allow software interrupt driven timing and
40 audio output respectively.
42 Software interrupts are restricted to 5 different priority levels,
43 +32, +16, 0, -16, -32.
45 Software interrupts can only be scheduled once.
47 The software interrupt is called with the following prototype:
49 AROS_INTC1(YourIntCode, APTR, interruptData)
51 The interruptData is the value of the is_Data field.
53 INPUTS
54 softint - The interrupt you wish to schedule. When setting up
55 you should set the type of the interrupt to either
56 NT_INTERRUPT or NT_UNKNOWN.
58 RESULT
59 The software interrupt will be delivered, or queued for later
60 delivery.
62 NOTES
63 No bounds checking on the software interrupt priority is done.
64 Passing a bad priority to the system can have a strange effect.
66 EXAMPLE
68 BUGS
69 Older versions of the Amiga operating system require that the
70 software interrupts preserve the A6 register.
72 Software interrupts which are added from a software interrupt of
73 lower priority may not be called immediately.
75 SEE ALSO
77 INTERNALS
79 ******************************************************************************/
81 AROS_LIBFUNC_INIT
83 UBYTE pri;
85 Disable();
87 /* Check to ensure that this node is not already in a list. */
88 if (softint->is_Node.ln_Type != NT_SOFTINT)
90 /* Scale the priority down to a number between 0 and 4 inclusive
91 We can use that to index into exec's software interrupt lists. */
92 pri = (softint->is_Node.ln_Pri + 0x20)>>4;
94 /* We are accessing an Exec list, protect ourselves. */
95 ADDTAIL(&SysBase->SoftInts[pri].sh_List, &softint->is_Node);
96 softint->is_Node.ln_Type = NT_SOFTINT;
98 /* Signal pending software interrupt condition */
99 SysBase->SysFlags |= SFF_SoftInt;
102 * Quick soft int request. For optimal performance m68k-amiga
103 * Enable() does not do any extra SFF_SoftInt checks
105 CUSTOM_CAUSE(INTF_SOFTINT);
107 * If we are in usermode the software interrupt will end up being triggered
108 * in Enable(). On Amiga hardware this happens because a hardware interrupt
109 * was queued. On other machines Enable() will simulate this behavior,
110 * looking at SFF_SoftInt flag.
113 Enable();
115 AROS_LIBFUNC_EXIT
116 } /* Cause() */
119 This is the dispatcher for software interrupts. We go through the
120 lists and remove the interrupts before calling them. Because we
121 can be interrupted we should not cache the next pointer, but
122 retreive it from ExecBase each time.
124 Note: All these arguments are passed to the function, so you must
125 at least declare all of them. You do not however have to use any
126 of them (although that is recommended).
128 This procedure could be more efficient.
131 AROS_INTH0(SoftIntDispatch)
133 AROS_INTFUNC_INIT
135 struct Interrupt *intr = NULL;
136 BYTE i;
138 /* disable soft ints temporarily */
139 CUSTOM_ACK(INTF_SOFTINT);
141 /* Don't bother if there are no software ints queued. */
142 if( SysBase->SysFlags & SFF_SoftInt )
144 /* Clear Software interrupt pending flag. */
145 SysBase->SysFlags &= ~(SFF_SoftInt);
147 for(;;)
149 for(i=4; i>=0; i--)
152 * This KrnCli() is needed because we could re-enter here after one handler has already
153 * been executed. In this case interrupts have been enabled before calling the handler.
155 KrnCli();
156 intr = (struct Interrupt *)RemHead(&SysBase->SoftInts[i].sh_List);
158 if (intr)
160 intr->is_Node.ln_Type = NT_INTERRUPT;
163 * SoftInt handlers are called with interrupts enabled,
164 * this is how original AmigaOS(tm) works
166 KrnSti();
168 /* Call the software interrupt. */
169 AROS_INTC1(intr->is_Code, intr->is_Data);
171 /* Get out and start loop *all* over again *from scratch*! */
172 break;
175 if (!intr)
178 * We executed KrnCli() and attempted to fetch a request from the list,
179 * but the list was empty.
180 * We are going to exit, but before this we need to re-enable
181 * interrupts. Otherwise we exit this vector with disabled interrupts,
182 * screwing things up.
184 KrnSti();
185 break;
190 /* re-enable soft ints */
191 CUSTOM_ENABLE(INTB_SOFTINT);
193 return FALSE;
195 AROS_INTFUNC_EXIT