]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/mn10300/dv-mn103int.c
66df97a63c8dd7a019a6f24fbf721eab838b5c79
[thirdparty/binutils-gdb.git] / sim / mn10300 / dv-mn103int.c
1 /* This file is part of the program GDB, the GNU debugger.
2
3 Copyright (C) 1998-2022 Free Software Foundation, Inc.
4 Contributed by Cygnus Solutions.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 /* This must come before any other includes. */
22 #include "defs.h"
23
24 #include "sim-main.h"
25 #include "hw-main.h"
26 #include "sim-hw.h"
27
28 /* DEVICE
29
30
31 mn103int - mn103002 interrupt controller
32
33
34 DESCRIPTION
35
36
37 Implements the mn103002 interrupt controller described in the
38 mn103002 user guide.
39
40
41 PROPERTIES
42
43
44 reg = <icr-adr> <icr-siz> <iagr-adr> <iadr-siz> <extmd-adr> <extmd-siz>
45
46 Specify the address of the ICR (total of 30 registers), IAGR and
47 EXTMD registers (within the parent bus).
48
49 The reg property value `0x34000100 0x7C 0x34000200 0x8 0x3400280
50 0x8' locates the interrupt controller at the addresses specified in
51 the mn103002 interrupt controller user guide.
52
53
54 PORTS
55
56
57 nmi (output)
58
59 Non-maskable interrupt output port. An event on this output ports
60 indicates a NMI request from the interrupt controller. The value
61 attached to the event should be ignored.
62
63
64 level (output)
65
66 Maskable interrupt level output port. An event on this output port
67 indicates a maskable interrupt request at the specified level. The
68 event value defines the level being requested.
69
70 The interrupt controller will generate an event on this port
71 whenever there is a change to the internal state of the interrupt
72 controller.
73
74
75 ack (input)
76
77 Signal from processor indicating that a maskable interrupt has been
78 accepted and the interrupt controller should latch the IAGR with
79 value of the current highest priority interrupting group.
80
81 The event value is the interrupt level being accepted by the
82 processor. It should be consistent with the most recent LEVEL sent
83 to the processor from the interrupt controller.
84
85
86 int[0..100] (input)
87
88 Level or edge triggered interrupt input port. Each of the 30
89 groups (0..30) can have up to 4 (0..3) interrupt inputs. The
90 interpretation of a port event/value is determined by the
91 configuration of the corresponding interrupt group.
92
93 For convenience, numerous aliases to these interrupt inputs are
94 provided.
95
96
97 BUGS
98
99
100 For edge triggered interrupts, the interrupt controller does not
101 differentiate between POSITIVE (rising) and NEGATIVE (falling)
102 edges. Instead any input port event is considered to be an
103 interrupt trigger.
104
105 For level sensitive interrupts, the interrupt controller ignores
106 active HIGH/LOW settings and instead always interprets a nonzero
107 port value as an interrupt assertion and a zero port value as a
108 negation.
109
110 */
111
112
113 /* The interrupt groups - numbered according to mn103002 convention */
114
115 enum mn103int_trigger {
116 ACTIVE_LOW,
117 ACTIVE_HIGH,
118 POSITIVE_EDGE,
119 NEGATIVE_EDGE,
120 };
121
122 enum mn103int_type {
123 NMI_GROUP,
124 LEVEL_GROUP,
125 };
126
127 struct mn103int_group {
128 int gid;
129 int level;
130 unsigned enable;
131 unsigned request;
132 unsigned input;
133 enum mn103int_trigger trigger;
134 enum mn103int_type type;
135 };
136
137 enum {
138 FIRST_NMI_GROUP = 0,
139 LAST_NMI_GROUP = 1,
140 FIRST_LEVEL_GROUP = 2,
141 LAST_LEVEL_GROUP = 30,
142 NR_GROUPS,
143 };
144
145 enum {
146 LOWEST_LEVEL = 7,
147 };
148
149 /* The interrupt controller register address blocks */
150
151 struct mn103int_block {
152 unsigned_word base;
153 unsigned_word bound;
154 };
155
156 enum { ICR_BLOCK, IAGR_BLOCK, EXTMD_BLOCK, NR_BLOCKS };
157
158
159 struct mn103int {
160 struct mn103int_block block[NR_BLOCKS];
161 struct mn103int_group group[NR_GROUPS];
162 unsigned interrupt_accepted_group;
163 };
164
165
166
167 /* output port ID's */
168
169 enum {
170 NMI_PORT,
171 LEVEL_PORT,
172 };
173
174
175 /* input port ID's */
176
177 enum {
178 G0_PORT = 0,
179 G1_PORT = 4,
180 G2_PORT = 8,
181 G3_PORT = 12,
182 G4_PORT = 16,
183 G5_PORT = 20,
184 G6_PORT = 24,
185 G7_PORT = 28,
186 G8_PORT = 32,
187 G9_PORT = 36,
188 G10_PORT = 40,
189 G11_PORT = 44,
190 G12_PORT = 48,
191 G13_PORT = 52,
192 G14_PORT = 56,
193 G15_PORT = 60,
194 G16_PORT = 64,
195 G17_PORT = 68,
196 G18_PORT = 72,
197 G19_PORT = 76,
198 G20_PORT = 80,
199 G21_PORT = 84,
200 G22_PORT = 88,
201 G23_PORT = 92,
202 IRQ0_PORT = G23_PORT,
203 G24_PORT = 96,
204 G25_PORT = 100,
205 G26_PORT = 104,
206 G27_PORT = 108,
207 IRQ4_PORT = G27_PORT,
208 G28_PORT = 112,
209 G29_PORT = 116,
210 G30_PORT = 120,
211 NR_G_PORTS = 124,
212 ACK_PORT,
213 };
214
215 static const struct hw_port_descriptor mn103int_ports[] = {
216
217 /* interrupt outputs */
218
219 { "nmi", NMI_PORT, 0, output_port, },
220 { "level", LEVEL_PORT, 0, output_port, },
221
222 /* interrupt ack (latch) input from cpu */
223
224 { "ack", ACK_PORT, 0, input_port, },
225
226 /* interrupt inputs (as names) */
227
228 { "nmirq", G0_PORT + 0, 0, input_port, },
229 { "watchdog", G0_PORT + 1, 0, input_port, },
230 { "syserr", G0_PORT + 2, 0, input_port, },
231
232 { "timer-0-underflow", G2_PORT, 0, input_port, },
233 { "timer-1-underflow", G3_PORT, 0, input_port, },
234 { "timer-2-underflow", G4_PORT, 0, input_port, },
235 { "timer-3-underflow", G5_PORT, 0, input_port, },
236 { "timer-4-underflow", G6_PORT, 0, input_port, },
237 { "timer-5-underflow", G7_PORT, 0, input_port, },
238 { "timer-6-underflow", G8_PORT, 0, input_port, },
239
240 { "timer-6-compare-a", G9_PORT, 0, input_port, },
241 { "timer-6-compare-b", G10_PORT, 0, input_port, },
242
243 { "dma-0-end", G12_PORT, 0, input_port, },
244 { "dma-1-end", G13_PORT, 0, input_port, },
245 { "dma-2-end", G14_PORT, 0, input_port, },
246 { "dma-3-end", G15_PORT, 0, input_port, },
247
248 { "serial-0-receive", G16_PORT, 0, input_port, },
249 { "serial-0-transmit", G17_PORT, 0, input_port, },
250
251 { "serial-1-receive", G18_PORT, 0, input_port, },
252 { "serial-1-transmit", G19_PORT, 0, input_port, },
253
254 { "serial-2-receive", G20_PORT, 0, input_port, },
255 { "serial-2-transmit", G21_PORT, 0, input_port, },
256
257 { "irq-0", G23_PORT, 0, input_port, },
258 { "irq-1", G24_PORT, 0, input_port, },
259 { "irq-2", G25_PORT, 0, input_port, },
260 { "irq-3", G26_PORT, 0, input_port, },
261 { "irq-4", G27_PORT, 0, input_port, },
262 { "irq-5", G28_PORT, 0, input_port, },
263 { "irq-6", G29_PORT, 0, input_port, },
264 { "irq-7", G30_PORT, 0, input_port, },
265
266 /* interrupt inputs (as generic numbers) */
267
268 { "int", 0, NR_G_PORTS, input_port, },
269
270 { NULL, },
271 };
272
273
274 /* Macros for extracting/restoring the various register bits */
275
276 #define EXTRACT_ID(X) (LSEXTRACTED8 ((X), 3, 0))
277 #define INSERT_ID(X) (LSINSERTED8 ((X), 3, 0))
278
279 #define EXTRACT_IR(X) (LSEXTRACTED8 ((X), 7, 4))
280 #define INSERT_IR(X) (LSINSERTED8 ((X), 7, 4))
281
282 #define EXTRACT_IE(X) (LSEXTRACTED8 ((X), 3, 0))
283 #define INSERT_IE(X) (LSINSERTED8 ((X), 3, 0))
284
285 #define EXTRACT_LV(X) (LSEXTRACTED8 ((X), 6, 4))
286 #define INSERT_LV(X) (LSINSERTED8 ((X), 6, 4))
287
288
289
290 /* Finish off the partially created hw device. Attach our local
291 callbacks. Wire up our port names etc */
292
293 static hw_io_read_buffer_method mn103int_io_read_buffer;
294 static hw_io_write_buffer_method mn103int_io_write_buffer;
295 static hw_port_event_method mn103int_port_event;
296 static hw_ioctl_method mn103int_ioctl;
297
298
299
300 static void
301 attach_mn103int_regs (struct hw *me,
302 struct mn103int *controller)
303 {
304 int i;
305 if (hw_find_property (me, "reg") == NULL)
306 hw_abort (me, "Missing \"reg\" property");
307 for (i = 0; i < NR_BLOCKS; i++)
308 {
309 unsigned_word attach_address;
310 int attach_space;
311 unsigned attach_size;
312 reg_property_spec reg;
313 if (!hw_find_reg_array_property (me, "reg", i, &reg))
314 hw_abort (me, "\"reg\" property must contain three addr/size entries");
315 hw_unit_address_to_attach_address (hw_parent (me),
316 &reg.address,
317 &attach_space,
318 &attach_address,
319 me);
320 controller->block[i].base = attach_address;
321 hw_unit_size_to_attach_size (hw_parent (me),
322 &reg.size,
323 &attach_size, me);
324 controller->block[i].bound = attach_address + (attach_size - 1);
325 hw_attach_address (hw_parent (me),
326 0,
327 attach_space, attach_address, attach_size,
328 me);
329 }
330 }
331
332 static void
333 mn103int_finish (struct hw *me)
334 {
335 int gid;
336 struct mn103int *controller;
337
338 controller = HW_ZALLOC (me, struct mn103int);
339 set_hw_data (me, controller);
340 set_hw_io_read_buffer (me, mn103int_io_read_buffer);
341 set_hw_io_write_buffer (me, mn103int_io_write_buffer);
342 set_hw_ports (me, mn103int_ports);
343 set_hw_port_event (me, mn103int_port_event);
344 me->to_ioctl = mn103int_ioctl;
345
346 /* Attach ourself to our parent bus */
347 attach_mn103int_regs (me, controller);
348
349 /* Initialize all the groups according to their default configuration */
350 for (gid = 0; gid < NR_GROUPS; gid++)
351 {
352 struct mn103int_group *group = &controller->group[gid];
353 group->trigger = NEGATIVE_EDGE;
354 group->gid = gid;
355 if (FIRST_NMI_GROUP <= gid && gid <= LAST_NMI_GROUP)
356 {
357 group->enable = 0xf;
358 group->type = NMI_GROUP;
359 }
360 else if (FIRST_LEVEL_GROUP <= gid && gid <= LAST_LEVEL_GROUP)
361 {
362 group->enable = 0x0;
363 group->type = LEVEL_GROUP;
364 }
365 else
366 hw_abort (me, "internal error - unknown group id");
367 }
368 }
369
370
371
372 /* Perform the nasty work of figuring out which of the interrupt
373 groups should have its interrupt delivered. */
374
375 static int
376 find_highest_interrupt_group (struct hw *me,
377 struct mn103int *controller)
378 {
379 int gid;
380 int selected;
381
382 /* FIRST_NMI_GROUP (group zero) is used as a special default value
383 when searching for an interrupt group.*/
384 selected = FIRST_NMI_GROUP;
385 controller->group[FIRST_NMI_GROUP].level = 7;
386
387 for (gid = FIRST_LEVEL_GROUP; gid <= LAST_LEVEL_GROUP; gid++)
388 {
389 struct mn103int_group *group = &controller->group[gid];
390 if ((group->request & group->enable) != 0)
391 {
392 /* Remember, lower level, higher priority. */
393 if (group->level < controller->group[selected].level)
394 {
395 selected = gid;
396 }
397 }
398 }
399 return selected;
400 }
401
402
403 /* Notify the processor of an interrupt level update */
404
405 static void
406 push_interrupt_level (struct hw *me,
407 struct mn103int *controller)
408 {
409 int selected = find_highest_interrupt_group (me, controller);
410 int level = controller->group[selected].level;
411 HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level));
412 hw_port_event (me, LEVEL_PORT, level);
413 }
414
415
416 /* An event arrives on an interrupt port */
417
418 static void
419 mn103int_port_event (struct hw *me,
420 int my_port,
421 struct hw *source,
422 int source_port,
423 int level)
424 {
425 struct mn103int *controller = hw_data (me);
426
427 switch (my_port)
428 {
429
430 case ACK_PORT:
431 {
432 int selected = find_highest_interrupt_group (me, controller);
433 if (controller->group[selected].level != level)
434 hw_abort (me, "botched level synchronisation");
435 controller->interrupt_accepted_group = selected;
436 HW_TRACE ((me, "port-event port=ack level=%d - selected=%d",
437 level, selected));
438 break;
439 }
440
441 default:
442 {
443 int gid;
444 int iid;
445 struct mn103int_group *group;
446 unsigned interrupt;
447 if (my_port > NR_G_PORTS)
448 hw_abort (me, "Event on unknown port %d", my_port);
449
450 /* map the port onto an interrupt group */
451 gid = (my_port % NR_G_PORTS) / 4;
452 group = &controller->group[gid];
453 iid = (my_port % 4);
454 interrupt = 1 << iid;
455
456 /* update our cached input */
457 if (level)
458 group->input |= interrupt;
459 else
460 group->input &= ~interrupt;
461
462 /* update the request bits */
463 switch (group->trigger)
464 {
465 case ACTIVE_LOW:
466 case ACTIVE_HIGH:
467 if (level)
468 group->request |= interrupt;
469 break;
470 case NEGATIVE_EDGE:
471 case POSITIVE_EDGE:
472 group->request |= interrupt;
473 }
474
475 /* force a corresponding output */
476 switch (group->type)
477 {
478
479 case NMI_GROUP:
480 {
481 /* for NMI's the event is the trigger */
482 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI",
483 my_port, gid, iid));
484 if ((group->request & group->enable) != 0)
485 {
486 HW_TRACE ((me, "port-out NMI"));
487 hw_port_event (me, NMI_PORT, 1);
488 }
489 break;
490 }
491
492 case LEVEL_GROUP:
493 {
494 /* if an interrupt is now pending */
495 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT",
496 my_port, gid, iid));
497 push_interrupt_level (me, controller);
498 break;
499 }
500 }
501 break;
502 }
503
504 }
505 }
506
507 /* Read/write to to an ICR (group control register) */
508
509 static struct mn103int_group *
510 decode_group (struct hw *me,
511 struct mn103int *controller,
512 unsigned_word base,
513 unsigned_word *offset)
514 {
515 int gid = (base / 4) % NR_GROUPS;
516 *offset = (base % 4);
517 return &controller->group[gid];
518 }
519
520 static unsigned8
521 read_icr (struct hw *me,
522 struct mn103int *controller,
523 unsigned_word base)
524 {
525 unsigned_word offset;
526 struct mn103int_group *group = decode_group (me, controller, base, &offset);
527 unsigned8 val = 0;
528 switch (group->type)
529 {
530
531 case NMI_GROUP:
532 switch (offset)
533 {
534 case 0:
535 val = INSERT_ID (group->request);
536 HW_TRACE ((me, "read-icr group=%d:0 nmi 0x%02x",
537 group->gid, val));
538 break;
539 default:
540 break;
541 }
542 break;
543
544 case LEVEL_GROUP:
545 switch (offset)
546 {
547 case 0:
548 val = (INSERT_IR (group->request)
549 | INSERT_ID (group->request & group->enable));
550 HW_TRACE ((me, "read-icr group=%d:0 level 0x%02x",
551 group->gid, val));
552 break;
553 case 1:
554 val = (INSERT_LV (group->level)
555 | INSERT_IE (group->enable));
556 HW_TRACE ((me, "read-icr level-%d:1 level 0x%02x",
557 group->gid, val));
558 break;
559 }
560 break;
561
562 default:
563 break;
564
565 }
566
567 return val;
568 }
569
570 static void
571 write_icr (struct hw *me,
572 struct mn103int *controller,
573 unsigned_word base,
574 unsigned8 val)
575 {
576 unsigned_word offset;
577 struct mn103int_group *group = decode_group (me, controller, base, &offset);
578 switch (group->type)
579 {
580
581 case NMI_GROUP:
582 switch (offset)
583 {
584 case 0:
585 HW_TRACE ((me, "write-icr group=%d:0 nmi 0x%02x",
586 group->gid, val));
587 group->request &= ~EXTRACT_ID (val);
588 break;
589 /* Special backdoor access to SYSEF flag from CPU. See
590 interp.c:program_interrupt(). */
591 case 3:
592 HW_TRACE ((me, "write-icr-special group=%d:0 nmi 0x%02x",
593 group->gid, val));
594 group->request |= EXTRACT_ID (val);
595 default:
596 break;
597 }
598 break;
599
600 case LEVEL_GROUP:
601 switch (offset)
602 {
603 case 0: /* request/detect */
604 /* Clear any ID bits and then set them according to IR */
605 HW_TRACE ((me, "write-icr group=%d:0 level 0x%02x %x:%x:%x",
606 group->gid, val,
607 group->request, EXTRACT_IR (val), EXTRACT_ID (val)));
608 group->request =
609 ((EXTRACT_IR (val) & EXTRACT_ID (val))
610 | (EXTRACT_IR (val) & group->request)
611 | (~EXTRACT_IR (val) & ~EXTRACT_ID (val) & group->request));
612 break;
613 case 1: /* level/enable */
614 HW_TRACE ((me, "write-icr group=%d:1 level 0x%02x",
615 group->gid, val));
616 group->level = EXTRACT_LV (val);
617 group->enable = EXTRACT_IE (val);
618 break;
619 default:
620 /* ignore */
621 break;
622 }
623 push_interrupt_level (me, controller);
624 break;
625
626 default:
627 break;
628
629 }
630 }
631
632
633 /* Read the IAGR (Interrupt accepted group register) */
634
635 static unsigned8
636 read_iagr (struct hw *me,
637 struct mn103int *controller,
638 unsigned_word offset)
639 {
640 unsigned8 val;
641 switch (offset)
642 {
643 case 0:
644 {
645 if (!(controller->group[controller->interrupt_accepted_group].request
646 & controller->group[controller->interrupt_accepted_group].enable))
647 {
648 /* oops, lost the request */
649 val = 0;
650 HW_TRACE ((me, "read-iagr:0 lost-0"));
651 }
652 else
653 {
654 val = (controller->interrupt_accepted_group << 2);
655 HW_TRACE ((me, "read-iagr:0 %d", (int) val));
656 }
657 break;
658 }
659 case 1:
660 val = 0;
661 HW_TRACE ((me, "read-iagr:1 %d", (int) val));
662 break;
663 default:
664 val = 0;
665 HW_TRACE ((me, "read-iagr 0x%08lx bad offset", (long) offset));
666 break;
667 }
668 return val;
669 }
670
671
672 /* Reads/writes to the EXTMD (external interrupt trigger configuration
673 register) */
674
675 static struct mn103int_group *
676 external_group (struct mn103int *controller,
677 unsigned_word offset)
678 {
679 switch (offset)
680 {
681 case 0:
682 return &controller->group[IRQ0_PORT/4];
683 case 1:
684 return &controller->group[IRQ4_PORT/4];
685 default:
686 return NULL;
687 }
688 }
689
690 static unsigned8
691 read_extmd (struct hw *me,
692 struct mn103int *controller,
693 unsigned_word offset)
694 {
695 int gid;
696 unsigned8 val = 0;
697 struct mn103int_group *group = external_group (controller, offset);
698 if (group != NULL)
699 {
700 for (gid = 0; gid < 4; gid++)
701 {
702 val |= (group[gid].trigger << (gid * 2));
703 }
704 }
705 HW_TRACE ((me, "read-extmd 0x%02lx", (long) val));
706 return val;
707 }
708
709 static void
710 write_extmd (struct hw *me,
711 struct mn103int *controller,
712 unsigned_word offset,
713 unsigned8 val)
714 {
715 int gid;
716 struct mn103int_group *group = external_group (controller, offset);
717 if (group != NULL)
718 {
719 for (gid = 0; gid < 4; gid++)
720 {
721 group[gid].trigger = (val >> (gid * 2)) & 0x3;
722 /* MAYBE: interrupts already pending? */
723 }
724 }
725 HW_TRACE ((me, "write-extmd 0x%02lx", (long) val));
726 }
727
728
729 /* generic read/write */
730
731 static int
732 decode_addr (struct hw *me,
733 struct mn103int *controller,
734 unsigned_word address,
735 unsigned_word *offset)
736 {
737 int i;
738 for (i = 0; i < NR_BLOCKS; i++)
739 {
740 if (address >= controller->block[i].base
741 && address <= controller->block[i].bound)
742 {
743 *offset = address - controller->block[i].base;
744 return i;
745 }
746 }
747 hw_abort (me, "bad address");
748 return -1;
749 }
750
751 static unsigned
752 mn103int_io_read_buffer (struct hw *me,
753 void *dest,
754 int space,
755 unsigned_word base,
756 unsigned nr_bytes)
757 {
758 struct mn103int *controller = hw_data (me);
759 unsigned8 *buf = dest;
760 unsigned byte;
761 /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */
762 for (byte = 0; byte < nr_bytes; byte++)
763 {
764 unsigned_word address = base + byte;
765 unsigned_word offset;
766 switch (decode_addr (me, controller, address, &offset))
767 {
768 case ICR_BLOCK:
769 buf[byte] = read_icr (me, controller, offset);
770 break;
771 case IAGR_BLOCK:
772 buf[byte] = read_iagr (me, controller, offset);
773 break;
774 case EXTMD_BLOCK:
775 buf[byte] = read_extmd (me, controller, offset);
776 break;
777 default:
778 hw_abort (me, "bad switch");
779 }
780 }
781 return nr_bytes;
782 }
783
784 static unsigned
785 mn103int_io_write_buffer (struct hw *me,
786 const void *source,
787 int space,
788 unsigned_word base,
789 unsigned nr_bytes)
790 {
791 struct mn103int *controller = hw_data (me);
792 const unsigned8 *buf = source;
793 unsigned byte;
794 /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */
795 for (byte = 0; byte < nr_bytes; byte++)
796 {
797 unsigned_word address = base + byte;
798 unsigned_word offset;
799 switch (decode_addr (me, controller, address, &offset))
800 {
801 case ICR_BLOCK:
802 write_icr (me, controller, offset, buf[byte]);
803 break;
804 case IAGR_BLOCK:
805 /* not allowed */
806 break;
807 case EXTMD_BLOCK:
808 write_extmd (me, controller, offset, buf[byte]);
809 break;
810 default:
811 hw_abort (me, "bad switch");
812 }
813 }
814 return nr_bytes;
815 }
816
817 static int
818 mn103int_ioctl(struct hw *me,
819 hw_ioctl_request request,
820 va_list ap)
821 {
822 struct mn103int *controller = (struct mn103int *)hw_data(me);
823 controller->group[0].request = EXTRACT_ID(4);
824 mn103int_port_event(me, 2 /* nmi_port(syserr) */, NULL, 0, 0);
825 return 0;
826 }
827
828
829 const struct hw_descriptor dv_mn103int_descriptor[] = {
830 { "mn103int", mn103int_finish, },
831 { NULL },
832 };