13 Upstream_irq const *const _prev;
18 * Abstraction for an IRQ controller chip.
23 virtual void mask(Mword pin) = 0;
24 virtual void unmask(Mword pin) = 0;
25 virtual void ack(Mword pin) = 0;
26 virtual void mask_and_ack(Mword pin) = 0;
29 * Set the trigger mode and polarity.
31 virtual unsigned set_mode(Mword pin, unsigned) = 0;
35 * \param pin the pin to configure
36 * \param cpu the logical CPU number.
38 virtual void set_cpu(Mword pin, Cpu_number cpu) = 0;
39 virtual void unbind(Irq_base *irq);
40 virtual ~Irq_chip() = 0;
44 * Artificial IRQ chip, used for SW IRQs.
46 class Irq_chip_soft : public Irq_chip
51 void mask_and_ack(Mword) {}
54 void set_cpu(Mword, Cpu_number) {}
55 unsigned set_mode(Mword, unsigned mode) { return mode; }
57 char const *chip_type() const { return "Soft"; }
59 static Irq_chip_soft sw_chip;
63 * Abstract IRQ controller chip that is visble as part of the
66 class Irq_chip_icu : public Irq_chip
69 virtual bool reserve(Mword pin) = 0;
70 virtual bool alloc(Irq_base *irq, Mword pin) = 0;
71 virtual Irq_base *irq(Mword pin) const = 0;
72 virtual unsigned nr_irqs() const = 0;
73 virtual ~Irq_chip_icu() = 0;
81 * Base class for all kinds of IRQ consuming objects.
85 friend class Irq_chip;
89 typedef void (*Hit_func)(Irq_base *, Upstream_irq const *);
108 Irq_base() : _flags(Trigger_level), _next(0)
110 Irq_chip_soft::sw_chip.bind(this, 0, true);
114 void hit(Upstream_irq const *ui) { hit_func(this, ui); }
116 Mword pin() const { return _pin; }
117 Irq_chip *chip() const { return _chip; }
119 void mask() { if (!__mask()) _chip->mask(_pin); }
123 _chip->mask_and_ack(_pin);
128 void unmask() { if (__unmask()) _chip->unmask(_pin); }
129 void ack() { _chip->ack(_pin); }
132 void set_mode(unsigned m)
134 unsigned mode = _chip->set_mode(_pin, m);
135 _flags = (_flags & ~0xe) | (mode & 0xe);
139 void set_cpu(Cpu_number cpu) { _chip->set_cpu(_pin, cpu); }
141 unsigned get_mode() const
142 { return _flags & 0xe; }
144 bool masked() const { return !(_flags & F_enabled); }
145 Mword flags() const { return _flags; }
147 void unbind() { _chip->unbind(this); }
149 bool __mask() { bool o = masked(); _flags &= ~F_enabled; return o; }
150 bool __unmask() { bool o = masked(); _flags |= F_enabled; return o; }
152 void set_hit(Hit_func f) { hit_func = f; }
153 virtual void switch_mode(unsigned mode) = 0;
154 virtual ~Irq_base() = 0;
164 static void handler_wrapper(Irq_base *irq, Upstream_irq const *ui)
165 { nonull_static_cast<T*>(irq)->handle(ui); }
170 static Irq_base *(*dcast)(Kobject_iface *);
176 //----------------------------------------------------------------------------
179 EXTENSION class Irq_chip
182 virtual char const *chip_type() const = 0;
186 //--------------------------------------------------------------------------
190 #include "cpu_lock.h"
191 #include "lock_guard.h"
192 #include "static_init.h"
194 Irq_chip_soft Irq_chip_soft::sw_chip INIT_PRIORITY(EARLY_INIT_PRIO);
195 Irq_base *(*Irq_base::dcast)(Kobject_iface *);
197 IMPLEMENT inline Irq_chip::~Irq_chip() {}
198 IMPLEMENT inline Irq_chip_icu::~Irq_chip_icu() {}
199 IMPLEMENT inline Irq_base::~Irq_base() {}
201 PUBLIC inline explicit
202 Upstream_irq::Upstream_irq(Irq_base const *b, Upstream_irq const *prev)
203 : _c(b->chip()), _p(b->pin()), _prev(prev)
208 Upstream_irq::ack() const
210 for (Upstream_irq const *c = this; c; c = c->_prev)
217 Irq_chip::bind(Irq_base *irq, Mword pin, bool ctor = false)
225 irq->set_mode(irq->get_mode());
234 Irq_chip::unbind(Irq_base *irq)
236 Irq_chip_soft::sw_chip.bind(irq, 0, true);
241 * \param CHIP must be the dynamic type of the object.
244 template<typename CHIP>
246 Irq_chip::handle_irq(Mword pin, Upstream_irq const *ui)
248 // call the irq function of the chip avoiding the
249 // virtual function call overhead.
250 Irq_base *irq = nonull_static_cast<CHIP*>(this)->CHIP::irq(pin);
256 template<typename CHIP>
258 Irq_chip::handle_multi_pending(Upstream_irq const *ui)
260 while (Mword pend = nonull_static_cast<CHIP*>(this)->CHIP::pending())
262 for (unsigned i = 0; i < sizeof(Mword)*8; ++i, pend >>= 1)
265 handle_irq<CHIP>(i, ui);
266 break; // read the pending ints again
272 PUBLIC inline NEEDS["lock_guard.h", "cpu_lock.h"]
276 auto g = lock_guard(cpu_lock);
281 // --------------------------------------------------------------------------
282 IMPLEMENTATION [!debug]:
284 PUBLIC inline void Irq_base::log() {}
286 //-----------------------------------------------------------------------------
289 #include "tb_entry.h"
291 EXTENSION class Irq_base
294 struct Irq_log : public Tb_entry
299 unsigned print(int max, char *buf) const;
304 // --------------------------------------------------------------------------
305 IMPLEMENTATION [debug]:
310 #include "kobject_dbg.h"
314 Irq_base::Irq_log::print(int maxlen, char *buf) const
316 Kobject_dbg::Const_iterator irq = Kobject_dbg::pointer_to_obj(obj);
318 if (irq != Kobject_dbg::end())
319 return snprintf(buf, maxlen, "0x%lx/%lu @ chip %s(%p) D:%lx",
320 pin, pin, chip->chip_type(), chip,
323 return snprintf(buf, maxlen, "0x%lx/%lu @ chip %s(%p) irq=%p",
324 pin, pin, chip->chip_type(), chip,
328 PUBLIC inline NEEDS["logdefs.h"]
332 Context *c = current();
333 LOG_TRACE("IRQ-Object triggers", "irq", c, Irq_log,