This commit was generated by cvs2svn to track changes on a CVS vendor
[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 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 };