Develop and Download Open Source Software

Browse CVS Repository

Contents of /mame32jp/mame32jp/src/cpuint.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download) (as text)
Wed Apr 24 03:53:20 2002 UTC (21 years, 11 months ago) by zero
Branch: MAIN
CVS Tags: ver_0_60_1, ver0_59_13, ver0_59_14, ver0_60_2, ver0_60_3, ver0_60_4, ver0_60_5, HEAD
Changes since 1.4: +0 -0 lines
File MIME type: text/x-csrc
*** empty log message ***

1 /***************************************************************************
2
3 cpuint.c
4
5 Core multi-CPU interrupt engine.
6
7 ***************************************************************************/
8
9 #include <signal.h>
10 #include "driver.h"
11 #include "timer.h"
12 #include "state.h"
13 #include "mamedbg.h"
14 #include "hiscore.h"
15
16 #if (HAS_M68000 || HAS_M68010 || HAS_M68020 || HAS_M68EC020)
17 #include "cpu/m68000/m68000.h"
18 #endif
19
20
21 /*************************************
22 *
23 * Debug logging
24 *
25 *************************************/
26
27 #define VERBOSE 0
28
29 #if VERBOSE
30 #define LOG(x) logerror x
31 #else
32 #define LOG(x)
33 #endif
34
35
36
37 /*************************************
38 *
39 * Macros to help verify active CPU
40 *
41 *************************************/
42
43 #define VERIFY_ACTIVECPU(retval, name) \
44 int activecpu = cpu_getactivecpu(); \
45 if (activecpu < 0) \
46 { \
47 logerror(#name "() called with no active cpu!\n"); \
48 return retval; \
49 }
50
51 #define VERIFY_ACTIVECPU_VOID(name) \
52 int activecpu = cpu_getactivecpu(); \
53 if (activecpu < 0) \
54 { \
55 logerror(#name "() called with no active cpu!\n"); \
56 return; \
57 }
58
59
60
61 /*************************************
62 *
63 * CPU interrupt variables
64 *
65 *************************************/
66
67 /* current states for each CPU */
68 static UINT8 interrupt_enable[MAX_CPU];
69 static INT32 interrupt_vector[MAX_CPU][MAX_IRQ_LINES];
70
71 /* deferred states written in callbacks */
72 static UINT8 irq_line_state[MAX_CPU][MAX_IRQ_LINES];
73 static INT32 irq_line_vector[MAX_CPU][MAX_IRQ_LINES];
74
75
76
77 /*************************************
78 *
79 * IRQ acknowledge callbacks
80 *
81 *************************************/
82
83 static int cpu_0_irq_callback(int irqline);
84 static int cpu_1_irq_callback(int irqline);
85 static int cpu_2_irq_callback(int irqline);
86 static int cpu_3_irq_callback(int irqline);
87 static int cpu_4_irq_callback(int irqline);
88 static int cpu_5_irq_callback(int irqline);
89 static int cpu_6_irq_callback(int irqline);
90 static int cpu_7_irq_callback(int irqline);
91
92 int (*cpu_irq_callbacks[MAX_CPU])(int) =
93 {
94 cpu_0_irq_callback,
95 cpu_1_irq_callback,
96 cpu_2_irq_callback,
97 cpu_3_irq_callback,
98 cpu_4_irq_callback,
99 cpu_5_irq_callback,
100 cpu_6_irq_callback,
101 cpu_7_irq_callback
102 };
103
104 static int (*drv_irq_callbacks[MAX_CPU])(int);
105
106
107
108 #if 0
109 #pragma mark CORE CPU
110 #endif
111
112 /*************************************
113 *
114 * Initialize a CPU's interrupt states
115 *
116 *************************************/
117
118 int cpuint_init(void)
119 {
120 int cpunum;
121 int irqline;
122
123 /* loop over all CPUs */
124 for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++)
125 {
126 /* reset the IRQ lines */
127 for (irqline = 0; irqline < MAX_IRQ_LINES; irqline++)
128 {
129 irq_line_state[cpunum][irqline] = CLEAR_LINE;
130 interrupt_vector[cpunum][irqline] =
131 irq_line_vector[cpunum][irqline] = cpunum_default_irq_vector(cpunum);
132 }
133 }
134
135 /* set up some stuff to save */
136 state_save_set_current_tag(0);
137 state_save_register_UINT8("cpu", 0, "irq enable", interrupt_enable, cpu_gettotalcpu());
138 state_save_register_INT32("cpu", 0, "irq vector", &interrupt_vector[0][0],cpu_gettotalcpu() * MAX_IRQ_LINES);
139 state_save_register_UINT8("cpu", 0, "irqline state", &irq_line_state[0][0], cpu_gettotalcpu() * MAX_IRQ_LINES);
140 state_save_register_INT32("cpu", 0, "irqline vector", &irq_line_vector[0][0], cpu_gettotalcpu() * MAX_IRQ_LINES);
141
142 return 0;
143 }
144
145
146
147 /*************************************
148 *
149 * Reset a CPU's interrupt states
150 *
151 *************************************/
152
153 void cpuint_reset_cpu(int cpunum)
154 {
155 int irqline;
156
157 /* start with interrupts enabled, so the generic routine will work even if */
158 /* the machine doesn't have an interrupt enable port */
159 interrupt_enable[cpunum] = 1;
160 for (irqline = 0; irqline < MAX_IRQ_LINES; irqline++)
161 interrupt_vector[cpunum][irqline] = cpunum_default_irq_vector(cpunum);
162
163 /* reset any driver hooks into the IRQ acknowledge callbacks */
164 drv_irq_callbacks[cpunum] = NULL;
165 }
166
167
168
169 #if 0
170 #pragma mark -
171 #pragma mark INTERRUPT HANDLING
172 #endif
173
174 /*************************************
175 *
176 * Set IRQ callback for drivers
177 *
178 *************************************/
179
180 void cpu_set_irq_callback(int cpunum, int (*callback)(int))
181 {
182 drv_irq_callbacks[cpunum] = callback;
183 }
184
185
186
187 /*************************************
188 *
189 * Internal IRQ callbacks
190 *
191 *************************************/
192
193 INLINE int cpu_irq_callback(int cpunum, int irqline)
194 {
195 int vector = irq_line_vector[cpunum][irqline];
196
197 LOG(("cpu_%d_irq_callback(%d) $%04xn", cpunum, irqline, vector));
198
199 /* if the IRQ state is HOLD_LINE, clear it */
200 if (irq_line_state[cpunum][irqline] == HOLD_LINE)
201 {
202 LOG(("->set_irq_line(%d,%d,%d)\n", cpunum, irqline, CLEAR_LINE));
203 activecpu_set_irq_line(irqline, INTERNAL_CLEAR_LINE);
204 irq_line_state[cpunum][irqline] = CLEAR_LINE;
205 }
206
207 /* if there's a driver callback, run it */
208 if (drv_irq_callbacks[cpunum])
209 vector = (*drv_irq_callbacks[cpunum])(irqline);
210
211 /* otherwise, just return the current vector */
212 return vector;
213 }
214
215 static int cpu_0_irq_callback(int irqline) { return cpu_irq_callback(0, irqline); }
216 static int cpu_1_irq_callback(int irqline) { return cpu_irq_callback(1, irqline); }
217 static int cpu_2_irq_callback(int irqline) { return cpu_irq_callback(2, irqline); }
218 static int cpu_3_irq_callback(int irqline) { return cpu_irq_callback(3, irqline); }
219 static int cpu_4_irq_callback(int irqline) { return cpu_irq_callback(4, irqline); }
220 static int cpu_5_irq_callback(int irqline) { return cpu_irq_callback(5, irqline); }
221 static int cpu_6_irq_callback(int irqline) { return cpu_irq_callback(6, irqline); }
222 static int cpu_7_irq_callback(int irqline) { return cpu_irq_callback(7, irqline); }
223
224
225
226 /*************************************
227 *
228 * Set the IRQ vector for a given
229 * IRQ line on a CPU
230 *
231 *************************************/
232
233 void cpu_irq_line_vector_w(int cpunum, int irqline, int vector)
234 {
235 if (cpunum < cpu_gettotalcpu() && irqline >= 0 && irqline < MAX_IRQ_LINES)
236 {
237 LOG(("cpu_irq_line_vector_w(%d,%d,$%04x)\n",cpunum,irqline,vector));
238 interrupt_vector[cpunum][irqline] = vector;
239 return;
240 }
241 LOG(("cpu_irq_line_vector_w CPU#%d irqline %d > max irq lines\n", cpunum, irqline));
242 }
243
244
245
246 /*************************************
247 *
248 * Generate a IRQ interrupt
249 *
250 *************************************/
251
252 static void cpu_manualirqcallback(int param)
253 {
254 int cpunum = param & 0x0f;
255 int state = (param >> 4) & 0x0f;
256 int irqline = (param >> 8) & 0x7f;
257 int set_vector = (param >> 15) & 0x01;
258 int vector = param >> 16;
259
260 LOG(("cpu_manualirqcallback %d,%d,%d\n",cpunum,irqline,state));
261
262 /* swap to the CPU's context */
263 cpuintrf_push_context(cpunum);
264
265 /* set the IRQ line state and vector */
266 if (irqline >= 0 && irqline < MAX_IRQ_LINES)
267 {
268 irq_line_state[cpunum][irqline] = state;
269 if (set_vector)
270 irq_line_vector[cpunum][irqline] = vector;
271 }
272
273 /* switch off the requested state */
274 switch (state)
275 {
276 case PULSE_LINE:
277 activecpu_set_irq_line(irqline, INTERNAL_ASSERT_LINE);
278 activecpu_set_irq_line(irqline, INTERNAL_CLEAR_LINE);
279 break;
280
281 case HOLD_LINE:
282 case ASSERT_LINE:
283 activecpu_set_irq_line(irqline, INTERNAL_ASSERT_LINE);
284 break;
285
286 case CLEAR_LINE:
287 activecpu_set_irq_line(irqline, INTERNAL_CLEAR_LINE);
288 break;
289
290 default:
291 logerror("cpu_manualirqcallback cpu #%d, line %d, unknown state %d\n", cpunum, irqline, state);
292 }
293 cpuintrf_pop_context();
294
295 /* generate a trigger to unsuspend any CPUs waiting on the interrupt */
296 if (state != CLEAR_LINE)
297 cpu_triggerint(cpunum);
298 }
299
300
301 void cpu_set_irq_line(int cpunum, int irqline, int state)
302 {
303 int vector = 0xff;
304 int param;
305
306 /* don't trigger interrupts on suspended CPUs */
307 if (cpu_getstatus(cpunum) == 0)
308 return;
309
310 /* pick the vector */
311 if (irqline >= 0 && irqline < MAX_IRQ_LINES)
312 vector = interrupt_vector[cpunum][irqline];
313
314 LOG(("cpu_set_irq_line(%d,%d,%d,%02x)\n", cpunum, irqline, state, vector));
315
316 /* set a timer to go off */
317 param = (cpunum & 0x0f) | ((state & 0x0f) << 4) | ((irqline & 0x7f) << 8) | (1 << 15) | (vector << 16);
318 // param = (cpunum & 0x0f) | ((state & 0x0f) << 4) | ((irqline & 0x7f) << 8);
319 timer_set(TIME_NOW, param, cpu_manualirqcallback);
320 }
321
322
323 void cpu_set_irq_line_and_vector(int cpunum, int irqline, int state, int vector)
324 {
325 int param;
326
327 /* don't trigger interrupts on suspended CPUs */
328 if (cpu_getstatus(cpunum) == 0)
329 return;
330
331 LOG(("cpu_set_irq_line(%d,%d,%d,%02x)\n", cpunum, irqline, state, vector));
332
333 /* set a timer to go off */
334 param = (cpunum & 0x0f) | ((state & 0x0f) << 4) | ((irqline & 0x7f) << 8) | (1 << 15) | (vector << 16);
335 timer_set(TIME_NOW, param, cpu_manualirqcallback);
336 }
337
338
339
340 #if 0
341 #pragma mark -
342 #pragma mark PREFERRED INTERRUPT HANDLING
343 #endif
344
345
346 /*************************************
347 *
348 * NMI interrupt generation
349 *
350 *************************************/
351
352 INTERRUPT_GEN( nmi_line_pulse )
353 {
354 int cpunum = cpu_getactivecpu();
355 if (interrupt_enable[cpunum])
356 cpu_set_irq_line(cpunum, IRQ_LINE_NMI, PULSE_LINE);
357 }
358
359 INTERRUPT_GEN( nmi_line_assert )
360 {
361 int cpunum = cpu_getactivecpu();
362 if (interrupt_enable[cpunum])
363 cpu_set_irq_line(cpunum, IRQ_LINE_NMI, ASSERT_LINE);
364 }
365
366
367
368 /*************************************
369 *
370 * IRQ n interrupt generation
371 *
372 *************************************/
373
374 INLINE void irqn_line_hold(int irqline)
375 {
376 int cpunum = cpu_getactivecpu();
377 if (interrupt_enable[cpunum])
378 {
379 int vector = (irqline >= 0 && irqline < MAX_IRQ_LINES) ? interrupt_vector[cpunum][irqline] : 0xff;
380 cpu_set_irq_line_and_vector(cpunum, irqline, HOLD_LINE, vector);
381 }
382 }
383
384 INLINE void irqn_line_pulse(int irqline)
385 {
386 int cpunum = cpu_getactivecpu();
387 if (interrupt_enable[cpunum])
388 {
389 int vector = (irqline >= 0 && irqline < MAX_IRQ_LINES) ? interrupt_vector[cpunum][irqline] : 0xff;
390 cpu_set_irq_line_and_vector(cpunum, irqline, PULSE_LINE, vector);
391 }
392 }
393
394 INLINE void irqn_line_assert(int irqline)
395 {
396 int cpunum = cpu_getactivecpu();
397 if (interrupt_enable[cpunum])
398 {
399 int vector = (irqline >= 0 && irqline < MAX_IRQ_LINES) ? interrupt_vector[cpunum][irqline] : 0xff;
400 cpu_set_irq_line_and_vector(cpunum, irqline, ASSERT_LINE, vector);
401 }
402 }
403
404
405
406 /*************************************
407 *
408 * IRQ interrupt generation
409 *
410 *************************************/
411
412 INTERRUPT_GEN( irq0_line_hold ) { irqn_line_hold(0); }
413 INTERRUPT_GEN( irq0_line_pulse ) { irqn_line_pulse(0); }
414 INTERRUPT_GEN( irq0_line_assert ) { irqn_line_assert(0); }
415
416 INTERRUPT_GEN( irq1_line_hold ) { irqn_line_hold(1); }
417 INTERRUPT_GEN( irq1_line_pulse ) { irqn_line_pulse(1); }
418 INTERRUPT_GEN( irq1_line_assert ) { irqn_line_assert(1); }
419
420 INTERRUPT_GEN( irq2_line_hold ) { irqn_line_hold(2); }
421 INTERRUPT_GEN( irq2_line_pulse ) { irqn_line_pulse(2); }
422 INTERRUPT_GEN( irq2_line_assert ) { irqn_line_assert(2); }
423
424 INTERRUPT_GEN( irq3_line_hold ) { irqn_line_hold(3); }
425 INTERRUPT_GEN( irq3_line_pulse ) { irqn_line_pulse(3); }
426 INTERRUPT_GEN( irq3_line_assert ) { irqn_line_assert(3); }
427
428 INTERRUPT_GEN( irq4_line_hold ) { irqn_line_hold(4); }
429 INTERRUPT_GEN( irq4_line_pulse ) { irqn_line_pulse(4); }
430 INTERRUPT_GEN( irq4_line_assert ) { irqn_line_assert(4); }
431
432 INTERRUPT_GEN( irq5_line_hold ) { irqn_line_hold(5); }
433 INTERRUPT_GEN( irq5_line_pulse ) { irqn_line_pulse(5); }
434 INTERRUPT_GEN( irq5_line_assert ) { irqn_line_assert(5); }
435
436 INTERRUPT_GEN( irq6_line_hold ) { irqn_line_hold(6); }
437 INTERRUPT_GEN( irq6_line_pulse ) { irqn_line_pulse(6); }
438 INTERRUPT_GEN( irq6_line_assert ) { irqn_line_assert(6); }
439
440 INTERRUPT_GEN( irq7_line_hold ) { irqn_line_hold(7); }
441 INTERRUPT_GEN( irq7_line_pulse ) { irqn_line_pulse(7); }
442 INTERRUPT_GEN( irq7_line_assert ) { irqn_line_assert(7); }
443
444
445
446 #if 0
447 #pragma mark -
448 #pragma mark OBSOLETE INTERRUPT HANDLING
449 #endif
450
451 /*************************************
452 *
453 * Interrupt enabling
454 *
455 *************************************/
456
457 static void cpu_clearintcallback(int cpunum)
458 {
459 int irqcount = cputype_get_interface(Machine->drv->cpu[cpunum].cpu_type & ~CPU_FLAGS_MASK)->num_irqs;
460 int irqline;
461
462 cpuintrf_push_context(cpunum);
463
464 /* clear NMI and all IRQs */
465 activecpu_set_irq_line(IRQ_LINE_NMI, INTERNAL_CLEAR_LINE);
466 for (irqline = 0; irqline < irqcount; irqline++)
467 activecpu_set_irq_line(irqline, INTERNAL_CLEAR_LINE);
468
469 cpuintrf_pop_context();
470 }
471
472
473 void cpu_interrupt_enable(int cpunum,int enabled)
474 {
475 interrupt_enable[cpunum] = enabled;
476
477 LOG(("CPU#%d interrupt_enable=%d\n", cpunum, enabled));
478
479 /* make sure there are no queued interrupts */
480 if (enabled == 0)
481 timer_set(TIME_NOW, cpunum, cpu_clearintcallback);
482 }
483
484
485 WRITE_HANDLER( interrupt_enable_w )
486 {
487 VERIFY_ACTIVECPU_VOID(interrupt_enable_w);
488 cpu_interrupt_enable(activecpu, data);
489 }
490
491
492 READ_HANDLER( interrupt_enable_r )
493 {
494 VERIFY_ACTIVECPU(1, interrupt_enable_r);
495 return interrupt_enable[activecpu];
496 }
497
498
499 WRITE_HANDLER( interrupt_vector_w )
500 {
501 VERIFY_ACTIVECPU_VOID(interrupt_vector_w);
502 if (interrupt_vector[activecpu][0] != data)
503 {
504 LOG(("CPU#%d interrupt_vector_w $%02x\n", activecpu, data));
505 interrupt_vector[activecpu][0] = data;
506
507 /* make sure there are no queued interrupts */
508 timer_set(TIME_NOW, activecpu, cpu_clearintcallback);
509 }
510 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26