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