7 * Flexible IRQ manager (manages multiple IRQ chips).
9 * This manager allow to manage up to `MAX_CHIPS` IRQ chips, where each chip
10 * gets a contiguous range of externally visible (global IRQ numbers)
11 * assigned. The ranges of the different chips must not overlap. However each
12 * chip can start at an arbitrary 16bit IRQ number.
14 template<unsigned MAX_CHIPS>
15 class Irq_mgr_flex : public Irq_mgr
18 unsigned max_chips() const { return MAX_CHIPS; }
20 unsigned nr_irqs() const override
23 unsigned nr_msis() const override
26 Irq chip(Mword irqnum) const override
28 for (unsigned i = 0; i < _used; ++i)
29 if (irqnum < _chips[i].end)
30 return Irq(_chips[i].chip, irqnum - _chips[i].start);
36 * Add a chip starting its range at `pos`.
37 * \param chip The chip to add.
38 * \param pos The first global IRQ number assigned to pin 0 of `chip`.
39 * use `-1` to assign the next free global IRQ number.
41 * This function checks for overlaps and returns an error string in case
44 char const *add_chip(Irq_chip_icu *chip, int pos = -1)
46 if (_used >= MAX_CHIPS)
47 return "too many IRQ chips";
49 unsigned n = chip->nr_irqs();
51 return "chip with zero interrupts";
56 if (pos >= (int)_max_irq)
59 auto &e = _chips[_used++];
68 for (unsigned x = 0; x < _used; ++x)
75 if (pos + n >= spot->start)
76 return "overlapping interrupt ranges";
79 for (Chip *x = &_chips[_used]; x >= spot; --x)
88 if (pos + n > _max_irq)
102 unsigned _max_irq = 0;
103 Chip _chips[MAX_CHIPS];
106 IMPLEMENTATION [!debug]:
108 PUBLIC template<unsigned MAX_CHIPS>
110 Irq_mgr_flex<MAX_CHIPS>::print_infos()
112 for (auto *e = _chips; e != _chips + _used; ++e)
113 printf(" %3d-%3d: @%p\n", e->start, e->end - 1, e->chip);
115 IMPLEMENTATION [debug]:
117 PUBLIC template<unsigned MAX_CHIPS>
119 Irq_mgr_flex<MAX_CHIPS>::print_infos()
121 for (auto *e = _chips; e != _chips + _used; ++e)
122 printf(" %3d-%3d: %s\n", e->start, e->end - 1, e->chip->chip_type());