Skip to content

Commit 1ee3724

Browse files
supercomputer7awesomekling
authored andcommitted
Kernel: Introduce IRQ sharing support
The support is very basic - Each component that needs to handle IRQs inherits from InterruptHandler class. When the InterruptHandler constructor is called it registers itself in a SharedInterruptHandler. When an IRQ is fired, the SharedInterruptHandler is invoked, then it iterates through a list of the registered InterruptHandlers. Also, InterruptEnabler class was created to provide a way to enable IRQ handling temporarily, similar to InterruptDisabler (in CPU.h, which does the opposite). In addition to that a PCI::Device class has been added, that inherits from InterruptHandler.
1 parent 2a160fa commit 1ee3724

File tree

7 files changed

+399
-0
lines changed

7 files changed

+399
-0
lines changed

Kernel/InterruptHandler.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice, this
9+
* list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
*/
26+
27+
#include <Kernel/InterruptHandler.h>
28+
#include <Kernel/SharedInterruptHandler.h>
29+
30+
InterruptHandler::InterruptHandler(u8 irq)
31+
: m_irq_number(irq)
32+
{
33+
SharedInterruptHandler::from(m_irq_number).register_handler(*this);
34+
disable_interrupts();
35+
}
36+
37+
InterruptHandler::~InterruptHandler()
38+
{
39+
disable_interrupts();
40+
SharedInterruptHandler::from(m_irq_number).unregister_handler(*this);
41+
}
42+
43+
void InterruptHandler::enable_interrupts()
44+
{
45+
m_enabled = true;
46+
}
47+
48+
void InterruptHandler::change_irq_number(u8 irq_number)
49+
{
50+
bool was_enabled = m_enabled;
51+
disable_interrupts();
52+
SharedInterruptHandler::from(m_irq_number).unregister_handler(*this);
53+
m_irq_number = irq_number;
54+
SharedInterruptHandler::from(m_irq_number).register_handler(*this);
55+
if (was_enabled)
56+
enable_interrupts();
57+
}
58+
59+
void InterruptHandler::disable_interrupts()
60+
{
61+
m_enabled = false;
62+
}
63+
64+
InterruptHandler::Enabler::Enabler(InterruptHandler& handler)
65+
: m_handler(handler)
66+
, m_was_enabled(m_handler.is_enabled())
67+
{
68+
m_handler.enable_interrupts();
69+
}
70+
InterruptHandler::Enabler::~Enabler()
71+
{
72+
if (!m_was_enabled)
73+
m_handler.disable_interrupts();
74+
}

Kernel/InterruptHandler.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice, this
9+
* list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
*/
26+
27+
#pragma once
28+
29+
#include <AK/Types.h>
30+
31+
class InterruptHandler {
32+
public:
33+
class Enabler {
34+
public:
35+
explicit Enabler(InterruptHandler&);
36+
~Enabler();
37+
38+
private:
39+
InterruptHandler& m_handler;
40+
bool m_was_enabled;
41+
};
42+
friend class Enabler;
43+
44+
public:
45+
virtual ~InterruptHandler();
46+
virtual void handle_interrupt() = 0;
47+
48+
u8 irq_number() const { return m_irq_number; }
49+
bool is_enabled() const { return m_enabled; }
50+
51+
protected:
52+
void enable_interrupts();
53+
void change_irq_number(u8 irq_number);
54+
void disable_interrupts();
55+
explicit InterruptHandler(u8 irq);
56+
57+
private:
58+
bool m_enabled { false };
59+
u8 m_irq_number { 0 };
60+
};

Kernel/PCI/Definitions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,6 @@ class Access;
178178
class MMIOAccess;
179179
class IOAccess;
180180
class MMIOSegment;
181+
class Device;
181182

182183
}

Kernel/PCI/Device.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice, this
9+
* list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
*/
26+
27+
#include <Kernel/PCI/Device.h>
28+
29+
PCI::Device::Device(PCI::Address address)
30+
: InterruptHandler(PCI::get_interrupt_line(address))
31+
, m_pci_address(address)
32+
{
33+
// FIXME: Register PCI device somewhere...
34+
}
35+
36+
PCI::Device::Device(PCI::Address address, u8 interrupt_vector)
37+
: InterruptHandler(interrupt_vector)
38+
, m_pci_address(address)
39+
{
40+
// FIXME: Register PCI device somewhere...
41+
}
42+
43+
PCI::Device::~Device()
44+
{
45+
// FIXME: Unregister the device
46+
}

