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