13#include "pedigree/kernel/Atomic.h"
14#include "pedigree/kernel/LockGuard.h"
15#include "pedigree/kernel/Log.h"
16#include "pedigree/kernel/compiler.h"
17#include "pedigree/kernel/machine/IrqHandler.h"
18#include "pedigree/kernel/machine/IrqManager.h"
19#include "pedigree/kernel/machine/Machine.h"
20#include "pedigree/kernel/machine/types.h"
21#include "pedigree/kernel/process/Mutex.h"
22#include "pedigree/kernel/process/Semaphore.h"
23#include "pedigree/kernel/processor/types.h"
41 : handler(
nullptr), device(
nullptr), registration(0), counter(0)
45 void (*handler)(
struct cdi_device *);
46 struct cdi_device *device;
47 irq_id_t registration;
51static Mutex irqSlotLock;
61int waitForIrqCounter(
Semaphore &counter, uint32_t timeout)
68 Semaphore::SemaphoreError error = Semaphore::NoError;
70 1, timeout / 1000, (timeout % 1000) * 1000, error);
71 return acquired ? 0 : -3;
82 return IrqDisposition::NotHandled;
85 void (*handler)(
struct cdi_device *) =
nullptr;
86 struct cdi_device *device =
nullptr;
89 handler = driverIrqs[
irq].handler;
90 device = driverIrqs[
irq].device;
94 return IrqDisposition::NotHandled;
98 return IrqDisposition::Handled;
109EXPORTED_PUBLIC
void cdi_register_irq(
110 uint8_t irq,
void (*handler)(
struct cdi_device *),
111 struct cdi_device *device)
113 if (irq >= IRQ_COUNT)
125 if (driverIrqs[irq].handler)
127 NOTICE(
"cdi: Versuch IRQ " << irq <<
" mehrfach zu registrieren");
131 const size_t discarded = resetIrqCounter(driverIrqs[irq].counter);
133 driverIrqs[irq].handler = handler;
134 driverIrqs[irq].device = device;
137 const irq_id_t registration =
139 irq,
static_cast<IrqHandler *
>(&cdi_irq_handler),
140 IrqPolicy::levelThreaded());
144 driverIrqs[irq].handler =
nullptr;
145 driverIrqs[irq].device =
nullptr;
146 ERROR(
"cdi: IRQ " << irq <<
" konnte nicht registriert werden");
151 driverIrqs[irq].registration = registration;
161EXPORTED_PUBLIC
int cdi_reset_wait_irq(uint8_t irq)
163 if (irq >= IRQ_COUNT)
169 if (!driverIrqs[irq].handler)
174 const size_t discarded = resetIrqCounter(driverIrqs[irq].counter);
192EXPORTED_PUBLIC
int cdi_wait_irq(uint8_t irq, uint32_t timeout)
194 if (irq >= IRQ_COUNT)
201 if (!driverIrqs[irq].handler)
205 return waitForIrqCounter(driverIrqs[irq].counter, timeout);
209#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
214void hostedCdiIrqHandler(
struct cdi_device *)
216 g_HostedCdiIrqCalls += 1;
220bool runHostedCdiIrqRegressions()
222 constexpr uint8_t TestIrq = IRQ_COUNT - 1;
225 g_HostedCdiIrqCalls = 0;
226 const size_t discarded = resetIrqCounter(driverIrqs[TestIrq].counter);
228 driverIrqs[TestIrq].handler = hostedCdiIrqHandler;
229 driverIrqs[TestIrq].device =
nullptr;
233 const bool reset = cdi_reset_wait_irq(TestIrq) == 0;
234 const bool emptyAfterReset = !driverIrqs[TestIrq].counter.
tryAcquire();
235 const bool zeroTimeout = cdi_wait_irq(TestIrq, 0) == -3;
236 driverIrqs[TestIrq].counter.
release();
237 const bool zeroSuccess = cdi_wait_irq(TestIrq, 0) == 0;
238 driverIrqs[TestIrq].counter.
release();
239 const bool finiteSuccess = cdi_wait_irq(TestIrq, 1) == 0;
240 const bool finiteTimeout = cdi_wait_irq(TestIrq, 1) == -3;
241 const bool invalidReset = cdi_reset_wait_irq(IRQ_COUNT) == -1;
242 const bool invalidWait = cdi_wait_irq(IRQ_COUNT, 0) == -1;
246 driverIrqs[TestIrq].handler =
nullptr;
247 driverIrqs[TestIrq].device =
nullptr;
248 const size_t discarded = resetIrqCounter(driverIrqs[TestIrq].counter);
252 const bool passed = disposition == IrqDisposition::Handled &&
253 g_HostedCdiIrqCalls == 1 && reset && emptyAfterReset &&
254 zeroTimeout && zeroSuccess && finiteSuccess &&
255 finiteTimeout && invalidReset && invalidWait;
258 NOTICE(
"HOSTED-WAIT-TEST: PASS cdi-irq-wait-contract");
262 ERROR(
"HOSTED-WAIT-TEST: FAIL cdi-irq-wait-contract");
IrqDisposition irq(irq_id_t number) override
virtual irq_id_t registerIsaIrqHandler(uint8_t irq, IrqHandler *handler, const IrqPolicy &policy)=0
MUST_USE_RESULT bool acquireWithError(size_t n, size_t timeoutSecs, size_t timeoutUsecs, SemaphoreError &error)
MUST_USE_RESULT size_t drainAvailable()
bool tryAcquire(size_t n=1)