forked from Bananymous/banan-os
Kernel: Rework interrupt mechanism
All interruptrable classes now inherit from Interruptable which has methdo handle_irq which is called on a interrupt.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include <kernel/ACPI.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/IDT.h>
|
||||
#include <kernel/Input/PS2Config.h>
|
||||
#include <kernel/Input/PS2Controller.h>
|
||||
#include <kernel/Input/PS2Keyboard.h>
|
||||
#include <kernel/InterruptController.h>
|
||||
@@ -11,77 +12,6 @@
|
||||
namespace Kernel::Input
|
||||
{
|
||||
|
||||
namespace PS2
|
||||
{
|
||||
|
||||
enum IOPort : uint8_t
|
||||
{
|
||||
DATA = 0x60,
|
||||
STATUS = 0x64,
|
||||
COMMAND = 0x64,
|
||||
};
|
||||
|
||||
enum Status : uint8_t
|
||||
{
|
||||
OUTPUT_FULL = (1 << 0),
|
||||
INPUT_FULL = (1 << 1),
|
||||
SYSTEM = (1 << 2),
|
||||
DEVICE_OR_CONTROLLER = (1 << 3),
|
||||
TIMEOUT_ERROR = (1 << 6),
|
||||
PARITY_ERROR = (1 << 7),
|
||||
};
|
||||
|
||||
enum Config : uint8_t
|
||||
{
|
||||
INTERRUPT_FIRST_PORT = (1 << 0),
|
||||
INTERRUPT_SECOND_PORT = (1 << 1),
|
||||
SYSTEM_FLAG = (1 << 2),
|
||||
ZERO1 = (1 << 3),
|
||||
CLOCK_FIRST_PORT = (1 << 4),
|
||||
CLOCK_SECOND_PORT = (1 << 5),
|
||||
TRANSLATION_FIRST_PORT = (1 << 6),
|
||||
ZERO2 = (1 << 7),
|
||||
};
|
||||
|
||||
enum Command : uint8_t
|
||||
{
|
||||
READ_CONFIG = 0x20,
|
||||
WRITE_CONFIG = 0x60,
|
||||
DISABLE_SECOND_PORT = 0xA7,
|
||||
ENABLE_SECOND_PORT = 0xA8,
|
||||
TEST_SECOND_PORT = 0xA9,
|
||||
TEST_CONTROLLER = 0xAA,
|
||||
TEST_FIRST_PORT = 0xAB,
|
||||
DISABLE_FIRST_PORT = 0xAD,
|
||||
ENABLE_FIRST_PORT = 0xAE,
|
||||
WRITE_TO_SECOND_PORT = 0xD4,
|
||||
};
|
||||
|
||||
enum Response
|
||||
{
|
||||
TEST_FIRST_PORT_PASS = 0x00,
|
||||
TEST_SECOND_PORT_PASS = 0x00,
|
||||
TEST_CONTROLLER_PASS = 0x55,
|
||||
SELF_TEST_PASS = 0xAA,
|
||||
ACK = 0xFA,
|
||||
};
|
||||
|
||||
enum DeviceCommand
|
||||
{
|
||||
ENABLE_SCANNING = 0xF4,
|
||||
DISABLE_SCANNING = 0xF5,
|
||||
IDENTIFY = 0xF2,
|
||||
RESET = 0xFF,
|
||||
};
|
||||
|
||||
enum IRQ
|
||||
{
|
||||
DEVICE0 = 1,
|
||||
DEVICE1 = 12,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static constexpr uint64_t s_device_timeout_ms = 100;
|
||||
|
||||
static void controller_send_command(PS2::Command command)
|
||||
@@ -136,20 +66,6 @@ namespace Kernel::Input
|
||||
return {};
|
||||
}
|
||||
|
||||
void PS2Controller::device0_irq()
|
||||
{
|
||||
auto& controller = PS2Controller::get();
|
||||
ASSERT(controller.m_devices[0] != nullptr);
|
||||
controller.m_devices[0]->on_byte(IO::inb(PS2::IOPort::DATA));
|
||||
}
|
||||
|
||||
void PS2Controller::device1_irq()
|
||||
{
|
||||
auto& controller = PS2Controller::get();
|
||||
ASSERT(controller.m_devices[1] != nullptr);
|
||||
controller.m_devices[1]->on_byte(IO::inb(PS2::IOPort::DATA));
|
||||
}
|
||||
|
||||
static PS2Controller* s_instance = nullptr;
|
||||
|
||||
BAN::ErrorOr<void> PS2Controller::initialize()
|
||||
@@ -256,15 +172,15 @@ namespace Kernel::Input
|
||||
|
||||
if (m_devices[0])
|
||||
{
|
||||
IDT::register_irq_handler(PS2::IRQ::DEVICE0, device0_irq);
|
||||
InterruptController::get().enable_irq(PS2::IRQ::DEVICE0);
|
||||
m_devices[0]->set_irq(PS2::IRQ::DEVICE0);
|
||||
m_devices[0]->enable_interrupt();
|
||||
config |= PS2::Config::INTERRUPT_FIRST_PORT;
|
||||
DevFileSystem::get().add_device("input0", m_devices[0]);
|
||||
}
|
||||
if (m_devices[1])
|
||||
{
|
||||
IDT::register_irq_handler(PS2::IRQ::DEVICE1, device1_irq);
|
||||
InterruptController::get().enable_irq(PS2::IRQ::DEVICE1);
|
||||
m_devices[1]->set_irq(PS2::IRQ::DEVICE1);
|
||||
m_devices[1]->enable_interrupt();
|
||||
config |= PS2::Config::INTERRUPT_SECOND_PORT;
|
||||
DevFileSystem::get().add_device("input1", m_devices[1]);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/CriticalScope.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/Input/PS2Config.h>
|
||||
#include <kernel/Input/PS2Keyboard.h>
|
||||
#include <kernel/IO.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
@@ -12,35 +14,6 @@
|
||||
namespace Kernel::Input
|
||||
{
|
||||
|
||||
namespace PS2
|
||||
{
|
||||
|
||||
enum Response
|
||||
{
|
||||
KEY_ERROR_OR_BUFFER_OVERRUN1 = 0x00,
|
||||
SELF_TEST_PASSED = 0xAA,
|
||||
ECHO_RESPONSE = 0xEE,
|
||||
ACK = 0xFA,
|
||||
RESEND = 0xFE,
|
||||
KEY_ERROR_OR_BUFFER_OVERRUN2 = 0xFF,
|
||||
};
|
||||
|
||||
enum Scancode
|
||||
{
|
||||
SET_SCANCODE_SET1 = 1,
|
||||
SET_SCANCODE_SET2 = 2,
|
||||
SET_SCANCODE_SET3 = 3,
|
||||
};
|
||||
|
||||
enum Leds
|
||||
{
|
||||
SCROLL_LOCK = (1 << 0),
|
||||
NUM_LOCK = (1 << 1),
|
||||
CAPS_LOCK = (1 << 2),
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
BAN::ErrorOr<PS2Keyboard*> PS2Keyboard::create(PS2Controller& controller)
|
||||
{
|
||||
PS2Keyboard* keyboard = new PS2Keyboard(controller);
|
||||
@@ -57,8 +30,10 @@ namespace Kernel::Input
|
||||
, m_rdev(makedev(DevFileSystem::get().get_next_dev(), 0))
|
||||
{ }
|
||||
|
||||
void PS2Keyboard::on_byte(uint8_t byte)
|
||||
void PS2Keyboard::handle_irq()
|
||||
{
|
||||
uint8_t byte = IO::inb(PS2::IOPort::DATA);
|
||||
|
||||
// NOTE: This implementation does not allow using commands
|
||||
// that respond with more bytes than ACK
|
||||
switch (m_state)
|
||||
@@ -71,11 +46,11 @@ namespace Kernel::Input
|
||||
m_command_queue.pop();
|
||||
m_state = State::Normal;
|
||||
break;
|
||||
case PS2::Response::RESEND:
|
||||
case PS2::KBResponse::RESEND:
|
||||
m_state = State::Normal;
|
||||
break;
|
||||
case PS2::Response::KEY_ERROR_OR_BUFFER_OVERRUN1:
|
||||
case PS2::Response::KEY_ERROR_OR_BUFFER_OVERRUN2:
|
||||
case PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN1:
|
||||
case PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN2:
|
||||
dwarnln("Key detection error or internal buffer overrun");
|
||||
break;
|
||||
default:
|
||||
@@ -97,7 +72,7 @@ namespace Kernel::Input
|
||||
BAN::ErrorOr<void> PS2Keyboard::initialize()
|
||||
{
|
||||
append_command_queue(Command::SET_LEDS, 0x00);
|
||||
append_command_queue(Command::SCANCODE, PS2::Scancode::SET_SCANCODE_SET2);
|
||||
append_command_queue(Command::SCANCODE, PS2::KBScancode::SET_SCANCODE_SET2);
|
||||
append_command_queue(Command::ENABLE_SCANNING);
|
||||
return {};
|
||||
}
|
||||
@@ -234,11 +209,11 @@ namespace Kernel::Input
|
||||
{
|
||||
uint8_t new_leds = 0;
|
||||
if (m_modifiers & (uint8_t)Input::KeyEvent::Modifier::ScrollLock)
|
||||
new_leds |= PS2::Leds::SCROLL_LOCK;
|
||||
new_leds |= PS2::KBLeds::SCROLL_LOCK;
|
||||
if (m_modifiers & (uint8_t)Input::KeyEvent::Modifier::NumLock)
|
||||
new_leds |= PS2::Leds::NUM_LOCK;
|
||||
new_leds |= PS2::KBLeds::NUM_LOCK;
|
||||
if (m_modifiers & (uint8_t)Input::KeyEvent::Modifier::CapsLock)
|
||||
new_leds |= PS2::Leds::CAPS_LOCK;
|
||||
new_leds |= PS2::KBLeds::CAPS_LOCK;
|
||||
append_command_queue(Command::SET_LEDS, new_leds);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user