1 /*  This file is part of the program GDB, the GNU debugger.
2 
3     Copyright (C) 1998-2024 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
attach_mn103int_regs(struct hw * me,struct mn103int * controller)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
mn103int_finish(struct hw * me)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
find_highest_interrupt_group(struct hw * me,struct mn103int * controller)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
push_interrupt_level(struct hw * me,struct mn103int * controller)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
mn103int_port_event(struct hw * me,int my_port,struct hw * source,int source_port,int level)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 *
decode_group(struct hw * me,struct mn103int * controller,unsigned_word base,unsigned_word * offset)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 uint8_t
read_icr(struct hw * me,struct mn103int * controller,unsigned_word base)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   uint8_t 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
write_icr(struct hw * me,struct mn103int * controller,unsigned_word base,uint8_t val)571 write_icr (struct hw *me,
572              struct mn103int *controller,
573              unsigned_word base,
574              uint8_t 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 uint8_t
read_iagr(struct hw * me,struct mn103int * controller,unsigned_word offset)636 read_iagr (struct hw *me,
637              struct mn103int *controller,
638              unsigned_word offset)
639 {
640   uint8_t 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 *
external_group(struct mn103int * controller,unsigned_word offset)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 uint8_t
read_extmd(struct hw * me,struct mn103int * controller,unsigned_word offset)691 read_extmd (struct hw *me,
692               struct mn103int *controller,
693               unsigned_word offset)
694 {
695   int gid;
696   uint8_t 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
write_extmd(struct hw * me,struct mn103int * controller,unsigned_word offset,uint8_t val)710 write_extmd (struct hw *me,
711                struct mn103int *controller,
712                unsigned_word offset,
713                uint8_t 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
decode_addr(struct hw * me,struct mn103int * controller,unsigned_word address,unsigned_word * offset)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
mn103int_io_read_buffer(struct hw * me,void * dest,int space,unsigned_word base,unsigned nr_bytes)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   uint8_t *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
mn103int_io_write_buffer(struct hw * me,const void * source,int space,unsigned_word base,unsigned nr_bytes)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 uint8_t *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
mn103int_ioctl(struct hw * me,hw_ioctl_request request,va_list ap)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 };
833