Indentation fix, cleanup.
[AROS.git] / rom / exec / cause.c
blob206d20207df1ed62a694a006d7708ac4a519c43e
1 /*
2 Copyright © 1995-2011, 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>
12 #include <proto/kernel.h>
14 #include "chipset.h"
15 #include "exec_intern.h"
17 /*****************************************************************************
19 NAME */
20 #include <exec/interrupts.h>
21 #include <proto/exec.h>
23 AROS_LH1(void, Cause,
25 /* SYNOPSIS */
26 AROS_LHA(struct Interrupt *, softint, A1),
28 /* LOCATION */
29 struct ExecBase *, SysBase, 30, Exec)
31 /* FUNCTION
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_INTC1(YourIntCode, APTR, interruptData)
52 The interruptData is the value of the is_Data field.
54 INPUTS
55 softint - The interrupt you wish to schedule. When setting up
56 you should set the type of the interrupt to either
57 NT_INTERRUPT or NT_UNKNOWN.
59 RESULT
60 The software interrupt will be delivered, or queued for later
61 delivery.
63 NOTES
64 No bounds checking on the software interrupt priority is done.
65 Passing a bad priority to the system can have a strange effect.
67 EXAMPLE
69 BUGS
70 Older versions of the Amiga operating system require that the
71 software interrupts preserve the A6 register.
73 Software interrupts which are added from a software interrupt of
74 lower priority may not be called immediately.
76 SEE ALSO
78 INTERNALS
80 ******************************************************************************/
82 AROS_LIBFUNC_INIT
84 UBYTE pri;
86 Disable();
88 /* Check to ensure that this node is not already in a list. */
89 if (softint->is_Node.ln_Type != NT_SOFTINT)
91 /* Scale the priority down to a number between 0 and 4 inclusive
92 We can use that to index into exec's software interrupt lists. */
93 pri = (softint->is_Node.ln_Pri + 0x20)>>4;
95 /* We are accessing an Exec list, protect ourselves. */
96 ADDTAIL(&SysBase->SoftInts[pri].sh_List, &softint->is_Node);
97 softint->is_Node.ln_Type = NT_SOFTINT;
99 /* Signal pending software interrupt condition */
100 SysBase->SysFlags |= SFF_SoftInt;
103 * Quick soft int request. For optimal performance m68k-amiga
104 * Enable() does not do any extra SFF_SoftInt checks
106 CUSTOM_CAUSE(INTF_SOFTINT);
108 * If we are in usermode the software interrupt will end up being triggered
109 * in Enable(). On Amiga hardware this happens because a hardware interrupt
110 * was queued. On other machines Enable() will simulate this behavior,
111 * looking at SFF_SoftInt flag.
114 Enable();
116 AROS_LIBFUNC_EXIT
117 } /* Cause() */
120 This is the dispatcher for software interrupts. We go through the
121 lists and remove the interrupts before calling them. Because we
122 can be interrupted we should not cache the next pointer, but
123 retreive it from ExecBase each time.
125 Note: All these arguments are passed to the function, so you must
126 at least declare all of them. You do not however have to use any
127 of them (although that is recommended).
129 This procedure could be more efficient.
132 AROS_INTH0(SoftIntDispatch)
134 AROS_INTFUNC_INIT
136 struct Interrupt *intr = NULL;
137 BYTE i;
139 /* disable soft ints temporarily */
140 CUSTOM_ACK(INTF_SOFTINT);
142 /* Don't bother if there are no software ints queued. */
143 if( SysBase->SysFlags & SFF_SoftInt )
145 /* Clear Software interrupt pending flag. */
146 SysBase->SysFlags &= ~(SFF_SoftInt);
148 for(;;)
150 for(i=4; i>=0; i--)
153 * This KrnCli() is needed because we could re-enter here after one handler has already
154 * been executed. In this case interrupts have been enabled before calling the handler.
156 KrnCli();
157 intr = (struct Interrupt *)RemHead(&SysBase->SoftInts[i].sh_List);
159 if (intr)
161 intr->is_Node.ln_Type = NT_INTERRUPT;
164 * SoftInt handlers are called with interrupts enabled,
165 * this is how original AmigaOS(tm) works
167 KrnSti();
169 /* Call the software interrupt. */
170 AROS_INTC1(intr->is_Code, intr->is_Data);
172 /* Get out and start loop *all* over again *from scratch*! */
173 break;
176 if (!intr)
179 * We executed KrnCli() and attempted to fetch a request from the list,
180 * but the list was empty.
181 * We are going to exit, but before this we need to re-enable
182 * interrupts. Otherwise we exit this vector with disabled interrupts,
183 * screwing things up.
185 KrnSti();
186 break;
191 /* re-enable soft ints */
192 CUSTOM_ENABLE(INTB_SOFTINT);
194 return FALSE;
196 AROS_INTFUNC_EXIT