KallistiOS  ##version##
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
irq.h
Go to the documentation of this file.
1 /* KallistiOS ##version##
2 
3  arch/dreamcast/include/irq.h
4  Copyright (C) 2000-2001 Dan Potter
5 
6 */
7 
8 /** \file arch/irq.h
9  \brief Interrupt and exception handling.
10 
11  This file contains various definitions and declarations related to handling
12  interrupts and exceptions on the Dreamcast. This level deals with IRQs and
13  exceptions generated on the SH4, versus the asic layer which deals with
14  actually differentiating "external" interrupts.
15 
16  \author Dan Potter
17  \see dc/asic.h
18 */
19 
20 #ifndef __ARCH_IRQ_H
21 #define __ARCH_IRQ_H
22 
23 #include <sys/cdefs.h>
24 __BEGIN_DECLS
25 
26 #include <arch/types.h>
27 
28 /** \brief The number of bytes required to save thread context.
29 
30  This should include all general CPU registers, FP registers, and status regs
31  (even if not all of these are actually used).
32 
33  On the Dreamcast, we need 228 bytes for all of that, but we round it up to a
34  nicer number for sanity.
35 */
36 #define REG_BYTE_CNT 256 /* Currently really 228 */
37 
38 /** \brief Architecture-specific structure for holding the processor state.
39 
40  This structure should hold register values and other important parts of the
41  processor state. The size of this structure should be less than or equal
42  to the REG_BYTE_CNT value.
43 
44  \headerfile arch/irq.h
45 */
46 typedef struct irq_context {
47  uint32 r[16]; /**< \brief 16 general purpose (integer) registers */
48  uint32 pc; /**< \brief Program counter */
49  uint32 pr; /**< \brief Procedure register (aka return address) */
50  uint32 gbr; /**< \brief Global base register */
51  uint32 vbr; /**< \brief Vector base register */
52  uint32 mach; /**< \brief Multiply-and-accumulate register (high) */
53  uint32 macl; /**< \brief Multiply-and-accumulate register (low) */
54  uint32 sr; /**< \brief Status register */
55  uint32 frbank[16]; /**< \brief Secondary floating poing registers */
56  uint32 fr[16]; /**< \brief Primary floating point registers */
57  uint32 fpscr; /**< \brief Floating-point status/control register */
58  uint32 fpul; /**< \brief Floatint-point communication register */
60 
61 /* A couple of architecture independent access macros */
62 /** \brief Fetch the program counter from an irq_context_t.
63  \param c The context to read from.
64  \return The program counter value.
65 */
66 #define CONTEXT_PC(c) ((c).pc)
67 
68 /** \brief Fetch the frame pointer from an irq_context_t.
69  \param c The context to read from.
70  \return The frame pointer value.
71 */
72 #define CONTEXT_FP(c) ((c).r[14])
73 
74 /** \brief Fetch the stack pointer from an irq_context_t.
75  \param c The context to read from.
76  \return The stack pointer value.
77 */
78 #define CONTEXT_SP(c) ((c).r[15])
79 
80 /** \brief Fetch the return value from an irq_context_t.
81  \param c The context to read from.
82  \return The return value.
83 */
84 #define CONTEXT_RET(c) ((c).r[0])
85 
86 /** \defgroup irq_exception_codes SH4 exception codes
87 
88  These are all of the exceptions that can be raised on the SH4, and their
89  codes. They're divided into several logical groups.
90 
91  @{
92 */
93 /* Dreamcast-specific exception codes.. use these when getting or setting an
94  exception code value. */
95 
96 /** \defgroup irq_reset_codes Reset type
97 
98  These are exceptions that essentially cause a reset of the system. They
99  cannot actually be caught by normal means. They will all automatically cause
100  a branch to address 0xA0000000. These are pretty much fatal.
101 
102  @{
103 */
104 #define EXC_RESET_POWERON 0x0000 /**< \brief Power-on reset */
105 #define EXC_RESET_MANUAL 0x0020 /**< \brief Manual reset */
106 #define EXC_RESET_UDI 0x0000 /**< \brief Hitachi UDI reset */
107 #define EXC_ITLB_MULTIPLE 0x0140 /**< \brief Instruction TLB multiple hit */
108 #define EXC_DTLB_MULTIPLE 0x0140 /**< \brief Data TLB multiple hit */
109 /** @} */
110 
111 /** \defgroup irq_reexec_codes Re-Execution type
112 
113  These exceptions will stop the currently processing instruction, and
114  transition into exception processing. After handling the exception (assuming
115  that it can be handled by the code), the offending instruction will be
116  re-executed from the start.
117 
118  @{
119 */
120 #define EXC_USER_BREAK_PRE 0x01e0 /**< \brief User break before instruction */
121 #define EXC_INSTR_ADDRESS 0x00e0 /**< \brief Instruction address */
122 #define EXC_ITLB_MISS 0x0040 /**< \brief Instruction TLB miss */
123 #define EXC_ITLB_PV 0x00a0 /**< \brief Instruction TLB protection violation */
124 #define EXC_ILLEGAL_INSTR 0x0180 /**< \brief Illegal instruction */
125 #define EXC_SLOT_ILLEGAL_INSTR 0x01a0 /**< \brief Slot illegal instruction */
126 #define EXC_GENERAL_FPU 0x0800 /**< \brief General FPU exception */
127 #define EXC_SLOT_FPU 0x0820 /**< \brief Slot FPU exception */
128 #define EXC_DATA_ADDRESS_READ 0x00e0 /**< \brief Data address (read) */
129 #define EXC_DATA_ADDRESS_WRITE 0x0100 /**< \brief Data address (write) */
130 #define EXC_DTLB_MISS_READ 0x0040 /**< \brief Data TLB miss (read) */
131 #define EXC_DTLB_MISS_WRITE 0x0060 /**< \brief Data TLB miss (write) */
132 #define EXC_DTLB_PV_READ 0x00a0 /**< \brief Data TLB protection violation (read) */
133 #define EXC_DTLB_PV_WRITE 0x00c0 /**< \brief Data TLB protection violation (write) */
134 #define EXC_FPU 0x0120 /**< \brief FPU exception */
135 #define EXC_INITIAL_PAGE_WRITE 0x0080 /**< \brief Initial page write exception */
136 /** @} */
137 
138 /** \defgroup irq_completion_codes Completion type
139 
140  These exceptions are actually handled in-between instructions, allowing the
141  instruction that causes them to finish completely. The saved PC thus is the
142  value of the next instruction.
143 
144  @{
145 */
146 #define EXC_TRAPA 0x0160 /**< \brief Unconditional trap (trapa) */
147 #define EXC_USER_BREAK_POST 0x01e0 /**< \brief User break after instruction */
148 /** @} */
149 
150 /** \defgroup irq_interrupt_codes Interrupt (completion type)
151 
152  These exceptions are caused by interrupt requests. These generally are from
153  peripheral devices, but NMIs, timer interrupts, and DMAC interrupts are also
154  included here.
155 
156  \note Not all of these have any meaning on the Dreamcast. Those that have
157  no meaning are only included for completeness.
158  @{
159 */
160 #define EXC_NMI 0x01c0 /**< \brief Nonmaskable interrupt */
161 #define EXC_IRQ0 0x0200 /**< \brief External IRQ request (level 0) */
162 #define EXC_IRQ1 0x0220 /**< \brief External IRQ request (level 1) */
163 #define EXC_IRQ2 0x0240 /**< \brief External IRQ request (level 2) */
164 #define EXC_IRQ3 0x0260 /**< \brief External IRQ request (level 3) */
165 #define EXC_IRQ4 0x0280 /**< \brief External IRQ request (level 4) */
166 #define EXC_IRQ5 0x02a0 /**< \brief External IRQ request (level 5) */
167 #define EXC_IRQ6 0x02c0 /**< \brief External IRQ request (level 6) */
168 #define EXC_IRQ7 0x02e0 /**< \brief External IRQ request (level 7) */
169 #define EXC_IRQ8 0x0300 /**< \brief External IRQ request (level 8) */
170 #define EXC_IRQ9 0x0320 /**< \brief External IRQ request (level 9) */
171 #define EXC_IRQA 0x0340 /**< \brief External IRQ request (level 10) */
172 #define EXC_IRQB 0x0360 /**< \brief External IRQ request (level 11) */
173 #define EXC_IRQC 0x0380 /**< \brief External IRQ request (level 12) */
174 #define EXC_IRQD 0x03a0 /**< \brief External IRQ request (level 13) */
175 #define EXC_IRQE 0x03c0 /**< \brief External IRQ request (level 14) */
176 #define EXC_TMU0_TUNI0 0x0400 /**< \brief TMU0 underflow */
177 #define EXC_TMU1_TUNI1 0x0420 /**< \brief TMU1 underflow */
178 #define EXC_TMU2_TUNI2 0x0440 /**< \brief TMU2 underflow */
179 #define EXC_TMU2_TICPI2 0x0460 /**< \brief TMU2 input capture */
180 #define EXC_RTC_ATI 0x0480 /**< \brief RTC alarm interrupt */
181 #define EXC_RTC_PRI 0x04a0 /**< \brief RTC periodic interrupt */
182 #define EXC_RTC_CUI 0x04c0 /**< \brief RTC carry interrupt */
183 #define EXC_SCI_ERI 0x04e0 /**< \brief SCI Error receive */
184 #define EXC_SCI_RXI 0x0500 /**< \brief SCI Receive ready */
185 #define EXC_SCI_TXI 0x0520 /**< \brief SCI Transmit ready */
186 #define EXC_SCI_TEI 0x0540 /**< \brief SCI Transmit error */
187 #define EXC_WDT_ITI 0x0560 /**< \brief Watchdog timer */
188 #define EXC_REF_RCMI 0x0580 /**< \brief Memory refresh compare-match interrupt */
189 #define EXC_REF_ROVI 0x05a0 /**< \brief Memory refresh counter overflow interrupt */
190 #define EXC_UDI 0x0600 /**< \brief Hitachi UDI */
191 #define EXC_GPIO_GPIOI 0x0620 /**< \brief I/O port interrupt */
192 #define EXC_DMAC_DMTE0 0x0640 /**< \brief DMAC transfer end (channel 0) */
193 #define EXC_DMAC_DMTE1 0x0660 /**< \brief DMAC transfer end (channel 1) */
194 #define EXC_DMAC_DMTE2 0x0680 /**< \brief DMAC transfer end (channel 2) */
195 #define EXC_DMAC_DMTE3 0x06a0 /**< \brief DMAC transfer end (channel 3) */
196 #define EXC_DMA_DMAE 0x06c0 /**< \brief DMAC address error */
197 #define EXC_SCIF_ERI 0x0700 /**< \brief SCIF Error receive */
198 #define EXC_SCIF_RXI 0x0720 /**< \brief SCIF Receive ready */
199 #define EXC_SCIF_BRI 0x0740 /**< \brief SCIF break */
200 #define EXC_SCIF_TXI 0x0760 /**< \brief SCIF Transmit ready */
201 /** @} */
202 
203 /** \brief Double fault
204 
205  This exception is completely done in software (not represented on the CPU at
206  all). Its used for when an exception occurs during an IRQ service routine.
207 */
208 #define EXC_DOUBLE_FAULT 0x0ff0
209 
210 /** \brief Unhandled exception
211 
212  This exception is a software-generated exception for a generic unhandled
213  exception.
214 */
215 #define EXC_UNHANDLED_EXC 0x0fe0
216 /** @} */
217 
218 /** \brief irq_type_offsets Exception type offsets
219 
220  The following are a table of "type offsets" (see the Hitachi PDF). These are
221  the 0x000, 0x100, 0x400, and 0x600 offsets.
222 
223  @{
224 */
225 #define EXC_OFFSET_000 0 /**< \brief Offset 0x000 */
226 #define EXC_OFFSET_100 1 /**< \brief Offset 0x100 */
227 #define EXC_OFFSET_400 2 /**< \brief Offset 0x400 */
228 #define EXC_OFFSET_600 3 /**< \brief Offset 0x600 */
229 /** @} */
230 
231 /** \brief The value of the timer IRQ */
232 #define TIMER_IRQ EXC_TMU0_TUNI0
233 
234 /** \brief The type of an interrupt identifier */
235 typedef uint32 irq_t;
236 
237 /** \brief The type of an IRQ handler
238  \param source The IRQ that caused the handler to be called.
239  \param context The CPU's context.
240 */
241 typedef void (*irq_handler)(irq_t source, irq_context_t *context);
242 
243 /** \brief Are we inside an interrupt handler?
244  \retval 1 If interrupt handling is in progress.
245  \retval 0 If normal processing is in progress.
246 */
247 int irq_inside_int();
248 
249 /** \brief Pretend like we just came in from an interrupt and force
250  a context switch back to the "current" context.
251 
252  Make sure you've called irq_set_context() before doing this!
253 */
254 void irq_force_return();
255 
256 /** \brief Set or remove an IRQ handler.
257 
258  Passing a NULL value for hnd will remove the current handler, if any.
259 
260  \param source The IRQ type to set the handler for
261  (see \ref irq_exception_codes).
262  \param hnd A pointer to a procedure to handle the exception.
263  \retval 0 On success.
264  \retval -1 If the source is invalid.
265 */
266 int irq_set_handler(irq_t source, irq_handler hnd);
267 
268 /** \brief Get the address of the current handler for the IRQ type.
269  \param source The IRQ type to look up.
270  \return A pointer to the procedure to handle the exception.
271 */
273 
274 /** \brief Set or remove a handler for a trapa code.
275  \param code The value passed to the trapa opcode.
276  \param hnd A pointer to the procedure to handle the trap.
277  \retval 0 On success.
278  \retval -1 If the code is invalid (greater than 0xFF).
279 */
280 int trapa_set_handler(irq_t code, irq_handler hnd);
281 
282 /** \brief Set a global exception handler.
283 
284  This function sets a global catch-all handler for all exception types.
285 
286  \param hnd A pointer to the procedure to handle the exception.
287  \retval 0 On success (no error conditions defined).
288  \note The specific handler will still be called for the
289  exception if one is set. If not, setting one of
290  these will stop the unhandled exception error.
291 */
293 
294 /** \brief Get the global exception handler.
295 
296  \return The global exception handler set with
297  irq_set_global_handler(), or NULL if none is set.
298 */
300 
301 /** \brief Switch out contexts (for interrupt return).
302 
303  This function will set the processor state that will be restored when the
304  exception returns.
305 
306  \param regbank The values of all registers to be restored.
307 */
308 void irq_set_context(irq_context_t *regbank);
309 
310 /** \brief Get the current IRQ context.
311 
312  This will fetch the processor context prior to the exception handling during
313  an IRQ service routine.
314 
315  \return The current IRQ context.
316 */
318 
319 /** \brief Fill a newly allocated context block for usage with supervisor
320  or user mode.
321 
322  The given parameters will be passed to the called routine (up to the
323  architecture maximum). For the Dreamcast, this maximum is 4.
324 
325  \param context The IRQ context to fill in.
326  \param stack_pointer The value to set in the stack pointer.
327  \param routine The address of the program counter for the context.
328  \param args Any arguments to set in the registers. This cannot
329  be NULL, and must have enough values to fill in up
330  to the architecture maximum.
331  \param usermode 1 to run the routine in user mode, 0 for supervisor.
332 */
333 void irq_create_context(irq_context_t *context, uint32 stack_pointer,
334  uint32 routine, uint32 *args, int usermode);
335 
336 /* Enable/Disable interrupts */
337 /** \brief Disable interrupts.
338 
339  This function will disable interrupts, but will leave exceptions enabled.
340 
341  \return The state of IRQs before calling the function. This
342  can be used to restore this state later on with
343  irq_restore().
344 */
345 int irq_disable();
346 
347 /** \brief Enable all interrupts.
348 
349  This function will enable ALL interrupts, including external ones.
350 */
351 void irq_enable();
352 
353 /** \brief Restore IRQ state.
354 
355  This function will restore the interrupt state to the value specified. This
356  should correspond to a value returned by irq_disable().
357 
358  \param v The IRQ state to restore. This should be a value
359  returned by irq_disable().
360 */
361 void irq_restore(int v);
362 
363 /** \brief Initialize interrupts.
364  \retval 0 On success (no error conditions defined).
365 */
366 int irq_init();
367 
368 /** \brief Shutdown interrupts, restoring the state to how it was before
369  irq_init() was called.
370 */
371 void irq_shutdown();
372 
373 __END_DECLS
374 
375 #endif /* __ARCH_IRQ_H */
uint32 vbr
Vector base register.
Definition: irq.h:51
int irq_init()
Initialize interrupts.
Common integer types.
int trapa_set_handler(irq_t code, irq_handler hnd)
Set or remove a handler for a trapa code.
uint32 fpscr
Floating-point status/control register.
Definition: irq.h:57
uint32 macl
Multiply-and-accumulate register (low)
Definition: irq.h:53
Architecture-specific structure for holding the processor state.
Definition: irq.h:46
uint32 irq_t
The type of an interrupt identifier.
Definition: irq.h:235
uint32 sr
Status register.
Definition: irq.h:54
int irq_inside_int()
Are we inside an interrupt handler?
uint32 pr
Procedure register (aka return address)
Definition: irq.h:49
uint32 r[16]
16 general purpose (integer) registers
Definition: irq.h:47
void irq_set_context(irq_context_t *regbank)
Switch out contexts (for interrupt return).
void irq_create_context(irq_context_t *context, uint32 stack_pointer, uint32 routine, uint32 *args, int usermode)
Fill a newly allocated context block for usage with supervisor or user mode.
void irq_shutdown()
Shutdown interrupts, restoring the state to how it was before irq_init() was called.
uint32 mach
Multiply-and-accumulate register (high)
Definition: irq.h:52
uint32 gbr
Global base register.
Definition: irq.h:50
irq_handler irq_get_global_handler()
Get the global exception handler.
struct irq_context irq_context_t
Architecture-specific structure for holding the processor state.
int irq_set_handler(irq_t source, irq_handler hnd)
Set or remove an IRQ handler.
uint32 fr[16]
Primary floating point registers.
Definition: irq.h:56
void(* irq_handler)(irq_t source, irq_context_t *context)
The type of an IRQ handler.
Definition: irq.h:241
irq_context_t * irq_get_context()
Get the current IRQ context.
unsigned long uint32
32-bit unsigned integer
Definition: types.h:28
irq_handler irq_get_handler(irq_t source)
Get the address of the current handler for the IRQ type.
void irq_enable()
Enable all interrupts.
void irq_force_return()
Pretend like we just came in from an interrupt and force a context switch back to the "current" conte...
void irq_restore(int v)
Restore IRQ state.
uint32 pc
Program counter.
Definition: irq.h:48
int irq_set_global_handler(irq_handler hnd)
Set a global exception handler.
uint32 fpul
Floatint-point communication register.
Definition: irq.h:58
uint32 frbank[16]
Secondary floating poing registers.
Definition: irq.h:55
int irq_disable()
Disable interrupts.