Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / rom / exec / cause.c
blobb757ed2dd7194451b0a6eb2af0e91bdad8bf001d
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 <aros/config.h>
11 #include <exec/execbase.h>
12 #include <hardware/custom.h>
13 #include <hardware/intbits.h>
14 #include <proto/kernel.h>
16 #include "exec_intern.h"
18 /*****************************************************************************
20 NAME */
21 #include <exec/interrupts.h>
22 #include <proto/exec.h>
24 AROS_LH1(void, Cause,
26 /* SYNOPSIS */
27 AROS_LHA(struct Interrupt *, softint, A1),
29 /* LOCATION */
30 struct ExecBase *, SysBase, 30, Exec)
32 /* FUNCTION
33 Schedule a software interrupt to occur. If the processor is
34 currently running a user task, then the software interrupt will
35 prempt the current task and run itself. From a real interrupt, it
36 will queue the software interrupt for a later time.
38 Software interrupts are useful from hardware interrupts if you
39 wish to defer your processing down to a lower level. They can
40 also be used in some special cases of device I/O. The timer.device
41 and audio.device allow software interrupt driven timing and
42 audio output respectively.
44 Software interrupts are restricted to 5 different priority levels,
45 +32, +16, 0, -16, -32.
47 Software interrupts can only be scheduled once.
49 The software interrupt is called with the following prototype:
51 AROS_UFH3(void, YourIntCode,
52 AROS_UFHA(APTR, interruptData, A1),
53 AROS_UFHA(APTR, interruptCode, A5),
54 AROS_UFHA(struct ExecBase *, SysBase, A6))
56 The interruptData is the value of the is_Data field, interruptCode
57 is the value of the is_Code field - it is included for historical
58 and compatibility reasons. You can ignore the value of interruptCode,
59 but you must declare it.
61 INPUTS
62 softint - The interrupt you wish to schedule. When setting up
63 you should set the type of the interrupt to either
64 NT_INTERRUPT or NT_UNKNOWN.
66 RESULT
67 The software interrupt will be delivered, or queued for later
68 delivery.
70 NOTES
71 No bounds checking on the software interrupt priority is done.
72 Passing a bad priority to the system can have a strange effect.
74 EXAMPLE
76 BUGS
77 Older versions of the Amiga operating system require that the
78 software interrupts preserve the A6 register.
80 Software interrupts which are added from a software interrupt of
81 lower priority may not be called immediately.
83 SEE ALSO
85 INTERNALS
87 ******************************************************************************/
89 AROS_LIBFUNC_INIT
91 UBYTE pri;
93 Disable();
94 /* Check to ensure that this node is not already in a list. */
95 if( softint->is_Node.ln_Type != NT_SOFTINT )
97 /* Scale the priority down to a number between 0 and 4 inclusive
98 We can use that to index into exec's software interrupt lists. */
99 pri = (softint->is_Node.ln_Pri + 0x20)>>4;
101 /* We are accessing an Exec list, protect ourselves. */
102 ADDTAIL(&SysBase->SoftInts[pri].sh_List, &softint->is_Node);
103 softint->is_Node.ln_Type = NT_SOFTINT;
104 SysBase->SysFlags |= SFF_SoftInt;
105 #if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT) && defined(__mc68000)
107 /* Quick soft int request. For optimal performance m68k-amiga
108 * Enable() does not do any extra SFF_SoftInt checks */
109 volatile struct Custom *custom = (struct Custom*)0xdff000;
110 custom->intreq = INTF_SETCLR | INTF_SOFTINT;
112 #else
113 /* If we are in usermode the software interrupt will end up
114 being triggered in Enable(). See Enable() code */
115 #endif
117 Enable();
119 AROS_LIBFUNC_EXIT
120 } /* Cause() */
123 This is the dispatcher for software interrupts. We go through the
124 lists and remove the interrupts before calling them. Because we
125 can be interrupted we should not cache the next pointer, but
126 retreive it from ExecBase each time.
128 Note: All these arguments are passed to the function, so you must
129 at least declare all of them. You do not however have to use any
130 of them (although that is recommended).
132 This procedure could be more efficient.
135 AROS_UFH5(void, SoftIntDispatch,
136 AROS_UFHA(ULONG, intReady, D1),
137 AROS_UFHA(volatile struct Custom *, custom, A0),
138 AROS_UFHA(IPTR, intData, A1),
139 AROS_UFHA(ULONG_FUNC, intCode, A5),
140 AROS_UFHA(struct ExecBase *, SysBase, A6))
142 AROS_USERFUNC_INIT
144 struct Interrupt *intr = NULL;
145 BYTE i;
147 #if defined(__mc68000)
148 /* If we are working on classic Amiga(tm), we have valid custom chip pointer */
149 if (custom)
151 /* disable soft ints temporarily */
152 custom->intena = INTF_SOFTINT;
153 /* clear request */
154 custom->intreq = INTF_SOFTINT;
156 #endif
158 /* Don't bother if there are no software ints queued. */
159 if( SysBase->SysFlags & SFF_SoftInt )
161 /* Clear Software interrupt pending flag. */
162 SysBase->SysFlags &= ~(SFF_SoftInt);
164 for(;;)
166 for(i=4; i>=0; i--)
169 * This KrnCli() is needed because we could re-enter here after one handler has already
170 * been executed. In this case interrupts have been enabled before calling the handler.
172 KrnCli();
173 intr = (struct Interrupt *)RemHead(&SysBase->SoftInts[i].sh_List);
175 if (intr)
177 intr->is_Node.ln_Type = NT_INTERRUPT;
180 * SoftInt handlers are called with interrupts enabled,
181 * this is how original AmigaOS(tm) works
183 KrnSti();
185 /* Call the software interrupt. */
186 AROS_UFC3(void, intr->is_Code,
187 AROS_UFCA(APTR, intr->is_Data, A1),
188 AROS_UFCA(APTR, intr->is_Code, A5),
189 AROS_UFCA(struct ExecBase *, SysBase, A6));
191 /* Get out and start loop *all* over again *from scratch*! */
192 break;
195 if (!intr)
198 * We executed KrnCli() and attempted to fetch a request from the list,
199 * but the list was empty.
200 * We are going to exit, but before this we need to re-enable
201 * interrupts. Otherwise we exit this vector with disabled interrupts,
202 * screwing things up.
204 KrnSti();
205 break;
210 #if defined(__mc68000)
211 /* re-enable soft ints */
212 if (custom)
213 custom->intena = INTF_SETCLR | INTF_SOFTINT;
214 #endif
216 AROS_USERFUNC_EXIT