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