Kernel/PCI/Device.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice, this
9+
* list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
*/
26+
27+
#pragma once
28+
29+
#include <AK/Types.h>
30+
#include <Kernel/InterruptHandler.h>
31+
#include <Kernel/PCI/Definitions.h>
32+
33+
class PCI::Device : public InterruptHandler {
34+
public:
35+
Address get_pci_address() const { return m_pci_address; };
36+
37+
protected:
38+
Device(Address pci_address);
39+
Device(Address pci_address, u8 interrupt_vector);
40+
~Device();
41+
42+
private:
43+
Address m_pci_address;
44+
};

Kernel/SharedInterruptHandler.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice, this
9+
* list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
*/
26+
27+
#include <Kernel/Arch/i386/CPU.h>
28+
#include <Kernel/Arch/i386/PIC.h>
29+
#include <Kernel/InterruptHandler.h>
30+
#include <Kernel/SharedInterruptHandler.h>
31+
32+
//#define INTERRUPT_DEBUG
33+
34+
SharedInterruptHandler& SharedInterruptHandler::from(u8 interrupt_number)
35+
{
36+
return get_interrupt_handler(interrupt_number);
37+
}
38+
39+
void SharedInterruptHandler::initialize(u8 interrupt_number)
40+
{
41+
new SharedInterruptHandler(interrupt_number);
42+
}
43+
44+
void SharedInterruptHandler::register_handler(InterruptHandler& handler)
45+
{
46+
#ifdef INTERRUPT_DEBUG
47+
kprintf("Interrupt Handler registered @ Shared Interrupt Handler %d\n", m_interrupt_number);
48+
#endif
49+
m_handlers.set(&handler);
50+
enable_interrupt_vector();
51+
}
52+
void SharedInterruptHandler::unregister_handler(InterruptHandler& handler)
53+
{
54+
#ifdef INTERRUPT_DEBUG
55+
kprintf("Interrupt Handler unregistered @ Shared Interrupt Handler %d\n", m_interrupt_number);
56+
#endif
57+
m_handlers.remove(&handler);
58+
if (m_handlers.is_empty())
59+
disable_interrupt_vector();
60+
}
61+
62+
SharedInterruptHandler::SharedInterruptHandler(u8 interrupt_number)
63+
: m_interrupt_number(interrupt_number)
64+
, m_enabled(true)
65+
{
66+
#ifdef INTERRUPT_DEBUG
67+
kprintf("Shared Interrupt Handler registered @ %d\n", m_interrupt_number);
68+
#endif
69+
register_shared_interrupt_handler(m_interrupt_number, *this);
70+
disable_interrupt_vector();
71+
}
72+
73+
SharedInterruptHandler::~SharedInterruptHandler()
74+
{
75+
#ifdef INTERRUPT_DEBUG
76+
kprintf("Shared Interrupt Handler unregistered @ %d\n", m_interrupt_number);
77+
#endif
78+
disable_interrupt_vector();
79+
unregister_shared_interrupt_handler(m_interrupt_number, *this);
80+
}
81+
82+
void SharedInterruptHandler::handle_interrupt()
83+
{
84+
#ifdef INTERRUPT_DEBUG
85+
kprintf("Interrupt @ %d\n", m_interrupt_number);
86+
kprintf("Interrupt Handlers registered - %d\n", m_handlers.size());
87+
#endif
88+
int i = 0;
89+
for (auto* handler : m_handlers) {
90+
#ifdef INTERRUPT_DEBUG
91+
kprintf("Going for Interrupt Handling @ %d, Shared Interrupt %d\n", i, m_interrupt_number);
92+
#endif
93+
ASSERT(handler != nullptr);
94+
if (handler->is_enabled())
95+
handler->handle_interrupt();
96+
97+
#ifdef INTERRUPT_DEBUG
98+
kprintf("Going for Interrupt Handling @ %d, Shared Interrupt %d - End\n", i, m_interrupt_number);
99+
#endif
100+
i++;
101+
}
102+
// FIXME: Determine if we use IRQs or MSIs (in the future) to send EOI...
103+
}
104+
105+
void SharedInterruptHandler::enable_interrupt_vector()
106+
{
107+
if (m_enabled)
108+
return;
109+
m_enabled = true;
110+
// FIXME: Determine if we use IRQs or MSIs (in the future) to enable the interrupt vector...
111+
PIC::enable(m_interrupt_number);
112+
}
113+
114+
void SharedInterruptHandler::disable_interrupt_vector()
115+
{
116+
if (!m_enabled)
117+
return;
118+
m_enabled = false;
119+
// FIXME: Determine if we use IRQs or MSIs (in the future) to disable the interrupt vector...
120+
PIC::disable(m_interrupt_number);
121+
}

0 commit comments

Comments
 (0)