1 // core/irq.cc -- generic IRQ handling
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
5 // This software is provided 'as-is', without any express or implied warranty.
6 // In no event will the authors or contributors be held liable for any damages
7 // arising from the use of this software.
9 // Permission is hereby granted to everyone, free of charge, to use, copy,
10 // modify, prepare derivative works of, publish, distribute, perform,
11 // sublicense, and/or sell copies of the Software, provided that the above
12 // copyright notice and disclaimer of warranty be included in all copies or
13 // substantial portions of this software.
16 #include <kern/kernel.h>
20 void InterruptController::request_int(InterruptSlot *slot, Interrupt *irq)
22 AutoSpinLockIRQ autolock(lock);
24 u32 irqnum = get_irqnum(slot);
25 Interrupt *list = slot->first_int;
26 Interrupt **insert = &slot->first_int;
30 throw_idl(ResourceBusy, -1, countarray("IRQ in use"));
38 irq->controller = this;
40 if (insert == &slot->first_int && slot->mask_count == 0) {
41 // There were no existing handlers, so it's currently masked
46 void InterruptController::free_int(Interrupt *irq)
48 InterruptSlot *slot = irq->slot;
49 u32 irqnum = get_irqnum(slot);
51 DroppableAutoSpinLockIRQ autolock(lock);
53 Interrupt *list = slot->first_int;
54 Interrupt **remove = &slot->first_int;
60 if (remove == &slot->first_int && !list->next &&
61 slot->mask_count == 0)
63 // It was the last handler for this IRQ num.
76 throw_idl(InvalidReference, 0, nullarray);
79 bool InterruptController::handle_irq(int irq)
81 DroppableAutoSpinLock autolock(lock);
82 bool handled_one = false;
83 bool irq_specified = irq >= 0;
89 irq = get_pending_irq();
97 InterruptSlot *slot = get_slot(irq);
99 if (slot->mask_count > 0 || slot->flags & InterruptSlot::Running) {
100 slot->flags |= InterruptSlot::Pending;
104 slot->flags |= InterruptSlot::Running;
105 assert(!(slot->flags & InterruptSlot::Pending));
109 for (Interrupt *i = slot->first_int; i; i = i->next)
110 handled_one |= i->action();
114 slot->flags &= ~InterruptSlot::Running;
116 if (slot->mask_count == 0)
118 } while (!irq_specified);
124 void InterruptController::rec_mask_nowait(InterruptSlot *slot)
126 AutoSpinLockIRQ autolock(lock);
127 u32 irq = get_irqnum(slot);
129 if (slot->mask_count++ == 0)
133 void InterruptController::rec_mask(InterruptSlot *slot)
135 rec_mask_nowait(slot);
139 void InterruptController::rec_unmask(InterruptSlot *slot)
141 bool was_pending = false;
142 DroppableAutoSpinLockRecIRQ autolock(lock);
144 if (--slot->mask_count == 0) {
145 unmask(get_irqnum(slot));
147 if (slot->flags & InterruptSlot::Pending) {
149 slot->flags &= ~InterruptSlot::Pending;
150 slot->flags |= InterruptSlot::Running;
157 // Only really necessary for edge-triggered interrupts
159 for (Interrupt *i = slot->first_int; i; i = i->next)
163 slot->flags &= ~InterruptSlot::Running;
168 void InterruptController::wait_for_irq(InterruptSlot *slot)
170 while (slot->flags & InterruptSlot::Running)
177 //#include "irq-server/footer.cc"