mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 21:57:35 +00:00
Kernel: Replace IRQHandler with the new InterruptHandler class
System components that need an IRQ handling are now inheriting the InterruptHandler class. In addition to that, the initialization process of PATAChannel was changed to fit the changes. PATAChannel, E1000NetworkAdapter and RTL8139NetworkAdapter are now inheriting from PCI::Device instead of InterruptHandler directly.
This commit is contained in:
parent
1ee37245cd
commit
6c72736b26
29 changed files with 193 additions and 169 deletions
|
@ -41,20 +41,20 @@ void ACPIDynamicParser::initialize_without_rsdp()
|
||||||
}
|
}
|
||||||
|
|
||||||
ACPIDynamicParser::ACPIDynamicParser()
|
ACPIDynamicParser::ACPIDynamicParser()
|
||||||
: IRQHandler(9)
|
: InterruptHandler(9)
|
||||||
, ACPIStaticParser()
|
, ACPIStaticParser()
|
||||||
|
|
||||||
{
|
{
|
||||||
kprintf("ACPI: Dynamic Parsing Enabled, Can parse AML\n");
|
kprintf("ACPI: Dynamic Parsing Enabled, Can parse AML\n");
|
||||||
}
|
}
|
||||||
ACPIDynamicParser::ACPIDynamicParser(ACPI_RAW::RSDPDescriptor20& rsdp)
|
ACPIDynamicParser::ACPIDynamicParser(ACPI_RAW::RSDPDescriptor20& rsdp)
|
||||||
: IRQHandler(9)
|
: InterruptHandler(9)
|
||||||
, ACPIStaticParser(rsdp)
|
, ACPIStaticParser(rsdp)
|
||||||
{
|
{
|
||||||
kprintf("ACPI: Dynamic Parsing Enabled, Can parse AML\n");
|
kprintf("ACPI: Dynamic Parsing Enabled, Can parse AML\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ACPIDynamicParser::handle_irq()
|
void ACPIDynamicParser::handle_interrupt()
|
||||||
{
|
{
|
||||||
// FIXME: Implement IRQ handling of ACPI signals!
|
// FIXME: Implement IRQ handling of ACPI signals!
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
@ -90,4 +90,4 @@ void ACPIDynamicParser::build_namespace()
|
||||||
{
|
{
|
||||||
// FIXME: Implement AML Interpretation to build the ACPI namespace
|
// FIXME: Implement AML Interpretation to build the ACPI namespace
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,12 @@
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <Kernel/ACPI/ACPIStaticParser.h>
|
#include <Kernel/ACPI/ACPIStaticParser.h>
|
||||||
#include <Kernel/Devices/DiskDevice.h>
|
#include <Kernel/Devices/DiskDevice.h>
|
||||||
#include <Kernel/IRQHandler.h>
|
#include <Kernel/InterruptHandler.h>
|
||||||
#include <Kernel/Lock.h>
|
#include <Kernel/Lock.h>
|
||||||
#include <Kernel/VM/PhysicalAddress.h>
|
#include <Kernel/VM/PhysicalAddress.h>
|
||||||
#include <Kernel/VM/PhysicalPage.h>
|
#include <Kernel/VM/PhysicalPage.h>
|
||||||
|
|
||||||
class ACPIDynamicParser final : public IRQHandler
|
class ACPIDynamicParser final : public InterruptHandler
|
||||||
, ACPIStaticParser {
|
, ACPIStaticParser {
|
||||||
public:
|
public:
|
||||||
static void initialize(ACPI_RAW::RSDPDescriptor20& rsdp);
|
static void initialize(ACPI_RAW::RSDPDescriptor20& rsdp);
|
||||||
|
@ -53,7 +53,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
void build_namespace();
|
void build_namespace();
|
||||||
// ^IRQHandler
|
// ^IRQHandler
|
||||||
virtual void handle_irq() override;
|
virtual void handle_interrupt() override;
|
||||||
|
|
||||||
OwnPtr<Region> m_acpi_namespace;
|
OwnPtr<Region> m_acpi_namespace;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,12 +26,12 @@
|
||||||
|
|
||||||
#include "APIC.h"
|
#include "APIC.h"
|
||||||
#include "Assertions.h"
|
#include "Assertions.h"
|
||||||
#include "IRQHandler.h"
|
|
||||||
#include "PIC.h"
|
#include "PIC.h"
|
||||||
#include "Process.h"
|
#include "Process.h"
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <Kernel/Arch/i386/CPU.h>
|
#include <Kernel/Arch/i386/CPU.h>
|
||||||
#include <Kernel/KSyms.h>
|
#include <Kernel/KSyms.h>
|
||||||
|
#include <Kernel/SharedInterruptHandler.h>
|
||||||
#include <Kernel/VM/MemoryManager.h>
|
#include <Kernel/VM/MemoryManager.h>
|
||||||
#include <LibC/mallocdefs.h>
|
#include <LibC/mallocdefs.h>
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ static DescriptorTablePointer s_gdtr;
|
||||||
static Descriptor s_idt[256];
|
static Descriptor s_idt[256];
|
||||||
static Descriptor s_gdt[256];
|
static Descriptor s_gdt[256];
|
||||||
|
|
||||||
static IRQHandler* s_irq_handler[16];
|
static SharedInterruptHandler* s_irq_handler[256];
|
||||||
|
|
||||||
static Vector<u16>* s_gdt_freelist;
|
static Vector<u16>* s_gdt_freelist;
|
||||||
|
|
||||||
|
@ -435,18 +435,25 @@ static void unimp_trap()
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_irq_handler(u8 irq, IRQHandler& handler)
|
void register_shared_interrupt_handler(u8 irq, SharedInterruptHandler& handler)
|
||||||
{
|
{
|
||||||
ASSERT(!s_irq_handler[irq]);
|
ASSERT(!s_irq_handler[irq]);
|
||||||
s_irq_handler[irq] = &handler;
|
s_irq_handler[irq] = &handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregister_irq_handler(u8 irq, IRQHandler& handler)
|
void unregister_shared_interrupt_handler(u8 irq, SharedInterruptHandler& handler)
|
||||||
{
|
{
|
||||||
ASSERT(s_irq_handler[irq] == &handler);
|
ASSERT(s_irq_handler[irq] == &handler);
|
||||||
s_irq_handler[irq] = nullptr;
|
s_irq_handler[irq] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SharedInterruptHandler& get_interrupt_handler(u8 number)
|
||||||
|
{
|
||||||
|
ASSERT(number < 256);
|
||||||
|
ASSERT(s_irq_handler[number] != nullptr);
|
||||||
|
return *s_irq_handler[number];
|
||||||
|
}
|
||||||
|
|
||||||
void register_interrupt_handler(u8 index, void (*f)())
|
void register_interrupt_handler(u8 index, void (*f)())
|
||||||
{
|
{
|
||||||
s_idt[index].low = 0x00080000 | LSW((f));
|
s_idt[index].low = 0x00080000 | LSW((f));
|
||||||
|
@ -524,8 +531,8 @@ void idt_init()
|
||||||
register_interrupt_handler(0x5e, irq_14_asm_entry);
|
register_interrupt_handler(0x5e, irq_14_asm_entry);
|
||||||
register_interrupt_handler(0x5f, irq_15_asm_entry);
|
register_interrupt_handler(0x5f, irq_15_asm_entry);
|
||||||
|
|
||||||
for (u8 i = 0; i < 16; ++i) {
|
for (u8 i = 0; i < 255; ++i) {
|
||||||
s_irq_handler[i] = nullptr;
|
SharedInterruptHandler::initialize(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_idt();
|
flush_idt();
|
||||||
|
@ -541,8 +548,9 @@ void handle_irq(RegisterDump regs)
|
||||||
clac();
|
clac();
|
||||||
ASSERT(regs.isr_number >= 0x50 && regs.isr_number <= 0x5f);
|
ASSERT(regs.isr_number >= 0x50 && regs.isr_number <= 0x5f);
|
||||||
u8 irq = (u8)(regs.isr_number - 0x50);
|
u8 irq = (u8)(regs.isr_number - 0x50);
|
||||||
if (s_irq_handler[irq])
|
ASSERT(s_irq_handler[irq] != nullptr);
|
||||||
s_irq_handler[irq]->handle_irq();
|
s_irq_handler[irq]->handle_interrupt();
|
||||||
|
// FIXME: Determine if we use IRQs or MSIs (in the future) to send EOI...
|
||||||
PIC::eoi(irq);
|
PIC::eoi(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,7 +240,7 @@ public:
|
||||||
u64 raw[4];
|
u64 raw[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
class IRQHandler;
|
class SharedInterruptHandler;
|
||||||
struct RegisterDump;
|
struct RegisterDump;
|
||||||
|
|
||||||
void gdt_init();
|
void gdt_init();
|
||||||
|
@ -248,8 +248,9 @@ void idt_init();
|
||||||
void sse_init();
|
void sse_init();
|
||||||
void register_interrupt_handler(u8 number, void (*f)());
|
void register_interrupt_handler(u8 number, void (*f)());
|
||||||
void register_user_callable_interrupt_handler(u8 number, void (*f)());
|
void register_user_callable_interrupt_handler(u8 number, void (*f)());
|
||||||
void register_irq_handler(u8 number, IRQHandler&);
|
void register_shared_interrupt_handler(u8 number, SharedInterruptHandler&);
|
||||||
void unregister_irq_handler(u8 number, IRQHandler&);
|
SharedInterruptHandler& get_interrupt_handler(u8 number);
|
||||||
|
void unregister_shared_interrupt_handler(u8 number, SharedInterruptHandler&);
|
||||||
void flush_idt();
|
void flush_idt();
|
||||||
void flush_gdt();
|
void flush_gdt();
|
||||||
void load_task_register(u16 selector);
|
void load_task_register(u16 selector);
|
||||||
|
|
|
@ -75,6 +75,20 @@ void enable(u8 irq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_enabled(u8 irq)
|
||||||
|
{
|
||||||
|
InterruptDisabler disabler;
|
||||||
|
u8 imr;
|
||||||
|
if (irq & 8) {
|
||||||
|
imr = IO::in8(PIC1_CMD);
|
||||||
|
imr &= (1 << (irq - 8));
|
||||||
|
} else {
|
||||||
|
imr = IO::in8(PIC0_CMD);
|
||||||
|
imr &= (1 << irq);
|
||||||
|
}
|
||||||
|
return (!!imr);
|
||||||
|
}
|
||||||
|
|
||||||
void eoi(u8 irq)
|
void eoi(u8 irq)
|
||||||
{
|
{
|
||||||
if (irq & 8)
|
if (irq & 8)
|
||||||
|
|
|
@ -34,6 +34,7 @@ void enable(u8 number);
|
||||||
void disable(u8 number);
|
void disable(u8 number);
|
||||||
void eoi(u8 number);
|
void eoi(u8 number);
|
||||||
void initialize();
|
void initialize();
|
||||||
|
bool is_enabled(u8 number);
|
||||||
u16 get_isr();
|
u16 get_isr();
|
||||||
u16 get_irr();
|
u16 get_irr();
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,9 @@ public:
|
||||||
|
|
||||||
size_t block_size() const { return m_block_size; }
|
size_t block_size() const { return m_block_size; }
|
||||||
virtual bool is_seekable() const override { return true; }
|
virtual bool is_seekable() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BlockDevice(unsigned major, unsigned minor, size_t block_size = PAGE_SIZE)
|
BlockDevice(unsigned major, unsigned minor, size_t block_size = PAGE_SIZE)
|
||||||
: Device(major, minor)
|
: Device(major, minor, (u8)DEVICE_TYPE::BLOCK_DEVICE)
|
||||||
, m_block_size(block_size)
|
, m_block_size(block_size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CharacterDevice(unsigned major, unsigned minor)
|
CharacterDevice(unsigned major, unsigned minor)
|
||||||
: Device(major, minor)
|
: Device(major, minor, (u8)DEVICE_TYPE::CHAR_DEVICE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,48 +25,32 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <Kernel/Devices/Device.h>
|
#include <Kernel/Devices/Device.h>
|
||||||
#include <Kernel/FileSystem/InodeMetadata.h>
|
#include <Kernel/Devices/HardwareEventsManager.h>
|
||||||
#include <LibC/errno_numbers.h>
|
#include <LibC/errno_numbers.h>
|
||||||
|
|
||||||
static HashMap<u32, Device*>* s_all_devices;
|
|
||||||
|
|
||||||
HashMap<u32, Device*>& Device::all_devices()
|
|
||||||
{
|
|
||||||
if (s_all_devices == nullptr)
|
|
||||||
s_all_devices = new HashMap<u32, Device*>;
|
|
||||||
return *s_all_devices;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::for_each(Function<void(Device&)> callback)
|
void Device::for_each(Function<void(Device&)> callback)
|
||||||
{
|
{
|
||||||
for (auto& entry : all_devices())
|
for (auto* entry : HardwareEventsManager::the().get_devices_list()) {
|
||||||
callback(*entry.value);
|
ASSERT(entry != nullptr);
|
||||||
|
callback(*entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Device* Device::get_device(unsigned major, unsigned minor)
|
Device* Device::get_device(unsigned major, unsigned minor)
|
||||||
{
|
{
|
||||||
auto it = all_devices().find(encoded_device(major, minor));
|
return HardwareEventsManager::the().get_device(major, minor);
|
||||||
if (it == all_devices().end())
|
|
||||||
return nullptr;
|
|
||||||
return it->value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(unsigned major, unsigned minor)
|
Device::Device(unsigned major, unsigned minor, u8 device_type)
|
||||||
: m_major(major)
|
: m_major(major)
|
||||||
, m_minor(minor)
|
, m_minor(minor)
|
||||||
{
|
{
|
||||||
u32 device_id = encoded_device(major, minor);
|
HardwareEventsManager::the().register_device(*this, device_type);
|
||||||
auto it = all_devices().find(device_id);
|
|
||||||
if (it != all_devices().end()) {
|
|
||||||
dbg() << "Already registered " << major << "," << minor << ": " << it->value->class_name();
|
|
||||||
}
|
|
||||||
ASSERT(!all_devices().contains(device_id));
|
|
||||||
all_devices().set(device_id, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device()
|
Device::~Device()
|
||||||
{
|
{
|
||||||
all_devices().remove(encoded_device(m_major, m_minor));
|
HardwareEventsManager::the().unregister_device(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
String Device::absolute_path() const
|
String Device::absolute_path() const
|
||||||
|
|
|
@ -39,6 +39,11 @@
|
||||||
#include <Kernel/FileSystem/File.h>
|
#include <Kernel/FileSystem/File.h>
|
||||||
#include <Kernel/UnixTypes.h>
|
#include <Kernel/UnixTypes.h>
|
||||||
|
|
||||||
|
enum class DEVICE_TYPE {
|
||||||
|
BLOCK_DEVICE = 1,
|
||||||
|
CHAR_DEVICE = 2
|
||||||
|
};
|
||||||
|
|
||||||
class Device : public File {
|
class Device : public File {
|
||||||
public:
|
public:
|
||||||
virtual ~Device() override;
|
virtual ~Device() override;
|
||||||
|
@ -55,16 +60,17 @@ public:
|
||||||
virtual bool is_device() const override { return true; }
|
virtual bool is_device() const override { return true; }
|
||||||
virtual bool is_disk_device() const { return false; }
|
virtual bool is_disk_device() const { return false; }
|
||||||
|
|
||||||
|
virtual bool is_block_device() const override { return false; }
|
||||||
|
virtual bool is_character_device() const override { return true; }
|
||||||
|
|
||||||
static void for_each(Function<void(Device&)>);
|
static void for_each(Function<void(Device&)>);
|
||||||
static Device* get_device(unsigned major, unsigned minor);
|
static Device* get_device(unsigned major, unsigned minor);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Device(unsigned major, unsigned minor);
|
Device(unsigned major, unsigned minor, u8 device_type);
|
||||||
void set_uid(uid_t uid) { m_uid = uid; }
|
void set_uid(uid_t uid) { m_uid = uid; }
|
||||||
void set_gid(gid_t gid) { m_gid = gid; }
|
void set_gid(gid_t gid) { m_gid = gid; }
|
||||||
|
|
||||||
static HashMap<u32, Device*>& all_devices();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned m_major { 0 };
|
unsigned m_major { 0 };
|
||||||
unsigned m_minor { 0 };
|
unsigned m_minor { 0 };
|
||||||
|
|
|
@ -109,7 +109,7 @@ const char* FloppyDiskDevice::class_name() const
|
||||||
}
|
}
|
||||||
|
|
||||||
FloppyDiskDevice::FloppyDiskDevice(FloppyDiskDevice::DriveType type)
|
FloppyDiskDevice::FloppyDiskDevice(FloppyDiskDevice::DriveType type)
|
||||||
: IRQHandler(IRQ_FLOPPY_DRIVE)
|
: InterruptHandler(IRQ_FLOPPY_DRIVE)
|
||||||
, DiskDevice(89, (type == FloppyDiskDevice::DriveType::Master) ? 0 : 1, BYTES_PER_SECTOR)
|
, DiskDevice(89, (type == FloppyDiskDevice::DriveType::Master) ? 0 : 1, BYTES_PER_SECTOR)
|
||||||
, m_io_base_addr((type == FloppyDiskDevice::DriveType::Master) ? 0x3F0 : 0x370)
|
, m_io_base_addr((type == FloppyDiskDevice::DriveType::Master) ? 0x3F0 : 0x370)
|
||||||
{
|
{
|
||||||
|
@ -167,7 +167,7 @@ bool FloppyDiskDevice::read_sectors_with_dma(u16 lba, u16 count, u8* outbuf)
|
||||||
//while(start < PIT::seconds_since_boot() + 1)
|
//while(start < PIT::seconds_since_boot() + 1)
|
||||||
// ;
|
// ;
|
||||||
|
|
||||||
disable_irq();
|
disable_interrupts();
|
||||||
|
|
||||||
IO::out8(0xA, FLOPPY_DMA_CHANNEL | 0x4); // Channel 2 SEL, MASK_ON = 1
|
IO::out8(0xA, FLOPPY_DMA_CHANNEL | 0x4); // Channel 2 SEL, MASK_ON = 1
|
||||||
IO::out8(0x0B, 0x56); // Begin DMA, Single Transfer, Increment, Auto, FDC -> RAM, Channel 2
|
IO::out8(0x0B, 0x56); // Begin DMA, Single Transfer, Increment, Auto, FDC -> RAM, Channel 2
|
||||||
|
@ -195,7 +195,7 @@ bool FloppyDiskDevice::read_sectors_with_dma(u16 lba, u16 count, u8* outbuf)
|
||||||
send_byte(0x1b); // GPL3 value. The Datasheet doesn't really specify the values for this properly...
|
send_byte(0x1b); // GPL3 value. The Datasheet doesn't really specify the values for this properly...
|
||||||
send_byte(0xff);
|
send_byte(0xff);
|
||||||
|
|
||||||
enable_irq();
|
enable_interrupts();
|
||||||
|
|
||||||
wait_for_irq(); // TODO: See if there was a lockup here via some "timeout counter"
|
wait_for_irq(); // TODO: See if there was a lockup here via some "timeout counter"
|
||||||
m_interrupted = false;
|
m_interrupted = false;
|
||||||
|
@ -269,7 +269,7 @@ bool FloppyDiskDevice::write_sectors_with_dma(u16 lba, u16 count, const u8* inbu
|
||||||
//while(start < PIT::seconds_since_boot() + 1)
|
//while(start < PIT::seconds_since_boot() + 1)
|
||||||
// ;
|
// ;
|
||||||
|
|
||||||
disable_irq();
|
disable_interrupts();
|
||||||
|
|
||||||
IO::out8(0xA, FLOPPY_DMA_CHANNEL | 0x4); // Channel 2 SEL, MASK_ON = 1
|
IO::out8(0xA, FLOPPY_DMA_CHANNEL | 0x4); // Channel 2 SEL, MASK_ON = 1
|
||||||
IO::out8(0x0B, 0x5A); // Begin DMA, Single Transfer, Increment, Auto, RAM -> FDC, Channel 2
|
IO::out8(0x0B, 0x5A); // Begin DMA, Single Transfer, Increment, Auto, RAM -> FDC, Channel 2
|
||||||
|
@ -295,7 +295,7 @@ bool FloppyDiskDevice::write_sectors_with_dma(u16 lba, u16 count, const u8* inbu
|
||||||
send_byte(0x1b); // GPL3 value. The Datasheet doesn't really specify the values for this properly...
|
send_byte(0x1b); // GPL3 value. The Datasheet doesn't really specify the values for this properly...
|
||||||
send_byte(0xff);
|
send_byte(0xff);
|
||||||
|
|
||||||
enable_irq();
|
enable_interrupts();
|
||||||
|
|
||||||
wait_for_irq(); // TODO: See if there was a lockup here via some "timeout counter"
|
wait_for_irq(); // TODO: See if there was a lockup here via some "timeout counter"
|
||||||
m_interrupted = false;
|
m_interrupted = false;
|
||||||
|
@ -358,7 +358,7 @@ bool FloppyDiskDevice::wait_for_irq()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloppyDiskDevice::handle_irq()
|
void FloppyDiskDevice::handle_interrupt()
|
||||||
{
|
{
|
||||||
// The only thing we need to do is acknowledge the IRQ happened
|
// The only thing we need to do is acknowledge the IRQ happened
|
||||||
m_interrupted = true;
|
m_interrupted = true;
|
||||||
|
@ -512,7 +512,7 @@ void FloppyDiskDevice::initialize()
|
||||||
kprintf("fdc: m_io_base = 0x%x IRQn = %d\n", m_io_base_addr, IRQ_FLOPPY_DRIVE);
|
kprintf("fdc: m_io_base = 0x%x IRQn = %d\n", m_io_base_addr, IRQ_FLOPPY_DRIVE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enable_irq();
|
enable_interrupts();
|
||||||
|
|
||||||
// Get the version of the Floppy Disk Controller
|
// Get the version of the Floppy Disk Controller
|
||||||
send_byte(FloppyCommand::Version);
|
send_byte(FloppyCommand::Version);
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
|
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <Kernel/Devices/DiskDevice.h>
|
#include <Kernel/Devices/DiskDevice.h>
|
||||||
#include <Kernel/IRQHandler.h>
|
#include <Kernel/InterruptHandler.h>
|
||||||
#include <Kernel/Lock.h>
|
#include <Kernel/Lock.h>
|
||||||
#include <Kernel/VM/PhysicalAddress.h>
|
#include <Kernel/VM/PhysicalAddress.h>
|
||||||
#include <Kernel/VM/PhysicalPage.h>
|
#include <Kernel/VM/PhysicalPage.h>
|
||||||
|
@ -122,7 +122,7 @@ struct FloppyControllerCommand {
|
||||||
// uses the Intel 82077A controller. More about this controller can
|
// uses the Intel 82077A controller. More about this controller can
|
||||||
// be found here: http://www.buchty.net/casio/files/82077.pdf
|
// be found here: http://www.buchty.net/casio/files/82077.pdf
|
||||||
//
|
//
|
||||||
class FloppyDiskDevice final : public IRQHandler
|
class FloppyDiskDevice final : public InterruptHandler
|
||||||
, public DiskDevice {
|
, public DiskDevice {
|
||||||
AK_MAKE_ETERNAL
|
AK_MAKE_ETERNAL
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ^IRQHandler
|
// ^IRQHandler
|
||||||
void handle_irq();
|
void handle_interrupt();
|
||||||
|
|
||||||
// ^DiskDevice
|
// ^DiskDevice
|
||||||
virtual const char* class_name() const override;
|
virtual const char* class_name() const override;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -24,27 +24,42 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "IRQHandler.h"
|
#include <Kernel/Devices/HardwareEventsManager.h>
|
||||||
#include <Kernel/Arch/i386/CPU.h>
|
|
||||||
#include <Kernel/Arch/i386/PIC.h>
|
|
||||||
|
|
||||||
IRQHandler::IRQHandler(u8 irq)
|
static HardwareEventsManager* s_hardware_events_manager;
|
||||||
: m_irq_number(irq)
|
|
||||||
|
HardwareEventsManager& HardwareEventsManager::the()
|
||||||
{
|
{
|
||||||
register_irq_handler(m_irq_number, *this);
|
if (s_hardware_events_manager == nullptr) {
|
||||||
|
s_hardware_events_manager = new HardwareEventsManager();
|
||||||
|
}
|
||||||
|
return *s_hardware_events_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
IRQHandler::~IRQHandler()
|
HashTable<Device*>& HardwareEventsManager::get_devices_list()
|
||||||
{
|
{
|
||||||
unregister_irq_handler(m_irq_number, *this);
|
return m_devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRQHandler::enable_irq()
|
void HardwareEventsManager::unregister_device(Device& device)
|
||||||
{
|
{
|
||||||
PIC::enable(m_irq_number);
|
get_devices_list().remove(&device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRQHandler::disable_irq()
|
HardwareEventsManager::HardwareEventsManager()
|
||||||
{
|
{
|
||||||
PIC::disable(m_irq_number);
|
}
|
||||||
|
|
||||||
|
Device* HardwareEventsManager::get_device(unsigned major, unsigned minor)
|
||||||
|
{
|
||||||
|
for (auto* entry : HardwareEventsManager::get_devices_list()) {
|
||||||
|
ASSERT(entry != nullptr);
|
||||||
|
if (entry->major() == major && entry->minor() == minor)
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
void HardwareEventsManager::register_device(Device& device, u8)
|
||||||
|
{
|
||||||
|
get_devices_list().set(&device);
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -27,20 +27,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
#include <Kernel/Devices/Device.h>
|
||||||
|
|
||||||
class IRQHandler {
|
class HardwareEventsManager {
|
||||||
public:
|
public:
|
||||||
virtual ~IRQHandler();
|
static HardwareEventsManager& the();
|
||||||
virtual void handle_irq() = 0;
|
void register_device(Device&, u8);
|
||||||
|
void unregister_device(Device&);
|
||||||
u8 irq_number() const { return m_irq_number; }
|
void register_device_event();
|
||||||
|
Device* get_device(unsigned, unsigned);
|
||||||
void enable_irq();
|
HashTable<Device*>& get_devices_list();
|
||||||
void disable_irq();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit IRQHandler(u8 irq);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u8 m_irq_number { 0 };
|
HashTable<Device*> m_devices;
|
||||||
|
HardwareEventsManager();
|
||||||
};
|
};
|
|
@ -483,7 +483,7 @@ void KeyboardDevice::key_state_changed(u8 raw, bool pressed)
|
||||||
m_has_e0_prefix = false;
|
m_has_e0_prefix = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardDevice::handle_irq()
|
void KeyboardDevice::handle_interrupt()
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
u8 status = IO::in8(I8042_STATUS);
|
u8 status = IO::in8(I8042_STATUS);
|
||||||
|
@ -551,7 +551,7 @@ KeyboardDevice& KeyboardDevice::the()
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboardDevice::KeyboardDevice()
|
KeyboardDevice::KeyboardDevice()
|
||||||
: IRQHandler(IRQ_KEYBOARD)
|
: InterruptHandler(IRQ_KEYBOARD)
|
||||||
, CharacterDevice(85, 1)
|
, CharacterDevice(85, 1)
|
||||||
{
|
{
|
||||||
s_the = this;
|
s_the = this;
|
||||||
|
@ -563,7 +563,7 @@ KeyboardDevice::KeyboardDevice()
|
||||||
while (IO::in8(I8042_STATUS) & I8042_BUFFER_FULL)
|
while (IO::in8(I8042_STATUS) & I8042_BUFFER_FULL)
|
||||||
IO::in8(I8042_BUFFER);
|
IO::in8(I8042_BUFFER);
|
||||||
|
|
||||||
enable_irq();
|
enable_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboardDevice::~KeyboardDevice()
|
KeyboardDevice::~KeyboardDevice()
|
||||||
|
|
|
@ -26,16 +26,16 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "IRQHandler.h"
|
|
||||||
#include "KeyCode.h"
|
#include "KeyCode.h"
|
||||||
#include <AK/CircularQueue.h>
|
#include <AK/CircularQueue.h>
|
||||||
#include <AK/DoublyLinkedList.h>
|
#include <AK/DoublyLinkedList.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <Kernel/Devices/CharacterDevice.h>
|
#include <Kernel/Devices/CharacterDevice.h>
|
||||||
|
#include <Kernel/InterruptHandler.h>
|
||||||
|
|
||||||
class KeyboardClient;
|
class KeyboardClient;
|
||||||
|
|
||||||
class KeyboardDevice final : public IRQHandler
|
class KeyboardDevice final : public InterruptHandler
|
||||||
, public CharacterDevice {
|
, public CharacterDevice {
|
||||||
AK_MAKE_ETERNAL
|
AK_MAKE_ETERNAL
|
||||||
public:
|
public:
|
||||||
|
@ -57,7 +57,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ^IRQHandler
|
// ^IRQHandler
|
||||||
virtual void handle_irq() override;
|
virtual void handle_interrupt() override;
|
||||||
|
|
||||||
// ^CharacterDevice
|
// ^CharacterDevice
|
||||||
virtual const char* class_name() const override { return "KeyboardDevice"; }
|
virtual const char* class_name() const override { return "KeyboardDevice"; }
|
||||||
|
|
|
@ -112,18 +112,25 @@ static Lock& s_lock()
|
||||||
return *lock;
|
return *lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
OwnPtr<PATAChannel> PATAChannel::create(ChannelType type, bool force_pio)
|
OwnPtr<PATAChannel> PATAChannel::autodetect(ChannelType type, bool force_pio)
|
||||||
{
|
{
|
||||||
return make<PATAChannel>(type, force_pio);
|
PCI::Address found_address;
|
||||||
|
PCI::enumerate_all([&](const PCI::Address& address, PCI::ID id) {
|
||||||
|
if (PCI::get_class(address) == PCI_Mass_Storage_Class && PCI::get_subclass(address) == PCI_IDE_Controller_Subclass) {
|
||||||
|
found_address = address;
|
||||||
|
kprintf("PATAChannel: PATA Controller found! id=%w:%w\n", id.vendor_id, id.device_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return make<PATAChannel>(found_address, type, force_pio);
|
||||||
}
|
}
|
||||||
|
|
||||||
PATAChannel::PATAChannel(ChannelType type, bool force_pio)
|
PATAChannel::PATAChannel(PCI::Address pci_address, ChannelType type, bool force_pio)
|
||||||
: IRQHandler((type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ))
|
: PCI::Device(pci_address, (type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ))
|
||||||
, m_channel_number((type == ChannelType::Primary ? 0 : 1))
|
, m_channel_number((type == ChannelType::Primary ? 0 : 1))
|
||||||
, m_io_base((type == ChannelType::Primary ? 0x1F0 : 0x170))
|
, m_io_base((type == ChannelType::Primary ? 0x1F0 : 0x170))
|
||||||
, m_control_base((type == ChannelType::Primary ? 0x3f6 : 0x376))
|
, m_control_base((type == ChannelType::Primary ? 0x3f6 : 0x376))
|
||||||
{
|
{
|
||||||
disable_irq();
|
disable_interrupts();
|
||||||
|
|
||||||
m_dma_enabled.resource() = true;
|
m_dma_enabled.resource() = true;
|
||||||
ProcFS::add_sys_bool("ide_dma", m_dma_enabled);
|
ProcFS::add_sys_bool("ide_dma", m_dma_enabled);
|
||||||
|
@ -140,14 +147,8 @@ PATAChannel::~PATAChannel()
|
||||||
|
|
||||||
void PATAChannel::initialize(bool force_pio)
|
void PATAChannel::initialize(bool force_pio)
|
||||||
{
|
{
|
||||||
PCI::enumerate_all([this](const PCI::Address& address, PCI::ID id) {
|
|
||||||
if (PCI::get_class(address) == PCI_Mass_Storage_Class && PCI::get_subclass(address) == PCI_IDE_Controller_Subclass) {
|
|
||||||
m_pci_address = address;
|
|
||||||
kprintf("PATAChannel: PATA Controller found! id=%w:%w\n", id.vendor_id, id.device_id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (m_pci_address.is_null()) {
|
if (get_pci_address().is_null()) {
|
||||||
kprintf("PATAChannel: PCI address was null; can not set up DMA\n");
|
kprintf("PATAChannel: PCI address was null; can not set up DMA\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -158,9 +159,9 @@ void PATAChannel::initialize(bool force_pio)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's try to set up DMA transfers.
|
// Let's try to set up DMA transfers.
|
||||||
PCI::enable_bus_mastering(m_pci_address);
|
PCI::enable_bus_mastering(get_pci_address());
|
||||||
prdt().end_of_table = 0x8000;
|
prdt().end_of_table = 0x8000;
|
||||||
m_bus_master_base = PCI::get_BAR4(m_pci_address) & 0xfffc;
|
m_bus_master_base = PCI::get_BAR4(get_pci_address()) & 0xfffc;
|
||||||
m_dma_buffer_page = MM.allocate_supervisor_physical_page();
|
m_dma_buffer_page = MM.allocate_supervisor_physical_page();
|
||||||
kprintf("PATAChannel: Bus master IDE: I/O @ %x\n", m_bus_master_base);
|
kprintf("PATAChannel: Bus master IDE: I/O @ %x\n", m_bus_master_base);
|
||||||
}
|
}
|
||||||
|
@ -181,12 +182,11 @@ static void print_ide_status(u8 status)
|
||||||
void PATAChannel::wait_for_irq()
|
void PATAChannel::wait_for_irq()
|
||||||
{
|
{
|
||||||
cli();
|
cli();
|
||||||
enable_irq();
|
InterruptHandler::Enabler enabler(*this);
|
||||||
current->wait_on(m_irq_queue);
|
current->wait_on(m_irq_queue);
|
||||||
disable_irq();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PATAChannel::handle_irq()
|
void PATAChannel::handle_interrupt()
|
||||||
{
|
{
|
||||||
u8 status = IO::in8(m_io_base + ATA_REG_STATUS);
|
u8 status = IO::in8(m_io_base + ATA_REG_STATUS);
|
||||||
if (status & ATA_SR_ERR) {
|
if (status & ATA_SR_ERR) {
|
||||||
|
|
|
@ -38,9 +38,10 @@
|
||||||
|
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <Kernel/IRQHandler.h>
|
#include <Kernel/InterruptHandler.h>
|
||||||
#include <Kernel/Lock.h>
|
#include <Kernel/Lock.h>
|
||||||
#include <Kernel/PCI/Access.h>
|
#include <Kernel/PCI/Access.h>
|
||||||
|
#include <Kernel/PCI/Device.h>
|
||||||
#include <Kernel/VM/PhysicalAddress.h>
|
#include <Kernel/VM/PhysicalAddress.h>
|
||||||
#include <Kernel/VM/PhysicalPage.h>
|
#include <Kernel/VM/PhysicalPage.h>
|
||||||
#include <Kernel/WaitQueue.h>
|
#include <Kernel/WaitQueue.h>
|
||||||
|
@ -52,7 +53,7 @@ struct PhysicalRegionDescriptor {
|
||||||
};
|
};
|
||||||
|
|
||||||
class PATADiskDevice;
|
class PATADiskDevice;
|
||||||
class PATAChannel final : public IRQHandler {
|
class PATAChannel final : public PCI::Device {
|
||||||
friend class PATADiskDevice;
|
friend class PATADiskDevice;
|
||||||
AK_MAKE_ETERNAL
|
AK_MAKE_ETERNAL
|
||||||
public:
|
public:
|
||||||
|
@ -62,8 +63,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static OwnPtr<PATAChannel> create(ChannelType type, bool force_pio);
|
static OwnPtr<PATAChannel> autodetect(ChannelType type, bool force_pio);
|
||||||
PATAChannel(ChannelType type, bool force_pio);
|
PATAChannel(PCI::Address pci_address, ChannelType type, bool force_pio);
|
||||||
virtual ~PATAChannel() override;
|
virtual ~PATAChannel() override;
|
||||||
|
|
||||||
RefPtr<PATADiskDevice> master_device() { return m_master; };
|
RefPtr<PATADiskDevice> master_device() { return m_master; };
|
||||||
|
@ -71,7 +72,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//^ IRQHandler
|
//^ IRQHandler
|
||||||
virtual void handle_irq() override;
|
virtual void handle_interrupt() override;
|
||||||
|
|
||||||
void initialize(bool force_pio);
|
void initialize(bool force_pio);
|
||||||
void detect_disks();
|
void detect_disks();
|
||||||
|
@ -90,7 +91,6 @@ private:
|
||||||
|
|
||||||
WaitQueue m_irq_queue;
|
WaitQueue m_irq_queue;
|
||||||
|
|
||||||
PCI::Address m_pci_address;
|
|
||||||
PhysicalRegionDescriptor& prdt() { return *reinterpret_cast<PhysicalRegionDescriptor*>(m_prdt_page->paddr().offset(0xc0000000).as_ptr()); }
|
PhysicalRegionDescriptor& prdt() { return *reinterpret_cast<PhysicalRegionDescriptor*>(m_prdt_page->paddr().offset(0xc0000000).as_ptr()); }
|
||||||
RefPtr<PhysicalPage> m_prdt_page;
|
RefPtr<PhysicalPage> m_prdt_page;
|
||||||
RefPtr<PhysicalPage> m_dma_buffer_page;
|
RefPtr<PhysicalPage> m_dma_buffer_page;
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Kernel/Devices/DiskDevice.h>
|
#include <Kernel/Devices/DiskDevice.h>
|
||||||
#include <Kernel/IRQHandler.h>
|
#include <Kernel/InterruptHandler.h>
|
||||||
#include <Kernel/Lock.h>
|
#include <Kernel/Lock.h>
|
||||||
|
|
||||||
class PATAChannel;
|
class PATAChannel;
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
static PS2MouseDevice* s_the;
|
static PS2MouseDevice* s_the;
|
||||||
|
|
||||||
PS2MouseDevice::PS2MouseDevice()
|
PS2MouseDevice::PS2MouseDevice()
|
||||||
: IRQHandler(IRQ_MOUSE)
|
: InterruptHandler(IRQ_MOUSE)
|
||||||
, CharacterDevice(10, 1)
|
, CharacterDevice(10, 1)
|
||||||
{
|
{
|
||||||
s_the = this;
|
s_the = this;
|
||||||
|
@ -70,7 +70,7 @@ PS2MouseDevice& PS2MouseDevice::the()
|
||||||
return *s_the;
|
return *s_the;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS2MouseDevice::handle_irq()
|
void PS2MouseDevice::handle_interrupt()
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
u8 status = IO::in8(I8042_STATUS);
|
u8 status = IO::in8(I8042_STATUS);
|
||||||
|
@ -242,7 +242,7 @@ void PS2MouseDevice::initialize_device()
|
||||||
kprintf("PS2MouseDevice: No mouse wheel detected!\n");
|
kprintf("PS2MouseDevice: No mouse wheel detected!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
enable_irq();
|
enable_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS2MouseDevice::expect_ack()
|
void PS2MouseDevice::expect_ack()
|
||||||
|
|
|
@ -28,10 +28,10 @@
|
||||||
|
|
||||||
#include <AK/CircularQueue.h>
|
#include <AK/CircularQueue.h>
|
||||||
#include <Kernel/Devices/CharacterDevice.h>
|
#include <Kernel/Devices/CharacterDevice.h>
|
||||||
#include <Kernel/IRQHandler.h>
|
#include <Kernel/InterruptHandler.h>
|
||||||
#include <Kernel/MousePacket.h>
|
#include <Kernel/MousePacket.h>
|
||||||
|
|
||||||
class PS2MouseDevice final : public IRQHandler
|
class PS2MouseDevice final : public InterruptHandler
|
||||||
, public CharacterDevice {
|
, public CharacterDevice {
|
||||||
public:
|
public:
|
||||||
PS2MouseDevice();
|
PS2MouseDevice();
|
||||||
|
@ -47,7 +47,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ^IRQHandler
|
// ^IRQHandler
|
||||||
virtual void handle_irq() override;
|
virtual void handle_interrupt() override;
|
||||||
|
|
||||||
// ^CharacterDevice
|
// ^CharacterDevice
|
||||||
virtual const char* class_name() const override { return "PS2MouseDevice"; }
|
virtual const char* class_name() const override { return "PS2MouseDevice"; }
|
||||||
|
|
|
@ -74,7 +74,7 @@ void SB16::set_sample_rate(uint16_t hz)
|
||||||
static SB16* s_the;
|
static SB16* s_the;
|
||||||
|
|
||||||
SB16::SB16()
|
SB16::SB16()
|
||||||
: IRQHandler(5)
|
: InterruptHandler(5)
|
||||||
, CharacterDevice(42, 42) // ### ?
|
, CharacterDevice(42, 42) // ### ?
|
||||||
{
|
{
|
||||||
s_the = this;
|
s_the = this;
|
||||||
|
@ -92,7 +92,7 @@ SB16& SB16::the()
|
||||||
|
|
||||||
void SB16::initialize()
|
void SB16::initialize()
|
||||||
{
|
{
|
||||||
disable_irq();
|
disable_interrupts();
|
||||||
|
|
||||||
IO::out8(0x226, 1);
|
IO::out8(0x226, 1);
|
||||||
IO::delay();
|
IO::delay();
|
||||||
|
@ -153,7 +153,7 @@ void SB16::dma_start(uint32_t length)
|
||||||
IO::out8(0xd4, (channel % 4));
|
IO::out8(0xd4, (channel % 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SB16::handle_irq()
|
void SB16::handle_interrupt()
|
||||||
{
|
{
|
||||||
// Stop sound output ready for the next block.
|
// Stop sound output ready for the next block.
|
||||||
dsp_write(0xd5);
|
dsp_write(0xd5);
|
||||||
|
@ -168,9 +168,8 @@ void SB16::handle_irq()
|
||||||
void SB16::wait_for_irq()
|
void SB16::wait_for_irq()
|
||||||
{
|
{
|
||||||
cli();
|
cli();
|
||||||
enable_irq();
|
InterruptHandler::Enabler enabler(*this);
|
||||||
current->wait_on(m_irq_queue);
|
current->wait_on(m_irq_queue);
|
||||||
disable_irq();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t SB16::write(FileDescription&, const u8* data, ssize_t length)
|
ssize_t SB16::write(FileDescription&, const u8* data, ssize_t length)
|
||||||
|
|
|
@ -28,14 +28,14 @@
|
||||||
|
|
||||||
#include <AK/CircularQueue.h>
|
#include <AK/CircularQueue.h>
|
||||||
#include <Kernel/Devices/CharacterDevice.h>
|
#include <Kernel/Devices/CharacterDevice.h>
|
||||||
#include <Kernel/IRQHandler.h>
|
#include <Kernel/InterruptHandler.h>
|
||||||
#include <Kernel/VM/PhysicalAddress.h>
|
#include <Kernel/VM/PhysicalAddress.h>
|
||||||
#include <Kernel/VM/PhysicalPage.h>
|
#include <Kernel/VM/PhysicalPage.h>
|
||||||
#include <Kernel/WaitQueue.h>
|
#include <Kernel/WaitQueue.h>
|
||||||
|
|
||||||
class SB16;
|
class SB16;
|
||||||
|
|
||||||
class SB16 final : public IRQHandler
|
class SB16 final : public InterruptHandler
|
||||||
, public CharacterDevice {
|
, public CharacterDevice {
|
||||||
public:
|
public:
|
||||||
SB16();
|
SB16();
|
||||||
|
@ -51,7 +51,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ^IRQHandler
|
// ^IRQHandler
|
||||||
virtual void handle_irq() override;
|
virtual void handle_interrupt() override;
|
||||||
|
|
||||||
// ^CharacterDevice
|
// ^CharacterDevice
|
||||||
virtual const char* class_name() const override { return "SB16"; }
|
virtual const char* class_name() const override { return "SB16"; }
|
||||||
|
|
|
@ -15,6 +15,7 @@ OBJS = \
|
||||||
Arch/i386/PIT.o \
|
Arch/i386/PIT.o \
|
||||||
CMOS.o \
|
CMOS.o \
|
||||||
Console.o \
|
Console.o \
|
||||||
|
Devices/HardwareEventsManager.o \
|
||||||
Devices/BXVGADevice.o \
|
Devices/BXVGADevice.o \
|
||||||
Devices/BlockDevice.o \
|
Devices/BlockDevice.o \
|
||||||
Devices/CharacterDevice.o \
|
Devices/CharacterDevice.o \
|
||||||
|
@ -54,7 +55,8 @@ OBJS = \
|
||||||
FileSystem/VirtualFileSystem.o \
|
FileSystem/VirtualFileSystem.o \
|
||||||
Heap/SlabAllocator.o \
|
Heap/SlabAllocator.o \
|
||||||
Heap/kmalloc.o \
|
Heap/kmalloc.o \
|
||||||
IRQHandler.o \
|
InterruptHandler.o \
|
||||||
|
SharedInterruptHandler.o \
|
||||||
KBufferBuilder.o \
|
KBufferBuilder.o \
|
||||||
KParams.o \
|
KParams.o \
|
||||||
KSyms.o \
|
KSyms.o \
|
||||||
|
@ -74,6 +76,7 @@ OBJS = \
|
||||||
PCI/IOAccess.o \
|
PCI/IOAccess.o \
|
||||||
PCI/MMIOAccess.o \
|
PCI/MMIOAccess.o \
|
||||||
PCI/Initializer.o \
|
PCI/Initializer.o \
|
||||||
|
PCI/Device.o \
|
||||||
Process.o \
|
Process.o \
|
||||||
ProcessTracer.o \
|
ProcessTracer.o \
|
||||||
Profiling.o \
|
Profiling.o \
|
||||||
|
|
|
@ -135,24 +135,23 @@ OwnPtr<E1000NetworkAdapter> E1000NetworkAdapter::autodetect()
|
||||||
return make<E1000NetworkAdapter>(found_address, irq);
|
return make<E1000NetworkAdapter>(found_address, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address pci_address, u8 irq)
|
E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address pci_address, u8 interrupt_vector)
|
||||||
: IRQHandler(irq)
|
: PCI::Device(pci_address, interrupt_vector)
|
||||||
, m_pci_address(pci_address)
|
|
||||||
{
|
{
|
||||||
set_interface_name("e1k");
|
set_interface_name("e1k");
|
||||||
|
|
||||||
kprintf("E1000: Found at PCI address @ %w:%b:%b.%b\n", pci_address.seg(), pci_address.bus(), pci_address.slot(), pci_address.function());
|
kprintf("E1000: Found at PCI address @ %w:%b:%b.%b\n", pci_address.seg(), pci_address.bus(), pci_address.slot(), pci_address.function());
|
||||||
|
|
||||||
enable_bus_mastering(m_pci_address);
|
enable_bus_mastering(get_pci_address());
|
||||||
|
|
||||||
size_t mmio_base_size = PCI::get_BAR_Space_Size(pci_address, 0);
|
size_t mmio_base_size = PCI::get_BAR_Space_Size(pci_address, 0);
|
||||||
m_mmio_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR0(m_pci_address))), PAGE_ROUND_UP(mmio_base_size), "E1000 MMIO", Region::Access::Read | Region::Access::Write, false, false);
|
m_mmio_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR0(get_pci_address()))), PAGE_ROUND_UP(mmio_base_size), "E1000 MMIO", Region::Access::Read | Region::Access::Write, false, false);
|
||||||
m_mmio_base = m_mmio_region->vaddr();
|
m_mmio_base = m_mmio_region->vaddr();
|
||||||
m_use_mmio = true;
|
m_use_mmio = true;
|
||||||
m_io_base = PCI::get_BAR1(m_pci_address) & ~1;
|
m_io_base = PCI::get_BAR1(get_pci_address()) & ~1;
|
||||||
m_interrupt_line = PCI::get_interrupt_line(m_pci_address);
|
m_interrupt_line = PCI::get_interrupt_line(get_pci_address());
|
||||||
kprintf("E1000: IO port base: %w\n", m_io_base);
|
kprintf("E1000: IO port base: %w\n", m_io_base);
|
||||||
kprintf("E1000: MMIO base: P%x\n", PCI::get_BAR0(pci_address) & 0xfffffffc);
|
kprintf("E1000: MMIO base: P%x\n", PCI::get_BAR0(get_pci_address()) & 0xfffffffc);
|
||||||
kprintf("E1000: MMIO base size: %u bytes\n", mmio_base_size);
|
kprintf("E1000: MMIO base size: %u bytes\n", mmio_base_size);
|
||||||
kprintf("E1000: Interrupt line: %u\n", m_interrupt_line);
|
kprintf("E1000: Interrupt line: %u\n", m_interrupt_line);
|
||||||
detect_eeprom();
|
detect_eeprom();
|
||||||
|
@ -171,14 +170,14 @@ E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address pci_address, u8 irq)
|
||||||
out32(REG_IMASK, 0xff & ~4);
|
out32(REG_IMASK, 0xff & ~4);
|
||||||
in32(0xc0);
|
in32(0xc0);
|
||||||
|
|
||||||
enable_irq();
|
enable_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
E1000NetworkAdapter::~E1000NetworkAdapter()
|
E1000NetworkAdapter::~E1000NetworkAdapter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void E1000NetworkAdapter::handle_irq()
|
void E1000NetworkAdapter::handle_interrupt()
|
||||||
{
|
{
|
||||||
out32(REG_IMASK, 0x1);
|
out32(REG_IMASK, 0x1);
|
||||||
|
|
||||||
|
@ -373,14 +372,14 @@ u32 E1000NetworkAdapter::in32(u16 address)
|
||||||
|
|
||||||
void E1000NetworkAdapter::send_raw(const u8* data, int length)
|
void E1000NetworkAdapter::send_raw(const u8* data, int length)
|
||||||
{
|
{
|
||||||
disable_irq();
|
disable_interrupts();
|
||||||
u32 tx_current = in32(REG_TXDESCTAIL);
|
u32 tx_current = in32(REG_TXDESCTAIL);
|
||||||
#ifdef E1000_DEBUG
|
#ifdef E1000_DEBUG
|
||||||
kprintf("E1000: Sending packet (%d bytes)\n", length);
|
kprintf("E1000: Sending packet (%d bytes)\n", length);
|
||||||
#endif
|
#endif
|
||||||
auto& descriptor = m_tx_descriptors[tx_current];
|
auto& descriptor = m_tx_descriptors[tx_current];
|
||||||
ASSERT(length <= 8192);
|
ASSERT(length <= 8192);
|
||||||
auto *vptr = (void*)(descriptor.addr + 0xc0000000);
|
auto* vptr = (void*)(descriptor.addr + 0xc0000000);
|
||||||
memcpy(vptr, data, length);
|
memcpy(vptr, data, length);
|
||||||
descriptor.length = length;
|
descriptor.length = length;
|
||||||
descriptor.status = 0;
|
descriptor.status = 0;
|
||||||
|
@ -391,7 +390,7 @@ void E1000NetworkAdapter::send_raw(const u8* data, int length)
|
||||||
tx_current = (tx_current + 1) % number_of_tx_descriptors;
|
tx_current = (tx_current + 1) % number_of_tx_descriptors;
|
||||||
out32(REG_TXDESCTAIL, tx_current);
|
out32(REG_TXDESCTAIL, tx_current);
|
||||||
cli();
|
cli();
|
||||||
enable_irq();
|
enable_interrupts();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (descriptor.status) {
|
if (descriptor.status) {
|
||||||
sti();
|
sti();
|
||||||
|
|
|
@ -27,23 +27,23 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <Kernel/IRQHandler.h>
|
|
||||||
#include <Kernel/Net/NetworkAdapter.h>
|
#include <Kernel/Net/NetworkAdapter.h>
|
||||||
#include <Kernel/PCI/Access.h>
|
#include <Kernel/PCI/Access.h>
|
||||||
|
#include <Kernel/PCI/Device.h>
|
||||||
|
|
||||||
class E1000NetworkAdapter final : public NetworkAdapter
|
class E1000NetworkAdapter final : public NetworkAdapter
|
||||||
, public IRQHandler {
|
, public PCI::Device {
|
||||||
public:
|
public:
|
||||||
static OwnPtr<E1000NetworkAdapter> autodetect();
|
static OwnPtr<E1000NetworkAdapter> autodetect();
|
||||||
|
|
||||||
E1000NetworkAdapter(PCI::Address, u8 irq);
|
E1000NetworkAdapter(PCI::Address, u8 interrupt_vector);
|
||||||
virtual ~E1000NetworkAdapter() override;
|
virtual ~E1000NetworkAdapter() override;
|
||||||
|
|
||||||
virtual void send_raw(const u8*, int) override;
|
virtual void send_raw(const u8*, int) override;
|
||||||
virtual bool link_up() override;
|
virtual bool link_up() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void handle_irq() override;
|
virtual void handle_interrupt() override;
|
||||||
virtual const char* class_name() const override { return "E1000NetworkAdapter"; }
|
virtual const char* class_name() const override { return "E1000NetworkAdapter"; }
|
||||||
|
|
||||||
struct [[gnu::packed]] e1000_rx_desc
|
struct [[gnu::packed]] e1000_rx_desc
|
||||||
|
@ -86,7 +86,6 @@ private:
|
||||||
|
|
||||||
void receive();
|
void receive();
|
||||||
|
|
||||||
PCI::Address m_pci_address;
|
|
||||||
u16 m_io_base { 0 };
|
u16 m_io_base { 0 };
|
||||||
VirtualAddress m_mmio_base;
|
VirtualAddress m_mmio_base;
|
||||||
OwnPtr<Region> m_mmio_region;
|
OwnPtr<Region> m_mmio_region;
|
||||||
|
|
|
@ -139,18 +139,17 @@ OwnPtr<RTL8139NetworkAdapter> RTL8139NetworkAdapter::autodetect()
|
||||||
return make<RTL8139NetworkAdapter>(found_address, irq);
|
return make<RTL8139NetworkAdapter>(found_address, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address pci_address, u8 irq)
|
RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address pci_address, u8 interrupt_vector)
|
||||||
: IRQHandler(irq)
|
: PCI::Device(pci_address, interrupt_vector)
|
||||||
, m_pci_address(pci_address)
|
|
||||||
{
|
{
|
||||||
set_interface_name("rtl8139");
|
set_interface_name("rtl8139");
|
||||||
|
|
||||||
kprintf("RTL8139: Found at PCI address %b:%b:%b\n", pci_address.bus(), pci_address.slot(), pci_address.function());
|
kprintf("RTL8139: Found at PCI address %b:%b:%b\n", pci_address.bus(), pci_address.slot(), pci_address.function());
|
||||||
|
|
||||||
enable_bus_mastering(m_pci_address);
|
enable_bus_mastering(get_pci_address());
|
||||||
|
|
||||||
m_io_base = PCI::get_BAR0(m_pci_address) & ~1;
|
m_io_base = PCI::get_BAR0(get_pci_address()) & ~1;
|
||||||
m_interrupt_line = PCI::get_interrupt_line(m_pci_address);
|
m_interrupt_line = PCI::get_interrupt_line(get_pci_address());
|
||||||
kprintf("RTL8139: IO port base: %w\n", m_io_base);
|
kprintf("RTL8139: IO port base: %w\n", m_io_base);
|
||||||
kprintf("RTL8139: Interrupt line: %u\n", m_interrupt_line);
|
kprintf("RTL8139: Interrupt line: %u\n", m_interrupt_line);
|
||||||
|
|
||||||
|
@ -174,14 +173,14 @@ RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address pci_address, u8 irq)
|
||||||
const auto& mac = mac_address();
|
const auto& mac = mac_address();
|
||||||
kprintf("RTL8139: MAC address: %s\n", mac.to_string().characters());
|
kprintf("RTL8139: MAC address: %s\n", mac.to_string().characters());
|
||||||
|
|
||||||
enable_irq();
|
enable_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
RTL8139NetworkAdapter::~RTL8139NetworkAdapter()
|
RTL8139NetworkAdapter::~RTL8139NetworkAdapter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTL8139NetworkAdapter::handle_irq()
|
void RTL8139NetworkAdapter::handle_interrupt()
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int status = in16(REG_ISR);
|
int status = in16(REG_ISR);
|
||||||
|
|
|
@ -27,25 +27,25 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <Kernel/IRQHandler.h>
|
|
||||||
#include <Kernel/Net/NetworkAdapter.h>
|
#include <Kernel/Net/NetworkAdapter.h>
|
||||||
#include <Kernel/PCI/Access.h>
|
#include <Kernel/PCI/Access.h>
|
||||||
|
#include <Kernel/PCI/Device.h>
|
||||||
|
|
||||||
#define RTL8139_TX_BUFFER_COUNT 4
|
#define RTL8139_TX_BUFFER_COUNT 4
|
||||||
|
|
||||||
class RTL8139NetworkAdapter final : public NetworkAdapter
|
class RTL8139NetworkAdapter final : public NetworkAdapter
|
||||||
, public IRQHandler {
|
, public PCI::Device {
|
||||||
public:
|
public:
|
||||||
static OwnPtr<RTL8139NetworkAdapter> autodetect();
|
static OwnPtr<RTL8139NetworkAdapter> autodetect();
|
||||||
|
|
||||||
RTL8139NetworkAdapter(PCI::Address, u8 irq);
|
RTL8139NetworkAdapter(PCI::Address, u8 interrupt_vector);
|
||||||
virtual ~RTL8139NetworkAdapter() override;
|
virtual ~RTL8139NetworkAdapter() override;
|
||||||
|
|
||||||
virtual void send_raw(const u8*, int) override;
|
virtual void send_raw(const u8*, int) override;
|
||||||
virtual bool link_up() override { return m_link_up; }
|
virtual bool link_up() override { return m_link_up; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void handle_irq() override;
|
virtual void handle_interrupt() override;
|
||||||
virtual const char* class_name() const override { return "RTL8139NetworkAdapter"; }
|
virtual const char* class_name() const override { return "RTL8139NetworkAdapter"; }
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
@ -60,7 +60,6 @@ private:
|
||||||
u16 in16(u16 address);
|
u16 in16(u16 address);
|
||||||
u32 in32(u16 address);
|
u32 in32(u16 address);
|
||||||
|
|
||||||
PCI::Address m_pci_address;
|
|
||||||
u16 m_io_base { 0 };
|
u16 m_io_base { 0 };
|
||||||
u8 m_interrupt_line { 0 };
|
u8 m_interrupt_line { 0 };
|
||||||
u32 m_rx_buffer_addr { 0 };
|
u32 m_rx_buffer_addr { 0 };
|
||||||
|
|
|
@ -101,8 +101,14 @@ extern "C" [[noreturn]] void init()
|
||||||
|
|
||||||
bool text_debug = KParams::the().has("text_debug");
|
bool text_debug = KParams::the().has("text_debug");
|
||||||
|
|
||||||
|
gdt_init();
|
||||||
|
idt_init();
|
||||||
|
|
||||||
setup_acpi();
|
setup_acpi();
|
||||||
|
|
||||||
|
// Sample test to see if the ACPI parser is working...
|
||||||
|
kprintf("ACPI: HPET table @ P 0x%x\n", ACPIParser::the().find_table("HPET"));
|
||||||
|
|
||||||
new VFS;
|
new VFS;
|
||||||
new DebugLogDevice;
|
new DebugLogDevice;
|
||||||
|
|
||||||
|
@ -114,8 +120,6 @@ extern "C" [[noreturn]] void init()
|
||||||
|
|
||||||
RTC::initialize();
|
RTC::initialize();
|
||||||
PIC::initialize();
|
PIC::initialize();
|
||||||
gdt_init();
|
|
||||||
idt_init();
|
|
||||||
|
|
||||||
// call global constructors after gtd and itd init
|
// call global constructors after gtd and itd init
|
||||||
for (ctor_func_t* ctor = &start_ctors; ctor < &end_ctors; ctor++)
|
for (ctor_func_t* ctor = &start_ctors; ctor < &end_ctors; ctor++)
|
||||||
|
@ -136,9 +140,6 @@ extern "C" [[noreturn]] void init()
|
||||||
new VirtualConsole(1);
|
new VirtualConsole(1);
|
||||||
VirtualConsole::switch_to(0);
|
VirtualConsole::switch_to(0);
|
||||||
|
|
||||||
// Sample test to see if the ACPI parser is working...
|
|
||||||
kprintf("ACPI: HPET table @ P 0x%x\n", ACPIParser::the().find_table("HPET"));
|
|
||||||
|
|
||||||
PCI::Initializer::the().test_and_initialize(KParams::the().has("nopci_mmio"));
|
PCI::Initializer::the().test_and_initialize(KParams::the().has("nopci_mmio"));
|
||||||
PCI::Initializer::the().dismiss();
|
PCI::Initializer::the().dismiss();
|
||||||
|
|
||||||
|
@ -171,7 +172,6 @@ extern "C" [[noreturn]] void init()
|
||||||
LoopbackAdapter::the();
|
LoopbackAdapter::the();
|
||||||
auto e1000 = E1000NetworkAdapter::autodetect();
|
auto e1000 = E1000NetworkAdapter::autodetect();
|
||||||
auto rtl8139 = RTL8139NetworkAdapter::autodetect();
|
auto rtl8139 = RTL8139NetworkAdapter::autodetect();
|
||||||
|
|
||||||
Process::initialize();
|
Process::initialize();
|
||||||
Thread::initialize();
|
Thread::initialize();
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ void init_stage2()
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pata0 = PATAChannel::create(PATAChannel::ChannelType::Primary, force_pio);
|
auto pata0 = PATAChannel::autodetect(PATAChannel::ChannelType::Primary, force_pio);
|
||||||
NonnullRefPtr<DiskDevice> root_dev = *pata0->master_device();
|
NonnullRefPtr<DiskDevice> root_dev = *pata0->master_device();
|
||||||
|
|
||||||
root = root.substring(strlen("/dev/hda"), root.length() - strlen("/dev/hda"));
|
root = root.substring(strlen("/dev/hda"), root.length() - strlen("/dev/hda"));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue