- kdevelop3 project files
[lightOS.git] / kernel / event_manager.cpp
blob974d7a2d838dc9c3e091e27070efd0985d2e1946
1 /*
2 lightOS kernel
3 Copyright (C) 2007-2009 Jörg Pfähler
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <kernel/log.hpp>
20 #include <kernel/event_manager.hpp>
21 #include <kernel/x86_shared/interrupt_controller.hpp>
22 using namespace std;
23 using namespace kernel;
25 SINGLETON_INSTANCE(kernel::event_manager);
28 kernel::event_manager::event_manager()
29 : mTicks(0)
33 kernel::event_manager::~event_manager()
37 size_t event_manager::register_irq(libkernel::port_id_t port,
38 size_t param1,
39 size_t param2)
41 // TODO: We should check whether this irq/params combination is really supposed to be used by this process
43 uint8_t bus = param1 & 0xFF;
44 uint8_t irq = (param1 >> 8) & 0xFF;
45 uint8_t busnr = param2 & 0xFF;
46 uint8_t dev = (param2 >> 8) & 0xFF;
47 uint8_t intn = (param1 >> 16) & 0xFF;
48 uint8_t priority = (param2 >> 24) & 0xFF;
50 uint8_t vector = 0;
51 interrupt_controller &InterruptController = interrupt_controller::instance();
52 if (bus == BUS_ID_ISA)
53 vector = InterruptController.register_isa_irq(irq, priority);
54 else if (bus == BUS_ID_PCI)
55 vector = InterruptController.register_pci_irq(irq, intn, busnr, dev, priority);
57 if (vector != 0)
59 LOCK(mIRQLock);
61 mIRQEvents.push_back(pair<libkernel::port_id_t, size_t>(port, vector));
63 UNLOCK(mIRQLock);
66 return vector;
69 void event_manager::acknoledge_irq(libkernel::port_id_t port,
70 size_t irq_id)
72 LOCK(mIRQLock);
74 auto end = mIRQEvents.end();
75 for (auto i = mIRQEvents.begin();i != end;i++)
76 if ((*i).first == port &&
77 (*i).second == irq_id)
79 interrupt_controller &InterruptController = interrupt_controller::instance();
80 InterruptController.acknoledge_irq(irq_id);
81 UNLOCK(mIRQLock);
82 return;
85 UNLOCK(mIRQLock);
88 void event_manager::unregister_irq(libkernel::port_id_t port,
89 size_t irq_id)
91 LOCK(mIRQLock);
93 auto end = mIRQEvents.end();
94 for (auto i = mIRQEvents.begin();i != end;i++)
95 if ((*i).first == port &&
96 (*i).second == irq_id)
98 interrupt_controller &InterruptController = interrupt_controller::instance();
99 InterruptController.unregister_irq((*i).second);
100 mIRQEvents.erase(i);
101 UNLOCK(mIRQLock);
102 return;
105 UNLOCK(mIRQLock);
108 void event_manager::handle_irq(uint8_t vector)
110 LOCK(mIRQLock);
112 auto end = mIRQEvents.end();
113 for (auto i = mIRQEvents.begin();i != end;i++)
114 if ((*i).second == vector)
116 libkernel::message_t msg((*i).first, libkernel::message::event, libkernel::event::irq, vector, 0);
117 port_manager &PortManager = port_manager::instance();
118 PortManager.send(libkernel::message_port::kernel, msg);
121 UNLOCK(mIRQLock);
124 void event_manager::register_timer(libkernel::port_id_t port,
125 uint64_t microseconds,
126 bool periodic)
128 LOCK(mLock);
130 timer_event event;
131 event.port = port;
132 event.remaining = microseconds * 1000;
133 event.microseconds = microseconds * 1000;
134 event.periodic = periodic;
135 mTimerEvents.push_back(event);
137 UNLOCK(mLock);
140 void event_manager::unregister_timer(libkernel::port_id_t port)
142 LOCK(mLock);
144 std::vector<timer_event>::iterator end = mTimerEvents.end();
145 for (std::vector<timer_event>::iterator i = mTimerEvents.begin();i != end;i++)
146 if ((*i).port == port)
148 mTimerEvents.erase(i);
149 UNLOCK(mLock);
150 return;
153 UNLOCK(mLock);
156 void event_manager::tick(uint64_t microseconds)
158 LOCK(mLock);
160 mTicks += microseconds;
162 for (size_t i = 0;i < mTimerEvents.size();)
164 if (mTimerEvents[i].remaining < microseconds)
166 // Send the message
167 libkernel::message_t msg(mTimerEvents[i].port,
168 libkernel::message::event,
169 libkernel::event::timer,
172 port_manager &PortManager = port_manager::instance();
173 PortManager.send(libkernel::message_port::kernel, msg);
175 // Is periodic?
176 if (mTimerEvents[i].periodic == true)
178 mTimerEvents[i].remaining = mTimerEvents[i].microseconds;
179 i++;
181 else
182 mTimerEvents.erase(mTimerEvents.begin() + i);
184 else
186 mTimerEvents[i].remaining -= microseconds;
187 i++;
191 UNLOCK(mLock);
194 size_t event_manager::get_ticks()
196 LOCK(mLock);
198 size_t result = mTicks / 1000;
200 UNLOCK(mLock);
201 return result;