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