mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-28 15:34:33 +00:00
Move drivers to kernel
This commit is contained in:
parent
e2063130ea
commit
80980ecfaf
@ -20,321 +20,317 @@
|
|||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
#include <ints.hpp>
|
#include <ints.hpp>
|
||||||
#include <task.hpp>
|
#include <task.hpp>
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
#include <printf.h>
|
||||||
#include <cwalk.h>
|
#include <cwalk.h>
|
||||||
#include <md5.h>
|
#include <md5.h>
|
||||||
|
|
||||||
|
#include "../../Drivers/drv.hpp"
|
||||||
#include "../../kernel.h"
|
#include "../../kernel.h"
|
||||||
#include "../../DAPI.hpp"
|
#include "../../DAPI.hpp"
|
||||||
#include "../../Fex.hpp"
|
#include "../../Fex.hpp"
|
||||||
#include "api.hpp"
|
#include "api.hpp"
|
||||||
|
|
||||||
NewLock(DriverInitLock);
|
|
||||||
NewLock(DriverInterruptLock);
|
|
||||||
|
|
||||||
namespace Driver
|
namespace Driver
|
||||||
{
|
{
|
||||||
void Driver::Panic()
|
void Driver::Panic()
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
debug("%ld drivers loaded, [DriverUIDs: %ld]", Drivers.size(), DriverUIDs - 1);
|
||||||
size_t DriversNum = Drivers.size();
|
|
||||||
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs);
|
|
||||||
debug("driver size %ld", DriversNum);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
foreach (auto drv in Drivers)
|
foreach (auto Drv in Drivers)
|
||||||
{
|
{
|
||||||
KernelCallback callback{};
|
KernelCallback callback{};
|
||||||
callback.Reason = StopReason;
|
callback.Reason = StopReason;
|
||||||
DriverManager->IOCB(drv.DriverUID, &callback);
|
DriverManager->IOCB(Drv.DriverUID, &callback);
|
||||||
|
|
||||||
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
|
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
|
||||||
{
|
{
|
||||||
if (!drv.InterruptHook[j])
|
if (!Drv.InterruptHook[j])
|
||||||
continue;
|
continue;
|
||||||
drv.InterruptHook[j]->Disable();
|
|
||||||
debug("Interrupt hook %#lx disabled", drv.InterruptHook[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Driver::UnloadAllDrivers()
|
Drv.InterruptHook[j]->Disable();
|
||||||
{
|
debug("Interrupt hook %#lx disabled", Drv.InterruptHook[j]);
|
||||||
#ifdef DEBUG
|
}
|
||||||
size_t DriversNum = Drivers.size();
|
}
|
||||||
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs);
|
}
|
||||||
debug("driver size %ld", DriversNum);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
foreach (auto drv in Drivers)
|
void Driver::UnloadAllDrivers()
|
||||||
{
|
{
|
||||||
KernelCallback callback{};
|
debug("%ld drivers loaded, [DriverUIDs: %ld]", Drivers.size(), DriverUIDs - 1);
|
||||||
callback.Reason = StopReason;
|
|
||||||
debug("Stopping & unloading driver %ld [%#lx]", drv.DriverUID, drv.Address);
|
|
||||||
DriverManager->IOCB(drv.DriverUID, &callback);
|
|
||||||
|
|
||||||
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
|
foreach (auto Drv in Drivers)
|
||||||
{
|
{
|
||||||
if (!drv.InterruptHook[j])
|
KernelCallback callback{};
|
||||||
continue;
|
callback.Reason = StopReason;
|
||||||
debug("Interrupt hook %#lx", drv.InterruptHook[j]);
|
debug("Stopping & unloading driver %ld [%#lx]", Drv.DriverUID, Drv.Address);
|
||||||
delete drv.InterruptHook[j], drv.InterruptHook[j] = nullptr;
|
DriverManager->IOCB(Drv.DriverUID, &callback);
|
||||||
}
|
|
||||||
if (drv.MemTrk)
|
|
||||||
delete drv.MemTrk, drv.MemTrk = nullptr;
|
|
||||||
}
|
|
||||||
Drivers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Driver::UnloadDriver(unsigned long DUID)
|
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
|
||||||
{
|
{
|
||||||
debug("Searching for driver %ld", DUID);
|
if (!Drv.InterruptHook[j])
|
||||||
|
continue;
|
||||||
|
|
||||||
foreach (auto drv in Drivers)
|
debug("Interrupt hook %#lx", Drv.InterruptHook[j]);
|
||||||
{
|
delete Drv.InterruptHook[j], Drv.InterruptHook[j] = nullptr;
|
||||||
if (drv.DriverUID == DUID)
|
}
|
||||||
{
|
|
||||||
KernelCallback callback{};
|
|
||||||
callback.Reason = StopReason;
|
|
||||||
debug("Stopping and unloading driver %ld [%#lx]", drv.DriverUID, drv.Address);
|
|
||||||
this->IOCB(drv.DriverUID, &callback);
|
|
||||||
|
|
||||||
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
|
if (Drv.MemTrk)
|
||||||
{
|
delete Drv.MemTrk, Drv.MemTrk = nullptr;
|
||||||
if (!drv.InterruptHook[j])
|
}
|
||||||
continue;
|
Drivers.clear();
|
||||||
debug("Interrupt hook %#lx", drv.InterruptHook[j]);
|
}
|
||||||
delete drv.InterruptHook[j], drv.InterruptHook[j] = nullptr;
|
|
||||||
}
|
|
||||||
delete drv.MemTrk, drv.MemTrk = nullptr;
|
|
||||||
Drivers.remove(drv);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Driver::IOCB(unsigned long DUID, void *KCB)
|
bool Driver::UnloadDriver(unsigned long DUID)
|
||||||
{
|
{
|
||||||
foreach (auto Drv in Drivers)
|
debug("Searching for driver %ld", DUID);
|
||||||
{
|
|
||||||
if (Drv.DriverUID == DUID)
|
|
||||||
{
|
|
||||||
FexExtended *DrvExtHdr = (FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS);
|
|
||||||
int ret = ((int (*)(void *))((uintptr_t)DrvExtHdr->Driver.Callback + (uintptr_t)Drv.Address))(KCB);
|
|
||||||
__sync;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::CallDriverEntryPoint(void *fex, void *KAPIAddress)
|
foreach (auto Drv in Drivers)
|
||||||
{
|
{
|
||||||
memcpy(KAPIAddress, &KernelAPITemplate, sizeof(KernelAPI));
|
if (Drv.DriverUID != DUID)
|
||||||
|
continue;
|
||||||
|
|
||||||
((KernelAPI *)KAPIAddress)->Info.Offset = (unsigned long)fex;
|
KernelCallback callback{};
|
||||||
((KernelAPI *)KAPIAddress)->Info.DriverUID = DriverUIDs++;
|
callback.Reason = StopReason;
|
||||||
((KernelAPI *)KAPIAddress)->Info.KernelDebug = DebuggerIsAttached;
|
debug("Stopping & unloading driver %ld [%#lx]", Drv.DriverUID, Drv.Address);
|
||||||
|
this->IOCB(Drv.DriverUID, &callback);
|
||||||
|
|
||||||
#ifdef DEBUG
|
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
{
|
||||||
debug("DRIVER: %s HAS DRIVER ID %ld", fexExtended->Driver.Name, ((KernelAPI *)KAPIAddress)->Info.DriverUID);
|
if (!Drv.InterruptHook[j])
|
||||||
#endif
|
continue;
|
||||||
|
|
||||||
debug("Calling driver entry point ( %#lx %ld )", (unsigned long)fex, ((KernelAPI *)KAPIAddress)->Info.DriverUID);
|
debug("Interrupt hook %#lx", Drv.InterruptHook[j]);
|
||||||
int ret = ((int (*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)KAPIAddress));
|
delete Drv.InterruptHook[j], Drv.InterruptHook[j] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (DriverReturnCode::OK != ret)
|
if (Drv.MemTrk)
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
delete Drv.MemTrk, Drv.MemTrk = nullptr;
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::LoadDriver(uintptr_t DriverAddress, uintptr_t Size)
|
Drivers.remove(Drv);
|
||||||
{
|
return true;
|
||||||
Fex *DrvHdr = (Fex *)DriverAddress;
|
}
|
||||||
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
|
return false;
|
||||||
{
|
}
|
||||||
if (Size > 0x1000)
|
|
||||||
{
|
|
||||||
Fex *ElfDrvHdr = (Fex *)(DriverAddress + 0x1000);
|
|
||||||
if (ElfDrvHdr->Magic[0] != 'F' || ElfDrvHdr->Magic[1] != 'E' || ElfDrvHdr->Magic[2] != 'X' || ElfDrvHdr->Magic[3] != '\0')
|
|
||||||
return DriverCode::INVALID_FEX_HEADER;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", ElfDrvHdr->Magic, ElfDrvHdr->Type, ElfDrvHdr->OS, ElfDrvHdr->EntryPoint);
|
|
||||||
|
|
||||||
if (ElfDrvHdr->Type == FexFormatType::FexFormatType_Driver)
|
int Driver::IOCB(unsigned long DUID, void *KCB)
|
||||||
{
|
{
|
||||||
FexExtended *ElfDrvExtHdr = (FexExtended *)((uintptr_t)ElfDrvHdr + EXTENDED_SECTION_ADDRESS);
|
foreach (auto Drv in Drivers)
|
||||||
debug("Name: \"%s\"; Type: %d; Callback: %#lx", ElfDrvExtHdr->Driver.Name, ElfDrvExtHdr->Driver.Type, ElfDrvExtHdr->Driver.Callback);
|
{
|
||||||
|
if (Drv.DriverUID != DUID)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
|
FexExtended *fexE = (FexExtended *)Drv.ExtendedHeaderAddress;
|
||||||
return this->DriverLoadBindPCI(ElfDrvExtHdr, DriverAddress, Size, true);
|
return ((int (*)(void *))((uintptr_t)fexE->Driver.Callback + (uintptr_t)Drv.Address))(KCB);
|
||||||
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
|
}
|
||||||
return this->DriverLoadBindInterrupt(ElfDrvExtHdr, DriverAddress, Size, true);
|
return -1;
|
||||||
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
|
}
|
||||||
return this->DriverLoadBindProcess(ElfDrvExtHdr, DriverAddress, Size, true);
|
|
||||||
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
|
|
||||||
return this->DriverLoadBindInput(ElfDrvExtHdr, DriverAddress, Size, true);
|
|
||||||
else
|
|
||||||
error("Unknown driver bind type: %d", ElfDrvExtHdr->Driver.Bind.Type);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return DriverCode::NOT_DRIVER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return DriverCode::INVALID_FEX_HEADER;
|
|
||||||
}
|
|
||||||
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->EntryPoint);
|
|
||||||
|
|
||||||
if (DrvHdr->Type == FexFormatType::FexFormatType_Driver)
|
DriverCode Driver::CallDriverEntryPoint(void *fex, bool BuiltIn)
|
||||||
{
|
{
|
||||||
FexExtended *DrvExtHdr = (FexExtended *)((uintptr_t)DrvHdr + EXTENDED_SECTION_ADDRESS);
|
DriverCode ret{};
|
||||||
debug("Name: \"%s\"; Type: %d; Callback: %#lx", DrvExtHdr->Driver.Name, DrvExtHdr->Driver.Type, DrvExtHdr->Driver.Callback);
|
KernelAPI DriverKAPI = KernelAPITemplate;
|
||||||
|
|
||||||
if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
|
DriverKAPI.Info.DriverUID = DriverUIDs++;
|
||||||
return this->DriverLoadBindPCI(DrvExtHdr, DriverAddress, Size);
|
DriverKAPI.Info.KernelDebug = DebuggerIsAttached;
|
||||||
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
|
|
||||||
return this->DriverLoadBindInterrupt(DrvExtHdr, DriverAddress, Size);
|
|
||||||
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
|
|
||||||
return this->DriverLoadBindProcess(DrvExtHdr, DriverAddress, Size);
|
|
||||||
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
|
|
||||||
return this->DriverLoadBindInput(DrvExtHdr, DriverAddress, Size);
|
|
||||||
else
|
|
||||||
error("Unknown driver bind type: %d", DrvExtHdr->Driver.Bind.Type);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return DriverCode::NOT_DRIVER;
|
|
||||||
return DriverCode::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
Driver::Driver()
|
debug("Calling driver entry point ( %#lx %ld )", (unsigned long)fex, DriverKAPI.Info.DriverUID);
|
||||||
{
|
|
||||||
SmartCriticalSection(DriverInitLock);
|
|
||||||
|
|
||||||
std::string DriverConfigFile = Config.DriverDirectory;
|
if (!BuiltIn)
|
||||||
DriverConfigFile << "/config.ini";
|
{
|
||||||
fixme("Loading driver config file: %s", DriverConfigFile.c_str());
|
DriverKAPI.Info.Offset = (unsigned long)fex;
|
||||||
|
|
||||||
VirtualFileSystem::File DriverDirectory = vfs->Open(Config.DriverDirectory);
|
debug("DRIVER: %s HAS DRIVER ID %ld",
|
||||||
if (DriverDirectory.IsOK())
|
((FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS))->Driver.Name,
|
||||||
{
|
DriverKAPI.Info.DriverUID);
|
||||||
foreach (auto driver in DriverDirectory.node->Children)
|
ret = ((DriverCode(*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)&DriverKAPI));
|
||||||
if (driver->Flags == VirtualFileSystem::NodeFlags::FILE)
|
}
|
||||||
if (cwk_path_has_extension(driver->Name))
|
else
|
||||||
{
|
{
|
||||||
const char *extension;
|
debug("DRIVER: BUILTIN HAS DRIVER ID %ld", DriverKAPI.Info.DriverUID);
|
||||||
size_t extension_length;
|
ret = ((DriverCode(*)(KernelAPI *))((uintptr_t)fex))(((KernelAPI *)&DriverKAPI));
|
||||||
cwk_path_get_extension(driver->Name, &extension, &extension_length);
|
}
|
||||||
debug("Driver: %s; Extension: %s", driver->Name, extension);
|
|
||||||
if (strcmp(extension, ".fex") == 0 || strcmp(extension, ".elf") == 0)
|
|
||||||
{
|
|
||||||
uintptr_t ret = this->LoadDriver(driver->Address, driver->Length);
|
|
||||||
char RetString[128];
|
|
||||||
if (ret == DriverCode::OK)
|
|
||||||
strncpy(RetString, "\e058C19OK", 10);
|
|
||||||
else if (ret == DriverCode::NOT_AVAILABLE)
|
|
||||||
strncpy(RetString, "\eFF7900NOT AVAILABLE", 21);
|
|
||||||
else
|
|
||||||
sprintf(RetString, "\eE85230FAILED (%#lx)", ret);
|
|
||||||
KPrint("%s %s", driver->Name, RetString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status);
|
|
||||||
vfs->Close(DriverDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
Driver::~Driver()
|
if (DriverCode::OK != ret)
|
||||||
{
|
{
|
||||||
debug("Destructor called");
|
DriverUIDs--;
|
||||||
this->UnloadAllDrivers();
|
return ret;
|
||||||
}
|
}
|
||||||
|
return DriverCode::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DriverCode Driver::LoadDriver(uintptr_t DriverAddress, uintptr_t Size)
|
||||||
|
{
|
||||||
|
Fex *DrvHdr = (Fex *)DriverAddress;
|
||||||
|
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
|
||||||
|
return DriverCode::INVALID_FEX_HEADER;
|
||||||
|
|
||||||
|
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->EntryPoint);
|
||||||
|
|
||||||
|
if (DrvHdr->Type != FexFormatType::FexFormatType_Driver)
|
||||||
|
return DriverCode::NOT_DRIVER;
|
||||||
|
|
||||||
|
FexExtended *fexE = (FexExtended *)((uintptr_t)DrvHdr + EXTENDED_SECTION_ADDRESS);
|
||||||
|
debug("Name: \"%s\"; Type: %d; Callback: %#lx", fexE->Driver.Name, fexE->Driver.Type, fexE->Driver.Callback);
|
||||||
|
|
||||||
|
switch (fexE->Driver.Bind.Type)
|
||||||
|
{
|
||||||
|
case DriverBindType::BIND_PCI:
|
||||||
|
return this->DriverLoadBindPCI(DriverAddress, Size);
|
||||||
|
case DriverBindType::BIND_INTERRUPT:
|
||||||
|
return this->DriverLoadBindInterrupt(DriverAddress, Size);
|
||||||
|
case DriverBindType::BIND_PROCESS:
|
||||||
|
return this->DriverLoadBindProcess(DriverAddress, Size);
|
||||||
|
case DriverBindType::BIND_INPUT:
|
||||||
|
return this->DriverLoadBindInput(DriverAddress, Size);
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
error("Unknown driver bind type: %d", fexE->Driver.Bind.Type);
|
||||||
|
return DriverCode::UNKNOWN_DRIVER_BIND_TYPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Driver::LoadDrivers()
|
||||||
|
{
|
||||||
|
SmartCriticalSection(DriverInitLock);
|
||||||
|
|
||||||
|
std::string DriverConfigFile = Config.DriverDirectory;
|
||||||
|
DriverConfigFile << "/config.ini";
|
||||||
|
fixme("Loading driver config file: %s", DriverConfigFile.c_str());
|
||||||
|
|
||||||
|
VirtualFileSystem::File DriverDirectory = vfs->Open(Config.DriverDirectory);
|
||||||
|
if (!DriverDirectory.IsOK())
|
||||||
|
{
|
||||||
|
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status);
|
||||||
|
vfs->Close(DriverDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("Loading built-in drivers");
|
||||||
|
StartAHCI();
|
||||||
|
StartVMwareMouse();
|
||||||
|
StartPS2Mouse();
|
||||||
|
StartATA();
|
||||||
|
StartAC97();
|
||||||
|
StartRTL8139();
|
||||||
|
StartPCNET();
|
||||||
|
StartGigabit();
|
||||||
|
|
||||||
|
debug("Loading drivers from %s", Config.DriverDirectory);
|
||||||
|
foreach (auto DrvFile in DriverDirectory.node->Children)
|
||||||
|
{
|
||||||
|
if (DrvFile->Flags != VirtualFileSystem::NodeFlags::FILE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cwk_path_has_extension(DrvFile->Name))
|
||||||
|
{
|
||||||
|
const char *extension;
|
||||||
|
size_t extension_length;
|
||||||
|
cwk_path_get_extension(DrvFile->Name, &extension, &extension_length);
|
||||||
|
debug("File: %s; Extension: %s", DrvFile->Name, extension);
|
||||||
|
if (strcmp(extension, ".fex") == 0)
|
||||||
|
{
|
||||||
|
uintptr_t ret = this->LoadDriver(DrvFile->Address, DrvFile->Length);
|
||||||
|
std::string RetString;
|
||||||
|
if (ret == DriverCode::OK)
|
||||||
|
RetString << "\e058C19OK";
|
||||||
|
else if (ret == DriverCode::NOT_AVAILABLE)
|
||||||
|
RetString << "\eFF7900NOT AVAILABLE";
|
||||||
|
else
|
||||||
|
RetString << "\eE85230FAILED";
|
||||||
|
KPrint("%s %s %#lx", DrvFile->Name, RetString.c_str(), ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vfs->Close(DriverDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
Driver::Driver() {}
|
||||||
|
|
||||||
|
Driver::~Driver()
|
||||||
|
{
|
||||||
|
debug("Destructor called");
|
||||||
|
this->UnloadAllDrivers();
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
|
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
|
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
SmartLock(DriverInterruptLock); /* Lock in case of multiple interrupts firing at the same time */
|
SmartLock(DriverInterruptLock); /* Lock in case of multiple interrupts firing at the same time */
|
||||||
if (!this->Enabled)
|
if (!this->Enabled)
|
||||||
{
|
{
|
||||||
debug("Interrupt hook is not enabled");
|
debug("Interrupt hook is not enabled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Handle.InterruptCallback)
|
if (!Handle.InterruptCallback)
|
||||||
{
|
{
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
uint64_t IntNum = Frame->InterruptNumber - 32;
|
uint64_t IntNum = Frame->InterruptNumber - 32;
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
uint64_t IntNum = Frame->InterruptNumber;
|
uint64_t IntNum = Frame->InterruptNumber;
|
||||||
#endif
|
#endif
|
||||||
warn("Interrupt callback for %ld is not set for driver %ld!", IntNum, Handle.DriverUID);
|
warn("Interrupt callback for %ld is not set for driver %ld!", IntNum, Handle.DriverUID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CPURegisters regs;
|
CPURegisters regs;
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
regs.r15 = Frame->r15;
|
regs.r15 = Frame->r15;
|
||||||
regs.r14 = Frame->r14;
|
regs.r14 = Frame->r14;
|
||||||
regs.r13 = Frame->r13;
|
regs.r13 = Frame->r13;
|
||||||
regs.r12 = Frame->r12;
|
regs.r12 = Frame->r12;
|
||||||
regs.r11 = Frame->r11;
|
regs.r11 = Frame->r11;
|
||||||
regs.r10 = Frame->r10;
|
regs.r10 = Frame->r10;
|
||||||
regs.r9 = Frame->r9;
|
regs.r9 = Frame->r9;
|
||||||
regs.r8 = Frame->r8;
|
regs.r8 = Frame->r8;
|
||||||
|
|
||||||
regs.rbp = Frame->rbp;
|
regs.rbp = Frame->rbp;
|
||||||
regs.rdi = Frame->rdi;
|
regs.rdi = Frame->rdi;
|
||||||
regs.rsi = Frame->rsi;
|
regs.rsi = Frame->rsi;
|
||||||
regs.rdx = Frame->rdx;
|
regs.rdx = Frame->rdx;
|
||||||
regs.rcx = Frame->rcx;
|
regs.rcx = Frame->rcx;
|
||||||
regs.rbx = Frame->rbx;
|
regs.rbx = Frame->rbx;
|
||||||
regs.rax = Frame->rax;
|
regs.rax = Frame->rax;
|
||||||
|
|
||||||
regs.InterruptNumber = Frame->InterruptNumber;
|
regs.InterruptNumber = Frame->InterruptNumber;
|
||||||
regs.ErrorCode = Frame->ErrorCode;
|
regs.ErrorCode = Frame->ErrorCode;
|
||||||
regs.rip = Frame->rip;
|
regs.rip = Frame->rip;
|
||||||
regs.cs = Frame->cs;
|
regs.cs = Frame->cs;
|
||||||
regs.rflags = Frame->rflags.raw;
|
regs.rflags = Frame->rflags.raw;
|
||||||
regs.rsp = Frame->rsp;
|
regs.rsp = Frame->rsp;
|
||||||
regs.ss = Frame->ss;
|
regs.ss = Frame->ss;
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
regs.ebp = Frame->ebp;
|
regs.ebp = Frame->ebp;
|
||||||
regs.edi = Frame->edi;
|
regs.edi = Frame->edi;
|
||||||
regs.esi = Frame->esi;
|
regs.esi = Frame->esi;
|
||||||
regs.edx = Frame->edx;
|
regs.edx = Frame->edx;
|
||||||
regs.ecx = Frame->ecx;
|
regs.ecx = Frame->ecx;
|
||||||
regs.ebx = Frame->ebx;
|
regs.ebx = Frame->ebx;
|
||||||
regs.eax = Frame->eax;
|
regs.eax = Frame->eax;
|
||||||
|
|
||||||
regs.InterruptNumber = Frame->InterruptNumber;
|
regs.InterruptNumber = Frame->InterruptNumber;
|
||||||
regs.ErrorCode = Frame->ErrorCode;
|
regs.ErrorCode = Frame->ErrorCode;
|
||||||
regs.eip = Frame->eip;
|
regs.eip = Frame->eip;
|
||||||
regs.cs = Frame->cs;
|
regs.cs = Frame->cs;
|
||||||
regs.eflags = Frame->eflags.raw;
|
regs.eflags = Frame->eflags.raw;
|
||||||
regs.esp = Frame->esp;
|
regs.esp = Frame->esp;
|
||||||
regs.ss = Frame->ss;
|
regs.ss = Frame->ss;
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
#endif
|
#endif
|
||||||
((int (*)(void *))(Handle.InterruptCallback))(®s);
|
((int (*)(void *))(Handle.InterruptCallback))(®s);
|
||||||
UNUSED(Frame);
|
UNUSED(Frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
DriverInterruptHook::DriverInterruptHook(int Interrupt, DriverFile Handle) : Interrupts::Handler(Interrupt)
|
DriverInterruptHook::DriverInterruptHook(int Interrupt, DriverFile Handle) : Interrupts::Handler(Interrupt)
|
||||||
{
|
{
|
||||||
this->Handle = Handle;
|
this->Handle = Handle;
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
|
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
|
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,165 +39,165 @@ void DriverDebugPrint(char *String, unsigned long DriverUID) { trace("[%ld] %s",
|
|||||||
|
|
||||||
void DriverDisplayPrint(char *String)
|
void DriverDisplayPrint(char *String)
|
||||||
{
|
{
|
||||||
SmartLock(DriverDisplayPrintLock);
|
SmartLock(DriverDisplayPrintLock);
|
||||||
for (unsigned long i = 0; i < strlen(String); i++)
|
for (unsigned long i = 0; i < strlen(String); i++)
|
||||||
Display->Print(String[i], 0, true);
|
Display->Print(String[i], 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *RequestPage(unsigned long Size)
|
void *RequestPage(unsigned long Size)
|
||||||
{
|
{
|
||||||
void *ret = KernelAllocator.RequestPages(Size + 1);
|
void *ret = KernelAllocator.RequestPages(Size + 1);
|
||||||
drvdbg("Allocated %ld pages (%#lx-%#lx)", Size, (unsigned long)ret, (unsigned long)ret + FROM_PAGES(Size));
|
drvdbg("Allocated %ld pages (%#lx-%#lx)", Size, (unsigned long)ret, (unsigned long)ret + FROM_PAGES(Size));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreePage(void *Page, unsigned long Size)
|
void FreePage(void *Page, unsigned long Size)
|
||||||
{
|
{
|
||||||
drvdbg("Freeing %ld pages (%#lx-%#lx)", Size, (unsigned long)Page, (unsigned long)Page + FROM_PAGES(Size));
|
drvdbg("Freeing %ld pages (%#lx-%#lx)", Size, (unsigned long)Page, (unsigned long)Page + FROM_PAGES(Size));
|
||||||
KernelAllocator.FreePages(Page, Size + 1);
|
KernelAllocator.FreePages(Page, Size + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapMemory(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags)
|
void MapMemory(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags)
|
||||||
{
|
{
|
||||||
SmartLock(DriverDisplayPrintLock);
|
SmartLock(DriverDisplayPrintLock);
|
||||||
drvdbg("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags);
|
drvdbg("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags);
|
||||||
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnmapMemory(void *VirtualAddress)
|
void UnmapMemory(void *VirtualAddress)
|
||||||
{
|
{
|
||||||
SmartLock(DriverDisplayPrintLock);
|
SmartLock(DriverDisplayPrintLock);
|
||||||
drvdbg("Unmapping %#lx...", (unsigned long)VirtualAddress);
|
drvdbg("Unmapping %#lx...", (unsigned long)VirtualAddress);
|
||||||
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Drivermemcpy(void *Destination, void *Source, unsigned long Size)
|
void *Drivermemcpy(void *Destination, void *Source, unsigned long Size)
|
||||||
{
|
{
|
||||||
SmartLock(DriverDisplayPrintLock);
|
SmartLock(DriverDisplayPrintLock);
|
||||||
drvdbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size,
|
drvdbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size,
|
||||||
(unsigned long)Source, (unsigned long)Source + Size,
|
(unsigned long)Source, (unsigned long)Source + Size,
|
||||||
(unsigned long)Destination, (unsigned long)Destination + Size);
|
(unsigned long)Destination, (unsigned long)Destination + Size);
|
||||||
return memcpy(Destination, Source, Size);
|
return memcpy(Destination, Source, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Drivermemset(void *Destination, int Value, unsigned long Size)
|
void *Drivermemset(void *Destination, int Value, unsigned long Size)
|
||||||
{
|
{
|
||||||
SmartLock(DriverDisplayPrintLock);
|
SmartLock(DriverDisplayPrintLock);
|
||||||
drvdbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value,
|
drvdbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value,
|
||||||
(unsigned long)Destination, (unsigned long)Destination + Size,
|
(unsigned long)Destination, (unsigned long)Destination + Size,
|
||||||
Size);
|
Size);
|
||||||
return memset(Destination, Value, Size);
|
return memset(Destination, Value, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriverNetSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
void DriverNetSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
||||||
{
|
{
|
||||||
// This is useless I guess...
|
// This is useless I guess...
|
||||||
if (NIManager)
|
if (NIManager)
|
||||||
NIManager->DrvSend(DriverID, Data, Size);
|
NIManager->DrvSend(DriverID, Data, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriverNetReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
void DriverNetReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
||||||
{
|
{
|
||||||
if (NIManager)
|
if (NIManager)
|
||||||
NIManager->DrvReceive(DriverID, Data, Size);
|
NIManager->DrvReceive(DriverID, Data, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
|
void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
|
||||||
{
|
{
|
||||||
DumpData("DriverDiskRead", Data, SectorCount * 512);
|
DumpData("DriverDiskRead", Data, SectorCount * 512);
|
||||||
UNUSED(DriverID);
|
UNUSED(DriverID);
|
||||||
UNUSED(Sector);
|
UNUSED(Sector);
|
||||||
UNUSED(Port);
|
UNUSED(Port);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriverAHCIDiskWrite(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
|
void DriverAHCIDiskWrite(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
|
||||||
{
|
{
|
||||||
DumpData("DriverDiskWrite", Data, SectorCount * 512);
|
DumpData("DriverDiskWrite", Data, SectorCount * 512);
|
||||||
UNUSED(DriverID);
|
UNUSED(DriverID);
|
||||||
UNUSED(Sector);
|
UNUSED(Sector);
|
||||||
UNUSED(Port);
|
UNUSED(Port);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *DriverPCIGetDeviceName(unsigned int VendorID, unsigned int DeviceID)
|
char *DriverPCIGetDeviceName(unsigned int VendorID, unsigned int DeviceID)
|
||||||
{
|
{
|
||||||
UNUSED(VendorID);
|
UNUSED(VendorID);
|
||||||
UNUSED(DeviceID);
|
UNUSED(DeviceID);
|
||||||
return (char *)"Unknown";
|
return (char *)"Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DriverGetWidth()
|
unsigned int DriverGetWidth()
|
||||||
{
|
{
|
||||||
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
|
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
|
||||||
return Display->GetBuffer(0)->Width;
|
return Display->GetBuffer(0)->Width;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DriverGetHeight()
|
unsigned int DriverGetHeight()
|
||||||
{
|
{
|
||||||
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
|
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
|
||||||
return Display->GetBuffer(0)->Height;
|
return Display->GetBuffer(0)->Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriverSleep(unsigned long Milliseconds)
|
void DriverSleep(unsigned long Milliseconds)
|
||||||
{
|
{
|
||||||
SmartLock(DriverDisplayPrintLock);
|
SmartLock(DriverDisplayPrintLock);
|
||||||
drvdbg("Sleeping for %ld milliseconds...", Milliseconds);
|
drvdbg("Sleeping for %ld milliseconds...", Milliseconds);
|
||||||
if (TaskManager)
|
if (TaskManager)
|
||||||
TaskManager->Sleep(Milliseconds);
|
TaskManager->Sleep(Milliseconds);
|
||||||
else
|
else
|
||||||
TimeManager->Sleep(Milliseconds, Time::Units::Milliseconds);
|
TimeManager->Sleep(Milliseconds, Time::Units::Milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Driversprintf(char *Buffer, const char *Format, ...)
|
int Driversprintf(char *Buffer, const char *Format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, Format);
|
va_start(args, Format);
|
||||||
int ret = vsprintf(Buffer, Format, args);
|
int ret = vsprintf(Buffer, Format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelAPI KernelAPITemplate = {
|
KernelAPI KernelAPITemplate = {
|
||||||
.Version = {
|
.Version = {
|
||||||
.Major = 0,
|
.Major = 0,
|
||||||
.Minor = 0,
|
.Minor = 0,
|
||||||
.Patch = 1},
|
.Patch = 1},
|
||||||
.Info = {
|
.Info = {
|
||||||
.Offset = 0,
|
.Offset = 0,
|
||||||
.DriverUID = 0,
|
.DriverUID = 0,
|
||||||
.KernelDebug = false,
|
.KernelDebug = false,
|
||||||
},
|
},
|
||||||
.Memory = {
|
.Memory = {
|
||||||
.PageSize = PAGE_SIZE,
|
.PageSize = PAGE_SIZE,
|
||||||
.RequestPage = RequestPage,
|
.RequestPage = RequestPage,
|
||||||
.FreePage = FreePage,
|
.FreePage = FreePage,
|
||||||
.Map = MapMemory,
|
.Map = MapMemory,
|
||||||
.Unmap = UnmapMemory,
|
.Unmap = UnmapMemory,
|
||||||
},
|
},
|
||||||
.PCI = {
|
.PCI = {
|
||||||
.GetDeviceName = DriverPCIGetDeviceName,
|
.GetDeviceName = DriverPCIGetDeviceName,
|
||||||
},
|
},
|
||||||
.Util = {
|
.Util = {
|
||||||
.DebugPrint = DriverDebugPrint,
|
.DebugPrint = DriverDebugPrint,
|
||||||
.DisplayPrint = DriverDisplayPrint,
|
.DisplayPrint = DriverDisplayPrint,
|
||||||
.memcpy = Drivermemcpy,
|
.memcpy = Drivermemcpy,
|
||||||
.memset = Drivermemset,
|
.memset = Drivermemset,
|
||||||
.Sleep = DriverSleep,
|
.Sleep = DriverSleep,
|
||||||
.sprintf = Driversprintf,
|
.sprintf = Driversprintf,
|
||||||
},
|
},
|
||||||
.Command = {
|
.Command = {
|
||||||
.Network = {
|
.Network = {
|
||||||
.SendPacket = DriverNetSend,
|
.SendPacket = DriverNetSend,
|
||||||
.ReceivePacket = DriverNetReceive,
|
.ReceivePacket = DriverNetReceive,
|
||||||
},
|
},
|
||||||
.Disk = {
|
.Disk = {
|
||||||
.AHCI = {
|
.AHCI = {
|
||||||
.ReadSector = DriverAHCIDiskRead,
|
.ReadSector = DriverAHCIDiskRead,
|
||||||
.WriteSector = DriverAHCIDiskWrite,
|
.WriteSector = DriverAHCIDiskWrite,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.Display = {
|
.Display = {
|
||||||
.GetWidth = DriverGetWidth,
|
.GetWidth = DriverGetWidth,
|
||||||
.GetHeight = DriverGetHeight,
|
.GetHeight = DriverGetHeight,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -31,43 +31,9 @@
|
|||||||
|
|
||||||
namespace Driver
|
namespace Driver
|
||||||
{
|
{
|
||||||
DriverCode Driver::DriverLoadBindInput(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
|
DriverCode Driver::DriverLoadBindInput(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
|
||||||
{
|
{
|
||||||
UNUSED(DrvExtHdr);
|
stub;
|
||||||
UNUSED(IsElf);
|
return DriverCode::NOT_IMPLEMENTED;
|
||||||
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
}
|
||||||
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
|
|
||||||
memcpy(fex, (void *)DriverAddress, Size);
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
|
||||||
#ifdef DEBUG
|
|
||||||
uint8_t *result = md5File((uint8_t *)fex, Size);
|
|
||||||
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
|
||||||
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
|
||||||
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
|
|
||||||
kfree(result);
|
|
||||||
#endif
|
|
||||||
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI) + 1));
|
|
||||||
|
|
||||||
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
|
|
||||||
{
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
|
|
||||||
|
|
||||||
switch (fexExtended->Driver.Type)
|
|
||||||
{
|
|
||||||
case FexDriverType::FexDriverType_Input:
|
|
||||||
return BindInputInput(mem, fex);
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
warn("Unknown driver type: %d", fexExtended->Driver.Type);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -31,55 +31,88 @@
|
|||||||
|
|
||||||
namespace Driver
|
namespace Driver
|
||||||
{
|
{
|
||||||
DriverCode Driver::DriverLoadBindInterrupt(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
|
DriverCode Driver::DriverLoadBindInterrupt(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
|
||||||
{
|
{
|
||||||
UNUSED(DrvExtHdr);
|
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
||||||
UNUSED(IsElf);
|
|
||||||
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
|
||||||
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
|
|
||||||
memcpy(fex, (void *)DriverAddress, Size);
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
|
||||||
#ifdef DEBUG
|
|
||||||
uint8_t *result = md5File((uint8_t *)fex, Size);
|
|
||||||
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
|
||||||
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
|
||||||
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
|
|
||||||
kfree(result);
|
|
||||||
#endif
|
|
||||||
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI) + 1));
|
|
||||||
|
|
||||||
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
|
BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress;
|
||||||
{
|
Fex *fex = nullptr;
|
||||||
delete mem, mem = nullptr;
|
if (!IsBuiltIn)
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
{
|
||||||
}
|
fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
|
||||||
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
|
memcpy(fex, (void *)DriverAddress, Size);
|
||||||
|
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fex = (Fex *)bidi->EntryPoint;
|
||||||
|
DriverCode ret = CallDriverEntryPoint(fex, IsBuiltIn);
|
||||||
|
if (ret != DriverCode::OK)
|
||||||
|
{
|
||||||
|
delete mem;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
switch (fexExtended->Driver.Type)
|
if (IsBuiltIn)
|
||||||
{
|
fex = 0x0; /* Addresses are absolute if built-in. */
|
||||||
case FexDriverType::FexDriverType_Generic:
|
|
||||||
return BindInterruptGeneric(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_Display:
|
|
||||||
return BindInterruptDisplay(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_Network:
|
|
||||||
return BindInterruptNetwork(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_Storage:
|
|
||||||
return BindInterruptStorage(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_FileSystem:
|
|
||||||
return BindInterruptFileSystem(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_Input:
|
|
||||||
return BindInterruptInput(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_Audio:
|
|
||||||
return BindInterruptAudio(mem, fex);
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
warn("Unknown driver type: %d", fexExtended->Driver.Type);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return DriverCode::OK;
|
FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||||
}
|
|
||||||
|
debug("Starting driver %s", fexE->Driver.Name);
|
||||||
|
|
||||||
|
switch (fexE->Driver.Type)
|
||||||
|
{
|
||||||
|
case FexDriverType::FexDriverType_Generic:
|
||||||
|
case FexDriverType::FexDriverType_Display:
|
||||||
|
case FexDriverType::FexDriverType_Network:
|
||||||
|
case FexDriverType::FexDriverType_Storage:
|
||||||
|
case FexDriverType::FexDriverType_FileSystem:
|
||||||
|
case FexDriverType::FexDriverType_Input:
|
||||||
|
case FexDriverType::FexDriverType_Audio:
|
||||||
|
{
|
||||||
|
FexExtended *DriverExtendedHeader = (FexExtended *)mem->RequestPages(TO_PAGES(sizeof(FexExtended) + 1));
|
||||||
|
memcpy(DriverExtendedHeader, fexE, sizeof(FexExtended));
|
||||||
|
|
||||||
|
DriverFile DrvFile = {
|
||||||
|
.Enabled = true,
|
||||||
|
.BuiltIn = IsBuiltIn,
|
||||||
|
.DriverUID = this->DriverUIDs - 1,
|
||||||
|
.Address = (void *)fex,
|
||||||
|
.ExtendedHeaderAddress = (void *)DriverExtendedHeader,
|
||||||
|
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexE->Driver.InterruptCallback),
|
||||||
|
.MemTrk = mem,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (fexE->Driver.InterruptCallback)
|
||||||
|
{
|
||||||
|
for (uint16_t i = 0; i < sizeof(fexE->Driver.Bind.Interrupt.Vector) / sizeof(fexE->Driver.Bind.Interrupt.Vector[0]); i++)
|
||||||
|
{
|
||||||
|
if (fexE->Driver.Bind.Interrupt.Vector[i] == 0)
|
||||||
|
break;
|
||||||
|
DrvFile.InterruptHook[i] = new DriverInterruptHook(fexE->Driver.Bind.Interrupt.Vector[i], DrvFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KernelCallback KCallback{};
|
||||||
|
KCallback.RawPtr = nullptr;
|
||||||
|
KCallback.Reason = CallbackReason::ConfigurationReason;
|
||||||
|
DriverCode CallbackRet = ((DriverCode(*)(KernelCallback *))((uintptr_t)fexE->Driver.Callback + (uintptr_t)fex))(&KCallback);
|
||||||
|
|
||||||
|
if (CallbackRet != DriverCode::OK)
|
||||||
|
{
|
||||||
|
error("Driver %s returned error %d", fexE->Driver.Name, CallbackRet);
|
||||||
|
delete mem;
|
||||||
|
return CallbackRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
Drivers.push_back(DrvFile);
|
||||||
|
return DriverCode::OK;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown driver type: %d", fexE->Driver.Type);
|
||||||
|
delete mem;
|
||||||
|
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,171 +31,114 @@
|
|||||||
|
|
||||||
namespace Driver
|
namespace Driver
|
||||||
{
|
{
|
||||||
void Driver::MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice)
|
DriverCode Driver::DriverLoadBindPCI(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
|
||||||
{
|
{
|
||||||
debug("Header Type: %d", PCIDevice->HeaderType);
|
FexExtended *DrvExtHdr = (FexExtended *)(DriverAddress + EXTENDED_SECTION_ADDRESS);
|
||||||
switch (PCIDevice->HeaderType)
|
if (IsBuiltIn)
|
||||||
{
|
DrvExtHdr = (FexExtended *)(((BuiltInDriverInfo *)DriverAddress)->ExtendedHeader);
|
||||||
case 0: // PCI Header 0
|
|
||||||
{
|
|
||||||
uint32_t BAR[6] = {0};
|
|
||||||
size_t BARsSize[6] = {0};
|
|
||||||
|
|
||||||
BAR[0] = ((PCI::PCIHeader0 *)PCIDevice)->BAR0;
|
uint16_t SizeOfVendorID = sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) /
|
||||||
BAR[1] = ((PCI::PCIHeader0 *)PCIDevice)->BAR1;
|
sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID[0]);
|
||||||
BAR[2] = ((PCI::PCIHeader0 *)PCIDevice)->BAR2;
|
uint16_t SizeOfDeviceID = sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID) /
|
||||||
BAR[3] = ((PCI::PCIHeader0 *)PCIDevice)->BAR3;
|
sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID[0]);
|
||||||
BAR[4] = ((PCI::PCIHeader0 *)PCIDevice)->BAR4;
|
|
||||||
BAR[5] = ((PCI::PCIHeader0 *)PCIDevice)->BAR5;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
for (uint16_t vID = 0; vID < SizeOfVendorID; vID++)
|
||||||
uintptr_t BAR_Type = BAR[0] & 1;
|
{
|
||||||
uintptr_t BAR_IOBase = BAR[1] & (~3);
|
for (uint16_t dID = 0; dID < SizeOfDeviceID; dID++)
|
||||||
uintptr_t BAR_MemoryBase = BAR[0] & (~15);
|
{
|
||||||
|
if (DrvExtHdr->Driver.Bind.PCI.VendorID[vID] == 0 ||
|
||||||
|
DrvExtHdr->Driver.Bind.PCI.DeviceID[dID] == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
debug("Type: %d; IOBase: %#lx; MemoryBase: %#lx", BAR_Type, BAR_IOBase, BAR_MemoryBase);
|
std::vector<PCI::PCIDeviceHeader *> devices =
|
||||||
#endif
|
PCIManager->FindPCIDevice(DrvExtHdr->Driver.Bind.PCI.VendorID[vID],
|
||||||
|
DrvExtHdr->Driver.Bind.PCI.DeviceID[dID]);
|
||||||
|
if (devices.size() == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* BARs Size */
|
foreach (auto PCIDevice in devices)
|
||||||
for (short i = 0; i < 6; i++)
|
{
|
||||||
{
|
debug("[%ld] VendorID: %#x; DeviceID: %#x",
|
||||||
if (BAR[i] == 0)
|
devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((BAR[i] & 1) == 0) // Memory Base
|
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
||||||
{
|
|
||||||
((PCI::PCIHeader0 *)PCIDevice)->BAR0 = 0xFFFFFFFF;
|
|
||||||
size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR0;
|
|
||||||
((PCI::PCIHeader0 *)PCIDevice)->BAR0 = BAR[i];
|
|
||||||
BARsSize[i] = size & (~15);
|
|
||||||
BARsSize[i] = ~BARsSize[i] + 1;
|
|
||||||
BARsSize[i] = BARsSize[i] & 0xFFFFFFFF;
|
|
||||||
debug("BAR%d %#lx size: %d", i, BAR[i], BARsSize[i]);
|
|
||||||
}
|
|
||||||
else if ((BAR[i] & 1) == 1) // I/O Base
|
|
||||||
{
|
|
||||||
((PCI::PCIHeader0 *)PCIDevice)->BAR1 = 0xFFFFFFFF;
|
|
||||||
size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR1;
|
|
||||||
((PCI::PCIHeader0 *)PCIDevice)->BAR1 = BAR[i];
|
|
||||||
BARsSize[i] = size & (~3);
|
|
||||||
BARsSize[i] = ~BARsSize[i] + 1;
|
|
||||||
BARsSize[i] = BARsSize[i] & 0xFFFF;
|
|
||||||
debug("BAR%d %#lx size: %d", i, BAR[i], BARsSize[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mapping the BARs */
|
BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress;
|
||||||
for (short i = 0; i < 6; i++)
|
Fex *fex = nullptr;
|
||||||
{
|
if (!IsBuiltIn)
|
||||||
if (BAR[i] == 0)
|
{
|
||||||
continue;
|
fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
|
||||||
|
memcpy(fex, (void *)DriverAddress, Size);
|
||||||
|
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fex = (Fex *)bidi->EntryPoint;
|
||||||
|
DriverCode ret = CallDriverEntryPoint(fex, IsBuiltIn);
|
||||||
|
if (ret != DriverCode::OK)
|
||||||
|
{
|
||||||
|
delete mem;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if ((BAR[i] & 1) == 0) // Memory Base
|
if (IsBuiltIn)
|
||||||
{
|
fex = 0x0; /* Addresses are absolute if built-in. */
|
||||||
uintptr_t BARBase = BAR[i] & (~15);
|
|
||||||
size_t BARSize = BARsSize[i];
|
|
||||||
|
|
||||||
debug("Mapping BAR%d %#lx-%#lx", i, BARBase, BARBase + BARSize);
|
FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||||
Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT);
|
debug("Starting driver %s", fexE->Driver.Name);
|
||||||
}
|
|
||||||
else if ((BAR[i] & 1) == 1) // I/O Base
|
|
||||||
{
|
|
||||||
uintptr_t BARBase = BAR[i] & (~3);
|
|
||||||
size_t BARSize = BARsSize[i];
|
|
||||||
|
|
||||||
debug("Mapping BAR%d %#x-%#x", i, BARBase, BARBase + BARSize);
|
PCIManager->MapPCIAddresses(PCIDevice);
|
||||||
Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: // PCI Header 1 (PCI-to-PCI Bridge)
|
|
||||||
{
|
|
||||||
fixme("PCI Header 1 (PCI-to-PCI Bridge) not implemented yet");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: // PCI Header 2 (PCI-to-CardBus Bridge)
|
|
||||||
{
|
|
||||||
fixme("PCI Header 2 (PCI-to-CardBus Bridge) not implemented yet");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
error("Unknown header type %d", PCIDevice->HeaderType);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::DriverLoadBindPCI(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
|
switch (fexE->Driver.Type)
|
||||||
{
|
{
|
||||||
UNUSED(IsElf);
|
case FexDriverType::FexDriverType_Generic:
|
||||||
for (unsigned long Vidx = 0; Vidx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[0]); Vidx++)
|
case FexDriverType::FexDriverType_Display:
|
||||||
{
|
case FexDriverType::FexDriverType_Network:
|
||||||
for (unsigned long Didx = 0; Didx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[0]); Didx++)
|
case FexDriverType::FexDriverType_Storage:
|
||||||
{
|
case FexDriverType::FexDriverType_FileSystem:
|
||||||
if (Vidx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) && Didx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID))
|
case FexDriverType::FexDriverType_Input:
|
||||||
break;
|
case FexDriverType::FexDriverType_Audio:
|
||||||
|
{
|
||||||
|
FexExtended *DriverExtendedHeader = (FexExtended *)mem->RequestPages(TO_PAGES(sizeof(FexExtended) + 1));
|
||||||
|
memcpy(DriverExtendedHeader, fexE, sizeof(FexExtended));
|
||||||
|
|
||||||
if (((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[Vidx] == 0 || ((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[Didx] == 0)
|
DriverFile DrvFile = {
|
||||||
continue;
|
.Enabled = true,
|
||||||
|
.BuiltIn = IsBuiltIn,
|
||||||
|
.DriverUID = this->DriverUIDs - 1,
|
||||||
|
.Address = (void *)fex,
|
||||||
|
.ExtendedHeaderAddress = (void *)DriverExtendedHeader,
|
||||||
|
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexE->Driver.InterruptCallback),
|
||||||
|
.MemTrk = mem,
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<PCI::PCIDeviceHeader *> devices = PCIManager->FindPCIDevice(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[Vidx], ((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[Didx]);
|
if (fexE->Driver.InterruptCallback)
|
||||||
if (devices.size() == 0)
|
DrvFile.InterruptHook[0] = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine), DrvFile);
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (auto PCIDevice in devices)
|
KernelCallback KCallback{};
|
||||||
{
|
KCallback.RawPtr = PCIDevice;
|
||||||
debug("[%ld] VendorID: %#x; DeviceID: %#x", devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
|
KCallback.Reason = CallbackReason::ConfigurationReason;
|
||||||
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
DriverCode CallbackRet = ((DriverCode(*)(KernelCallback *))((uintptr_t)fexE->Driver.Callback + (uintptr_t)fex))(&KCallback);
|
||||||
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
|
|
||||||
memcpy(fex, (void *)DriverAddress, Size);
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
|
||||||
#ifdef DEBUG
|
|
||||||
uint8_t *result = md5File((uint8_t *)fex, Size);
|
|
||||||
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
|
||||||
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
|
||||||
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
|
|
||||||
kfree(result);
|
|
||||||
#endif
|
|
||||||
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI) + 1));
|
|
||||||
|
|
||||||
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
|
if (CallbackRet != DriverCode::OK)
|
||||||
{
|
{
|
||||||
delete mem, mem = nullptr;
|
error("Driver %s returned error %d", fexE->Driver.Name, CallbackRet);
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
delete mem;
|
||||||
}
|
return CallbackRet;
|
||||||
debug("Starting driver %s", fexExtended->Driver.Name);
|
}
|
||||||
|
|
||||||
MapPCIAddresses(PCIDevice);
|
Drivers.push_back(DrvFile);
|
||||||
|
return DriverCode::OK;
|
||||||
switch (fexExtended->Driver.Type)
|
}
|
||||||
{
|
default:
|
||||||
case FexDriverType::FexDriverType_Generic:
|
{
|
||||||
return BindPCIGeneric(mem, fex, PCIDevice);
|
warn("Unknown driver type: %d", fexE->Driver.Type);
|
||||||
case FexDriverType::FexDriverType_Display:
|
delete mem;
|
||||||
return BindPCIDisplay(mem, fex, PCIDevice);
|
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
||||||
case FexDriverType::FexDriverType_Network:
|
}
|
||||||
return BindPCINetwork(mem, fex, PCIDevice);
|
}
|
||||||
case FexDriverType::FexDriverType_Storage:
|
}
|
||||||
return BindPCIStorage(mem, fex, PCIDevice);
|
}
|
||||||
case FexDriverType::FexDriverType_FileSystem:
|
}
|
||||||
return BindPCIFileSystem(mem, fex, PCIDevice);
|
return DriverCode::PCI_DEVICE_NOT_FOUND;
|
||||||
case FexDriverType::FexDriverType_Input:
|
}
|
||||||
return BindPCIInput(mem, fex, PCIDevice);
|
|
||||||
case FexDriverType::FexDriverType_Audio:
|
|
||||||
return BindPCIAudio(mem, fex, PCIDevice);
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
warn("Unknown driver type: %d", fexExtended->Driver.Type);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return DriverCode::PCI_DEVICE_NOT_FOUND;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,9 @@
|
|||||||
|
|
||||||
namespace Driver
|
namespace Driver
|
||||||
{
|
{
|
||||||
DriverCode Driver::DriverLoadBindProcess(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
|
DriverCode Driver::DriverLoadBindProcess(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
|
||||||
{
|
{
|
||||||
fixme("Process driver: %s", ((FexExtended *)DrvExtHdr)->Driver.Name);
|
stub;
|
||||||
UNUSED(Size);
|
return DriverCode::NOT_IMPLEMENTED;
|
||||||
UNUSED(DriverAddress);
|
}
|
||||||
UNUSED(IsElf);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInputFileSystem(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
UNUSED(mem);
|
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInputGeneric(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
UNUSED(mem);
|
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInputInput(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
KernelCallback KCallback{};
|
|
||||||
|
|
||||||
fixme("Input driver: %s", fexExtended->Driver.Name);
|
|
||||||
KCallback.RawPtr = nullptr;
|
|
||||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet != DriverReturnCode::OK)
|
|
||||||
{
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Input driver: %s", fexExtended->Driver.Name);
|
|
||||||
|
|
||||||
DriverFile DrvFile = {
|
|
||||||
.Enabled = true,
|
|
||||||
.DriverUID = this->DriverUIDs - 1,
|
|
||||||
.Address = (void *)fex,
|
|
||||||
.MemTrk = mem,
|
|
||||||
};
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInputNetwork(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
UNUSED(mem);
|
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInputStorage(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
UNUSED(mem);
|
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInterruptAudio(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Audio driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInterruptDisplay(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Display driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInterruptFileSystem(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInterruptGeneric(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Generic driver: %s", fexExtended->Driver.Name);
|
|
||||||
DriverFile DrvFile = {
|
|
||||||
.Enabled = true,
|
|
||||||
.DriverUID = this->DriverUIDs - 1,
|
|
||||||
.Address = (void *)fex,
|
|
||||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
|
|
||||||
.MemTrk = mem,
|
|
||||||
};
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInterruptInput(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
debug("Searching for conflicting drivers...");
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if ((fe->Driver.TypeFlags & FexDriverInputTypes_Mouse &&
|
|
||||||
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Mouse) ||
|
|
||||||
(fe->Driver.TypeFlags & FexDriverInputTypes_Keyboard &&
|
|
||||||
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Keyboard))
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if ((fe->Driver.TypeFlags & FexDriverInputTypes_Mouse &&
|
|
||||||
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Mouse) ||
|
|
||||||
(fe->Driver.TypeFlags & FexDriverInputTypes_Keyboard &&
|
|
||||||
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Keyboard))
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverFile DrvFile = {
|
|
||||||
.Enabled = true,
|
|
||||||
.DriverUID = this->DriverUIDs - 1,
|
|
||||||
.Address = (void *)fex,
|
|
||||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
|
|
||||||
.MemTrk = mem,
|
|
||||||
};
|
|
||||||
if (fexExtended->Driver.InterruptCallback)
|
|
||||||
{
|
|
||||||
for (unsigned long i = 0; i < sizeof(fexExtended->Driver.Bind.Interrupt.Vector) / sizeof(fexExtended->Driver.Bind.Interrupt.Vector[0]); i++)
|
|
||||||
{
|
|
||||||
if (fexExtended->Driver.Bind.Interrupt.Vector[i] == 0)
|
|
||||||
break;
|
|
||||||
DrvFile.InterruptHook[i] = new DriverInterruptHook(fexExtended->Driver.Bind.Interrupt.Vector[i], DrvFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelCallback KCallback{};
|
|
||||||
KCallback.RawPtr = nullptr;
|
|
||||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
|
|
||||||
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet != DriverReturnCode::OK)
|
|
||||||
{
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInterruptNetwork(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Network driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInterruptStorage(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverFile DrvFile = {
|
|
||||||
.Enabled = true,
|
|
||||||
.DriverUID = this->DriverUIDs - 1,
|
|
||||||
.Address = (void *)fex,
|
|
||||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
|
|
||||||
.MemTrk = mem,
|
|
||||||
};
|
|
||||||
if (fexExtended->Driver.InterruptCallback)
|
|
||||||
{
|
|
||||||
for (unsigned long i = 0; i < sizeof(fexExtended->Driver.Bind.Interrupt.Vector) / sizeof(fexExtended->Driver.Bind.Interrupt.Vector[0]); i++)
|
|
||||||
{
|
|
||||||
if (fexExtended->Driver.Bind.Interrupt.Vector[i] == 0)
|
|
||||||
break;
|
|
||||||
DrvFile.InterruptHook[i] = new DriverInterruptHook(fexExtended->Driver.Bind.Interrupt.Vector[i], DrvFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelCallback KCallback{};
|
|
||||||
KCallback.RawPtr = nullptr;
|
|
||||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
|
|
||||||
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet != DriverReturnCode::OK)
|
|
||||||
{
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindPCIAudio(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverFile DrvFile = {
|
|
||||||
.Enabled = true,
|
|
||||||
.DriverUID = this->DriverUIDs - 1,
|
|
||||||
.Address = (void *)fex,
|
|
||||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
|
|
||||||
.MemTrk = mem,
|
|
||||||
};
|
|
||||||
if (fexExtended->Driver.InterruptCallback)
|
|
||||||
DrvFile.InterruptHook[0] = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine), DrvFile);
|
|
||||||
|
|
||||||
KernelCallback KCallback{};
|
|
||||||
KCallback.RawPtr = PCIDevice;
|
|
||||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
|
|
||||||
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet == DriverReturnCode::OK)
|
|
||||||
trace("Device found for driver: %s", fexExtended->Driver.Name);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindPCIDisplay(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
UNUSED(PCIDevice);
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Display driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindPCIFileSystem(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
UNUSED(PCIDevice);
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindPCIGeneric(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
UNUSED(PCIDevice);
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Generic driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindPCIInput(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
UNUSED(PCIDevice);
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Input driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindPCINetwork(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverFile DrvFile = {
|
|
||||||
.Enabled = true,
|
|
||||||
.DriverUID = this->DriverUIDs - 1,
|
|
||||||
.Address = (void *)fex,
|
|
||||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
|
|
||||||
.MemTrk = mem,
|
|
||||||
};
|
|
||||||
if (fexExtended->Driver.InterruptCallback)
|
|
||||||
DrvFile.InterruptHook[0] = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine), DrvFile);
|
|
||||||
|
|
||||||
KernelCallback KCallback{};
|
|
||||||
KCallback.RawPtr = PCIDevice;
|
|
||||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
|
|
||||||
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet == DriverReturnCode::OK)
|
|
||||||
trace("Device found for driver: %s", fexExtended->Driver.Name);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindPCIStorage(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
std::vector<size_t> DriversToRemove = std::vector<size_t>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv.DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverFile DrvFile = {
|
|
||||||
.Enabled = true,
|
|
||||||
.DriverUID = this->DriverUIDs - 1,
|
|
||||||
.Address = (void *)fex,
|
|
||||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
|
|
||||||
.MemTrk = mem,
|
|
||||||
};
|
|
||||||
if (fexExtended->Driver.InterruptCallback)
|
|
||||||
DrvFile.InterruptHook[0] = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine), DrvFile);
|
|
||||||
|
|
||||||
KernelCallback KCallback{};
|
|
||||||
KCallback.RawPtr = PCIDevice;
|
|
||||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
|
|
||||||
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet == DriverReturnCode::OK)
|
|
||||||
trace("Device found for driver: %s", fexExtended->Driver.Name);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindProcessAudio(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
UNUSED(mem);
|
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindProcessDisplay(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
UNUSED(mem);
|
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindProcessFileSystem(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
UNUSED(mem);
|
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindProcessGeneric(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
UNUSED(mem);
|
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindProcessInput(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
UNUSED(mem);
|
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindProcessNetwork(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
UNUSED(mem);
|
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindProcessStorage(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
UNUSED(mem);
|
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -32,70 +32,70 @@
|
|||||||
|
|
||||||
namespace Time
|
namespace Time
|
||||||
{
|
{
|
||||||
bool HighPrecisionEventTimer::Sleep(uint64_t Duration, Units Unit)
|
bool HighPrecisionEventTimer::Sleep(size_t Duration, Units Unit)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
size_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
||||||
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
|
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
|
||||||
CPU::Pause();
|
CPU::Pause();
|
||||||
return true;
|
return true;
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
uint64_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
size_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
||||||
while (mminl(&((HPET *)hpet)->MainCounterValue) < Target)
|
while (mminl(&((HPET *)hpet)->MainCounterValue) < Target)
|
||||||
CPU::Pause();
|
CPU::Pause();
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t HighPrecisionEventTimer::GetCounter()
|
size_t HighPrecisionEventTimer::GetCounter()
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
return mminq(&((HPET *)hpet)->MainCounterValue);
|
return mminq(&((HPET *)hpet)->MainCounterValue);
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
return mminl(&((HPET *)hpet)->MainCounterValue);
|
return mminl(&((HPET *)hpet)->MainCounterValue);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t HighPrecisionEventTimer::CalculateTarget(uint64_t Target, Units Unit)
|
size_t HighPrecisionEventTimer::CalculateTarget(size_t Target, Units Unit)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
return mminq(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
|
return mminq(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
return mminl(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
|
return mminl(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation()
|
size_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation()
|
||||||
{
|
{
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
uint64_t Subtraction = this->GetCounter() - this->ClassCreationTime;
|
size_t Subtraction = this->GetCounter() - this->ClassCreationTime;
|
||||||
if (Subtraction <= 0 || this->clk <= 0)
|
if (Subtraction <= 0 || this->clk <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
return Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds));
|
return Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
HighPrecisionEventTimer::HighPrecisionEventTimer(void *hpet)
|
HighPrecisionEventTimer::HighPrecisionEventTimer(void *hpet)
|
||||||
{
|
{
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
ACPI::ACPI::HPETHeader *HPET_HDR = (ACPI::ACPI::HPETHeader *)hpet;
|
ACPI::ACPI::HPETHeader *HPET_HDR = (ACPI::ACPI::HPETHeader *)hpet;
|
||||||
Memory::Virtual().Remap((void *)HPET_HDR->Address.Address,
|
Memory::Virtual().Remap((void *)HPET_HDR->Address.Address,
|
||||||
(void *)HPET_HDR->Address.Address,
|
(void *)HPET_HDR->Address.Address,
|
||||||
Memory::PTFlag::RW | Memory::PTFlag::PCD);
|
Memory::PTFlag::RW | Memory::PTFlag::PCD);
|
||||||
this->hpet = (HPET *)HPET_HDR->Address.Address;
|
this->hpet = (HPET *)HPET_HDR->Address.Address;
|
||||||
trace("%s timer is at address %016p", HPET_HDR->Header.OEMID, (void *)HPET_HDR->Address.Address);
|
trace("%s timer is at address %016p", HPET_HDR->Header.OEMID, (void *)HPET_HDR->Address.Address);
|
||||||
clk = s_cst(uint32_t, (uint64_t)this->hpet->GeneralCapabilities >> 32);
|
clk = s_cst(uint32_t, (uint64_t)this->hpet->GeneralCapabilities >> 32);
|
||||||
#ifdef a64
|
#ifdef a64
|
||||||
mmoutq(&this->hpet->GeneralConfiguration, 0);
|
mmoutq(&this->hpet->GeneralConfiguration, 0);
|
||||||
mmoutq(&this->hpet->MainCounterValue, 0);
|
mmoutq(&this->hpet->MainCounterValue, 0);
|
||||||
mmoutq(&this->hpet->GeneralConfiguration, 1);
|
mmoutq(&this->hpet->GeneralConfiguration, 1);
|
||||||
#else
|
#else
|
||||||
mmoutl(&this->hpet->GeneralConfiguration, 0);
|
mmoutl(&this->hpet->GeneralConfiguration, 0);
|
||||||
mmoutl(&this->hpet->MainCounterValue, 0);
|
mmoutl(&this->hpet->MainCounterValue, 0);
|
||||||
mmoutl(&this->hpet->GeneralConfiguration, 1);
|
mmoutl(&this->hpet->GeneralConfiguration, 1);
|
||||||
#endif
|
#endif
|
||||||
ClassCreationTime = this->GetCounter();
|
ClassCreationTime = this->GetCounter();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,51 +31,51 @@
|
|||||||
|
|
||||||
namespace Time
|
namespace Time
|
||||||
{
|
{
|
||||||
bool TimeStampCounter::Sleep(uint64_t Duration, Units Unit)
|
bool TimeStampCounter::Sleep(size_t Duration, Units Unit)
|
||||||
{
|
{
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
uint64_t Target = this->GetCounter() + (Duration * ConvertUnit(Unit)) / this->clk;
|
size_t Target = this->GetCounter() + (Duration * ConvertUnit(Unit)) / this->clk;
|
||||||
while (this->GetCounter() < Target)
|
while (this->GetCounter() < Target)
|
||||||
CPU::Pause();
|
CPU::Pause();
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t TimeStampCounter::GetCounter()
|
size_t TimeStampCounter::GetCounter()
|
||||||
{
|
{
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
return CPU::Counter();
|
return CPU::Counter();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t TimeStampCounter::CalculateTarget(uint64_t Target, Units Unit)
|
size_t TimeStampCounter::CalculateTarget(size_t Target, Units Unit)
|
||||||
{
|
{
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
return this->GetCounter() + (Target * ConvertUnit(Unit)) / this->clk;
|
return this->GetCounter() + (Target * ConvertUnit(Unit)) / this->clk;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t TimeStampCounter::GetNanosecondsSinceClassCreation()
|
size_t TimeStampCounter::GetNanosecondsSinceClassCreation()
|
||||||
{
|
{
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
return (this->GetCounter() - this->ClassCreationTime) / this->clk;
|
return (this->GetCounter() - this->ClassCreationTime) / this->clk;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeStampCounter::TimeStampCounter()
|
TimeStampCounter::TimeStampCounter()
|
||||||
{
|
{
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
fixme(""); // FIXME: This is not a good way to measure the clock speed
|
fixme(""); // FIXME: This is not a good way to measure the clock speed
|
||||||
uint64_t Start = CPU::Counter();
|
size_t Start = CPU::Counter();
|
||||||
TimeManager->Sleep(1, Units::Milliseconds);
|
TimeManager->Sleep(1, Units::Milliseconds);
|
||||||
uint64_t End = CPU::Counter();
|
size_t End = CPU::Counter();
|
||||||
|
|
||||||
this->clk = End - Start;
|
this->clk = End - Start;
|
||||||
this->ClassCreationTime = this->GetCounter();
|
this->ClassCreationTime = this->GetCounter();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeStampCounter::~TimeStampCounter()
|
TimeStampCounter::~TimeStampCounter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,184 +32,184 @@
|
|||||||
|
|
||||||
namespace Time
|
namespace Time
|
||||||
{
|
{
|
||||||
bool time::Sleep(uint64_t Duration, Units Unit)
|
bool time::Sleep(size_t Duration, Units Unit)
|
||||||
{
|
{
|
||||||
switch (ActiveTimer)
|
switch (ActiveTimer)
|
||||||
{
|
{
|
||||||
case NONE:
|
case NONE:
|
||||||
error("No timer is active");
|
error("No timer is active");
|
||||||
return false;
|
return false;
|
||||||
case RTC:
|
case RTC:
|
||||||
fixme("RTC sleep not implemented");
|
fixme("RTC sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case PIT:
|
case PIT:
|
||||||
fixme("PIT sleep not implemented");
|
fixme("PIT sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case HPET:
|
case HPET:
|
||||||
return this->hpet->Sleep(Duration, Unit);
|
return this->hpet->Sleep(Duration, Unit);
|
||||||
case ACPI:
|
case ACPI:
|
||||||
fixme("ACPI sleep not implemented");
|
fixme("ACPI sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case APIC:
|
case APIC:
|
||||||
fixme("APIC sleep not implemented");
|
fixme("APIC sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case TSC:
|
case TSC:
|
||||||
return this->tsc->Sleep(Duration, Unit);
|
return this->tsc->Sleep(Duration, Unit);
|
||||||
default:
|
default:
|
||||||
error("Unknown timer");
|
error("Unknown timer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t time::GetCounter()
|
size_t time::GetCounter()
|
||||||
{
|
{
|
||||||
switch (ActiveTimer)
|
switch (ActiveTimer)
|
||||||
{
|
{
|
||||||
case NONE:
|
case NONE:
|
||||||
error("No timer is active");
|
error("No timer is active");
|
||||||
return false;
|
return false;
|
||||||
case RTC:
|
case RTC:
|
||||||
fixme("RTC sleep not implemented");
|
fixme("RTC sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case PIT:
|
case PIT:
|
||||||
fixme("PIT sleep not implemented");
|
fixme("PIT sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case HPET:
|
case HPET:
|
||||||
return this->hpet->GetCounter();
|
return this->hpet->GetCounter();
|
||||||
case ACPI:
|
case ACPI:
|
||||||
fixme("ACPI sleep not implemented");
|
fixme("ACPI sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case APIC:
|
case APIC:
|
||||||
fixme("APIC sleep not implemented");
|
fixme("APIC sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case TSC:
|
case TSC:
|
||||||
return this->tsc->GetCounter();
|
return this->tsc->GetCounter();
|
||||||
default:
|
default:
|
||||||
error("Unknown timer");
|
error("Unknown timer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t time::CalculateTarget(uint64_t Target, Units Unit)
|
size_t time::CalculateTarget(size_t Target, Units Unit)
|
||||||
{
|
{
|
||||||
switch (ActiveTimer)
|
switch (ActiveTimer)
|
||||||
{
|
{
|
||||||
case NONE:
|
case NONE:
|
||||||
error("No timer is active");
|
error("No timer is active");
|
||||||
return false;
|
return false;
|
||||||
case RTC:
|
case RTC:
|
||||||
fixme("RTC sleep not implemented");
|
fixme("RTC sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case PIT:
|
case PIT:
|
||||||
fixme("PIT sleep not implemented");
|
fixme("PIT sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case HPET:
|
case HPET:
|
||||||
return this->hpet->CalculateTarget(Target, Unit);
|
return this->hpet->CalculateTarget(Target, Unit);
|
||||||
case ACPI:
|
case ACPI:
|
||||||
fixme("ACPI sleep not implemented");
|
fixme("ACPI sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case APIC:
|
case APIC:
|
||||||
fixme("APIC sleep not implemented");
|
fixme("APIC sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case TSC:
|
case TSC:
|
||||||
return this->tsc->CalculateTarget(Target, Unit);
|
return this->tsc->CalculateTarget(Target, Unit);
|
||||||
default:
|
default:
|
||||||
error("Unknown timer");
|
error("Unknown timer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t time::GetNanosecondsSinceClassCreation()
|
size_t time::GetNanosecondsSinceClassCreation()
|
||||||
{
|
{
|
||||||
switch (ActiveTimer)
|
switch (ActiveTimer)
|
||||||
{
|
{
|
||||||
case NONE:
|
case NONE:
|
||||||
error("No timer is active");
|
error("No timer is active");
|
||||||
return false;
|
return false;
|
||||||
case RTC:
|
case RTC:
|
||||||
fixme("RTC sleep not implemented");
|
fixme("RTC sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case PIT:
|
case PIT:
|
||||||
fixme("PIT sleep not implemented");
|
fixme("PIT sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case HPET:
|
case HPET:
|
||||||
return this->hpet->GetNanosecondsSinceClassCreation();
|
return this->hpet->GetNanosecondsSinceClassCreation();
|
||||||
case ACPI:
|
case ACPI:
|
||||||
fixme("ACPI sleep not implemented");
|
fixme("ACPI sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case APIC:
|
case APIC:
|
||||||
fixme("APIC sleep not implemented");
|
fixme("APIC sleep not implemented");
|
||||||
return false;
|
return false;
|
||||||
case TSC:
|
case TSC:
|
||||||
return this->tsc->GetNanosecondsSinceClassCreation();
|
return this->tsc->GetNanosecondsSinceClassCreation();
|
||||||
default:
|
default:
|
||||||
error("Unknown timer");
|
error("Unknown timer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void time::FindTimers(void *acpi)
|
void time::FindTimers(void *acpi)
|
||||||
{
|
{
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
/* TODO: RTC check */
|
/* TODO: RTC check */
|
||||||
/* TODO: PIT check */
|
/* TODO: PIT check */
|
||||||
|
|
||||||
if (acpi)
|
if (acpi)
|
||||||
{
|
{
|
||||||
if (((ACPI::ACPI *)acpi)->HPET)
|
if (((ACPI::ACPI *)acpi)->HPET)
|
||||||
{
|
{
|
||||||
hpet = new HighPrecisionEventTimer(((ACPI::ACPI *)acpi)->HPET);
|
hpet = new HighPrecisionEventTimer(((ACPI::ACPI *)acpi)->HPET);
|
||||||
ActiveTimer = HPET;
|
ActiveTimer = HPET;
|
||||||
SupportedTimers |= HPET;
|
SupportedTimers |= HPET;
|
||||||
KPrint("\e11FF11HPET found");
|
KPrint("\e11FF11HPET found");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
KPrint("\eFF2200HPET not found");
|
KPrint("\eFF2200HPET not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: ACPI check */
|
/* TODO: ACPI check */
|
||||||
/* TODO: APIC check */
|
/* TODO: APIC check */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
KPrint("\eFF2200ACPI not found");
|
KPrint("\eFF2200ACPI not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TSCInvariant = false;
|
bool TSCInvariant = false;
|
||||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
||||||
{
|
{
|
||||||
CPU::x86::AMD::CPUID0x80000007 cpuid80000007;
|
CPU::x86::AMD::CPUID0x80000007 cpuid80000007;
|
||||||
cpuid80000007.Get();
|
cpuid80000007.Get();
|
||||||
if (cpuid80000007.EDX.TscInvariant)
|
if (cpuid80000007.EDX.TscInvariant)
|
||||||
TSCInvariant = true;
|
TSCInvariant = true;
|
||||||
}
|
}
|
||||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
||||||
{
|
{
|
||||||
// TODO: Intel 0x80000007
|
// TODO: Intel 0x80000007
|
||||||
CPU::x86::AMD::CPUID0x80000007 cpuid80000007;
|
CPU::x86::AMD::CPUID0x80000007 cpuid80000007;
|
||||||
cpuid80000007.Get();
|
cpuid80000007.Get();
|
||||||
if (cpuid80000007.EDX.TscInvariant)
|
if (cpuid80000007.EDX.TscInvariant)
|
||||||
TSCInvariant = true;
|
TSCInvariant = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TSCInvariant)
|
if (TSCInvariant)
|
||||||
{
|
{
|
||||||
tsc = new TimeStampCounter;
|
tsc = new TimeStampCounter;
|
||||||
// FIXME: ActiveTimer = TSC;
|
// FIXME: ActiveTimer = TSC;
|
||||||
SupportedTimers |= TSC;
|
SupportedTimers |= TSC;
|
||||||
KPrint("\e11FF11Invariant TSC found");
|
KPrint("\e11FF11Invariant TSC found");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
KPrint("\eFF2200TSC is not invariant");
|
KPrint("\eFF2200TSC is not invariant");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
time::time()
|
time::time()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
time::~time()
|
time::~time()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
646
DAPI.hpp
646
DAPI.hpp
@ -46,386 +46,386 @@
|
|||||||
|
|
||||||
enum DriverReturnCode
|
enum DriverReturnCode
|
||||||
{
|
{
|
||||||
ERROR,
|
ERROR,
|
||||||
OK,
|
OK,
|
||||||
NOT_IMPLEMENTED,
|
NOT_IMPLEMENTED,
|
||||||
NOT_FOUND,
|
NOT_FOUND,
|
||||||
NOT_READY,
|
NOT_READY,
|
||||||
NOT_AVAILABLE,
|
NOT_AVAILABLE,
|
||||||
NOT_AUTHORIZED,
|
NOT_AUTHORIZED,
|
||||||
NOT_VALID,
|
NOT_VALID,
|
||||||
NOT_ACCEPTED,
|
NOT_ACCEPTED,
|
||||||
INVALID_PCI_BAR,
|
INVALID_PCI_BAR,
|
||||||
INVALID_KERNEL_API,
|
INVALID_KERNEL_API,
|
||||||
INVALID_MEMORY_ALLOCATION,
|
INVALID_MEMORY_ALLOCATION,
|
||||||
INVALID_DATA,
|
INVALID_DATA,
|
||||||
DEVICE_NOT_SUPPORTED,
|
DEVICE_NOT_SUPPORTED,
|
||||||
SYSTEM_NOT_SUPPORTED,
|
SYSTEM_NOT_SUPPORTED,
|
||||||
KERNEL_API_VERSION_NOT_SUPPORTED,
|
KERNEL_API_VERSION_NOT_SUPPORTED,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DriverBindType
|
enum DriverBindType
|
||||||
{
|
{
|
||||||
BIND_NULL,
|
BIND_NULL,
|
||||||
BIND_INTERRUPT,
|
BIND_INTERRUPT,
|
||||||
BIND_PROCESS,
|
BIND_PROCESS,
|
||||||
BIND_PCI,
|
BIND_PCI,
|
||||||
BIND_INPUT
|
BIND_INPUT
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KernelAPI
|
struct KernelAPI
|
||||||
{
|
{
|
||||||
struct KAPIVersion
|
struct KAPIVersion
|
||||||
{
|
{
|
||||||
int Major;
|
int Major;
|
||||||
int Minor;
|
int Minor;
|
||||||
int Patch;
|
int Patch;
|
||||||
} Version;
|
} Version;
|
||||||
|
|
||||||
struct KAPIInfo
|
struct KAPIInfo
|
||||||
{
|
{
|
||||||
unsigned long Offset;
|
unsigned long Offset;
|
||||||
unsigned long DriverUID;
|
unsigned int DriverUID;
|
||||||
char KernelDebug;
|
char KernelDebug;
|
||||||
} Info;
|
} Info;
|
||||||
|
|
||||||
struct KAPIMemory
|
struct KAPIMemory
|
||||||
{
|
{
|
||||||
unsigned long PageSize;
|
unsigned long PageSize;
|
||||||
void *(*RequestPage)(unsigned long Size);
|
void *(*RequestPage)(unsigned long Size);
|
||||||
void (*FreePage)(void *Page, unsigned long Size);
|
void (*FreePage)(void *Page, unsigned long Size);
|
||||||
void (*Map)(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags);
|
void (*Map)(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags);
|
||||||
void (*Unmap)(void *VirtualAddress);
|
void (*Unmap)(void *VirtualAddress);
|
||||||
} Memory;
|
} Memory;
|
||||||
|
|
||||||
struct KAPIPCI
|
struct KAPIPCI
|
||||||
{
|
{
|
||||||
char *(*GetDeviceName)(unsigned int VendorID, unsigned int DeviceID);
|
char *(*GetDeviceName)(unsigned int VendorID, unsigned int DeviceID);
|
||||||
} PCI;
|
} PCI;
|
||||||
|
|
||||||
struct KAPIUtilities
|
struct KAPIUtilities
|
||||||
{
|
{
|
||||||
void (*DebugPrint)(char *String, unsigned long DriverUID);
|
void (*DebugPrint)(char *String, unsigned long DriverUID);
|
||||||
void (*DisplayPrint)(char *Value);
|
void (*DisplayPrint)(char *Value);
|
||||||
void *(*memcpy)(void *Destination, void *Source, unsigned long Size);
|
void *(*memcpy)(void *Destination, void *Source, unsigned long Size);
|
||||||
void *(*memset)(void *Destination, int Value, unsigned long Size);
|
void *(*memset)(void *Destination, int Value, unsigned long Size);
|
||||||
void (*Sleep)(unsigned long Milliseconds);
|
void (*Sleep)(unsigned long Milliseconds);
|
||||||
int (*sprintf)(char *Buffer, const char *Format, ...);
|
int (*sprintf)(char *Buffer, const char *Format, ...);
|
||||||
} Util;
|
} Util;
|
||||||
|
|
||||||
struct KAPIDriverTalk
|
struct KAPIDriverTalk
|
||||||
{
|
{
|
||||||
/** @brief Connects to the network manager */
|
/** @brief Connects to the network manager */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
void (*SendPacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
|
void (*SendPacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
|
||||||
void (*ReceivePacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
|
void (*ReceivePacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size);
|
||||||
} Network;
|
} Network;
|
||||||
|
|
||||||
/** @brief Connects to the disk manager */
|
/** @brief Connects to the disk manager */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
void (*ReadSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port);
|
void (*ReadSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port);
|
||||||
void (*WriteSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port);
|
void (*WriteSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port);
|
||||||
} AHCI;
|
} AHCI;
|
||||||
} Disk;
|
} Disk;
|
||||||
} Command;
|
} Command;
|
||||||
|
|
||||||
struct KAPIDisplay
|
struct KAPIDisplay
|
||||||
{
|
{
|
||||||
unsigned int (*GetWidth)(void);
|
unsigned int (*GetWidth)(void);
|
||||||
unsigned int (*GetHeight)(void);
|
unsigned int (*GetHeight)(void);
|
||||||
/* TODO: Add more */
|
/* TODO: Add more */
|
||||||
} Display;
|
} Display;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
enum CallbackReason
|
enum CallbackReason
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @brief This is used to detect memory corruption, not used.
|
* @brief This is used to detect memory corruption, not used.
|
||||||
*/
|
*/
|
||||||
UnknownReason,
|
UnknownReason,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is called once the kernel is ready to use the driver and call @see ConfigurationReason .
|
* @brief This is called once the kernel is ready to use the driver and call @see ConfigurationReason .
|
||||||
*/
|
*/
|
||||||
AcknowledgeReason,
|
AcknowledgeReason,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is used after the driver is loaded and the kernel is ready to use the driver.
|
* @brief This is used after the driver is loaded and the kernel is ready to use the driver.
|
||||||
*
|
*
|
||||||
* For PCI drivers, @see RawPtr will be the PCI device address.
|
* For PCI drivers, @see RawPtr will be the PCI device address.
|
||||||
*/
|
*/
|
||||||
ConfigurationReason,
|
ConfigurationReason,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is used when the kernel wants to stop the driver.
|
* @brief This is used when the kernel wants to stop the driver.
|
||||||
*
|
*
|
||||||
* The memory allocated by the driver will be freed automatically.
|
* The memory allocated by the driver will be freed automatically.
|
||||||
*/
|
*/
|
||||||
StopReason,
|
StopReason,
|
||||||
|
|
||||||
ProcessReason,
|
ProcessReason,
|
||||||
InputReason,
|
InputReason,
|
||||||
|
|
||||||
/* Kernel reserved callbacks. */
|
/* Kernel reserved callbacks. */
|
||||||
/* ------------------------------------------------------- */
|
/* ------------------------------------------------------- */
|
||||||
/* Driver callbacks for basic usage. */
|
/* Driver callbacks for basic usage. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is used when the kernel sends data.
|
* @brief This is used when the kernel sends data.
|
||||||
*
|
*
|
||||||
* - Network
|
* - Network
|
||||||
* - Packet
|
* - Packet
|
||||||
* - Audio
|
* - Audio
|
||||||
* - PCM Data
|
* - PCM Data
|
||||||
*/
|
*/
|
||||||
SendReason,
|
SendReason,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is used when the kernel wants to receive data.
|
* @brief This is used when the kernel wants to receive data.
|
||||||
* Currently not used.
|
* Currently not used.
|
||||||
*/
|
*/
|
||||||
ReceiveReason,
|
ReceiveReason,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is used to adjust driver settings.
|
* @brief This is used to adjust driver settings.
|
||||||
*
|
*
|
||||||
* - Audio
|
* - Audio
|
||||||
* - Volume
|
* - Volume
|
||||||
* - PCM Encoding
|
* - PCM Encoding
|
||||||
*/
|
*/
|
||||||
AdjustReason,
|
AdjustReason,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is used when the kernel wants to fetch information about the driver.
|
* @brief This is used when the kernel wants to fetch information about the driver.
|
||||||
*
|
*
|
||||||
* - Input
|
* - Input
|
||||||
* - Mouse
|
* - Mouse
|
||||||
* - Position
|
* - Position
|
||||||
* - Buttons
|
* - Buttons
|
||||||
* - Keyboard
|
* - Keyboard
|
||||||
* - Key
|
* - Key
|
||||||
*/
|
*/
|
||||||
FetchReason,
|
FetchReason,
|
||||||
};
|
};
|
||||||
|
|
||||||
union KernelCallback
|
union KernelCallback
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
CallbackReason Reason;
|
CallbackReason Reason;
|
||||||
void *RawPtr;
|
void *RawPtr;
|
||||||
unsigned long RawData;
|
unsigned long RawData;
|
||||||
|
|
||||||
/** @brief When the kernel wants to send a packet. */
|
/** @brief When the kernel wants to send a packet. */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned char *Data;
|
unsigned char *Data;
|
||||||
unsigned long Length;
|
unsigned long Length;
|
||||||
} Send;
|
} Send;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
char Name[128];
|
char Name[128];
|
||||||
unsigned long MAC;
|
unsigned long MAC;
|
||||||
} Fetch;
|
} Fetch;
|
||||||
} NetworkCallback;
|
} NetworkCallback;
|
||||||
|
|
||||||
/** @brief When the kernel wants to write to disk. */
|
/** @brief When the kernel wants to write to disk. */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned long Sector;
|
unsigned long Sector;
|
||||||
unsigned long SectorCount;
|
unsigned long SectorCount;
|
||||||
unsigned char Port;
|
unsigned char Port;
|
||||||
unsigned char *Buffer;
|
unsigned char *Buffer;
|
||||||
bool Write;
|
bool Write;
|
||||||
} RW;
|
} RW;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned char Ports;
|
unsigned char Ports;
|
||||||
int BytesPerSector;
|
int BytesPerSector;
|
||||||
} Fetch;
|
} Fetch;
|
||||||
} DiskCallback;
|
} DiskCallback;
|
||||||
|
|
||||||
/** @brief When the kernel wants to get mouse position / keyboard key */
|
/** @brief When the kernel wants to get mouse position / keyboard key */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned long X;
|
unsigned long X;
|
||||||
unsigned long Y;
|
unsigned long Y;
|
||||||
unsigned long Z;
|
unsigned long Z;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool Left;
|
bool Left;
|
||||||
bool Right;
|
bool Right;
|
||||||
bool Middle;
|
bool Middle;
|
||||||
} Buttons;
|
} Buttons;
|
||||||
} Mouse;
|
} Mouse;
|
||||||
} InputCallback;
|
} InputCallback;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool _Volume;
|
bool _Volume;
|
||||||
bool _Encoding;
|
bool _Encoding;
|
||||||
bool _SampleRate;
|
bool _SampleRate;
|
||||||
bool _Channels;
|
bool _Channels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adjust the volume.
|
* @brief Adjust the volume.
|
||||||
*
|
*
|
||||||
* 0 - 100
|
* 0 - 100
|
||||||
*/
|
*/
|
||||||
unsigned char Volume;
|
unsigned char Volume;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adjust the encoding.
|
* @brief Adjust the encoding.
|
||||||
*
|
*
|
||||||
* 0 - None, use default
|
* 0 - None, use default
|
||||||
*
|
*
|
||||||
* 1 - Signed PCM 8-bit
|
* 1 - Signed PCM 8-bit
|
||||||
* 2 - Unsigned PCM 8-bit
|
* 2 - Unsigned PCM 8-bit
|
||||||
*
|
*
|
||||||
* 3 - Signed PCM 16-bit Little Endian
|
* 3 - Signed PCM 16-bit Little Endian
|
||||||
* 4 - Signed PCM 20-bit Little Endian
|
* 4 - Signed PCM 20-bit Little Endian
|
||||||
* 5 - Signed PCM 24-bit Little Endian
|
* 5 - Signed PCM 24-bit Little Endian
|
||||||
* 6 - Signed PCM 32-bit Little Endian
|
* 6 - Signed PCM 32-bit Little Endian
|
||||||
*
|
*
|
||||||
* 7 - Unsigned PCM 16-bit Little Endian
|
* 7 - Unsigned PCM 16-bit Little Endian
|
||||||
* 8 - Unsigned PCM 20-bit Little Endian
|
* 8 - Unsigned PCM 20-bit Little Endian
|
||||||
* 9 - Unsigned PCM 24-bit Little Endian
|
* 9 - Unsigned PCM 24-bit Little Endian
|
||||||
* 10 - Unsigned PCM 32-bit Little Endian
|
* 10 - Unsigned PCM 32-bit Little Endian
|
||||||
*
|
*
|
||||||
* 11 - Signed PCM 16-bit Big Endian
|
* 11 - Signed PCM 16-bit Big Endian
|
||||||
* 12 - Signed PCM 20-bit Big Endian
|
* 12 - Signed PCM 20-bit Big Endian
|
||||||
* 13 - Signed PCM 24-bit Big Endian
|
* 13 - Signed PCM 24-bit Big Endian
|
||||||
* 14 - Signed PCM 32-bit Big Endian
|
* 14 - Signed PCM 32-bit Big Endian
|
||||||
*
|
*
|
||||||
* 15 - Unsigned PCM 16-bit Big Endian
|
* 15 - Unsigned PCM 16-bit Big Endian
|
||||||
* 16 - Unsigned PCM 20-bit Big Endian
|
* 16 - Unsigned PCM 20-bit Big Endian
|
||||||
* 17 - Unsigned PCM 24-bit Big Endian
|
* 17 - Unsigned PCM 24-bit Big Endian
|
||||||
* 18 - Unsigned PCM 32-bit Big Endian
|
* 18 - Unsigned PCM 32-bit Big Endian
|
||||||
*
|
*
|
||||||
* 19 - Float PCM 32-bit Little Endian
|
* 19 - Float PCM 32-bit Little Endian
|
||||||
* 20 - Float PCM 64-bit Little Endian
|
* 20 - Float PCM 64-bit Little Endian
|
||||||
*
|
*
|
||||||
* 21 - Float PCM 32-bit Big Endian
|
* 21 - Float PCM 32-bit Big Endian
|
||||||
* 22 - Float PCM 64-bit Big Endian
|
* 22 - Float PCM 64-bit Big Endian
|
||||||
*
|
*
|
||||||
* 23 - PCM A-law
|
* 23 - PCM A-law
|
||||||
* 24 - PCM Mu-law
|
* 24 - PCM Mu-law
|
||||||
*
|
*
|
||||||
* ... - More
|
* ... - More
|
||||||
*/
|
*/
|
||||||
unsigned short Encoding;
|
unsigned short Encoding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adjust the sample rate.
|
* @brief Adjust the sample rate.
|
||||||
*
|
*
|
||||||
* 0 - 8000 Hz
|
* 0 - 8000 Hz
|
||||||
* 1 - 11025 Hz
|
* 1 - 11025 Hz
|
||||||
* 2 - 16000 Hz
|
* 2 - 16000 Hz
|
||||||
* 3 - 22050 Hz
|
* 3 - 22050 Hz
|
||||||
* 4 - 32000 Hz
|
* 4 - 32000 Hz
|
||||||
* 5 - 44100 Hz
|
* 5 - 44100 Hz
|
||||||
* 6 - 48000 Hz
|
* 6 - 48000 Hz
|
||||||
* 7 - 88200 Hz
|
* 7 - 88200 Hz
|
||||||
* 8 - 96000 Hz
|
* 8 - 96000 Hz
|
||||||
*/
|
*/
|
||||||
unsigned char SampleRate;
|
unsigned char SampleRate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adjust the channels.
|
* @brief Adjust the channels.
|
||||||
*
|
*
|
||||||
* 0 - Mono
|
* 0 - Mono
|
||||||
* 1 - Stereo
|
* 1 - Stereo
|
||||||
*/
|
*/
|
||||||
unsigned char Channels;
|
unsigned char Channels;
|
||||||
} Adjust;
|
} Adjust;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned char *Data;
|
unsigned char *Data;
|
||||||
unsigned long Length;
|
unsigned long Length;
|
||||||
} Send;
|
} Send;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned char Volume;
|
unsigned char Volume;
|
||||||
unsigned short Encoding;
|
unsigned short Encoding;
|
||||||
unsigned char SampleRate;
|
unsigned char SampleRate;
|
||||||
unsigned char Channels;
|
unsigned char Channels;
|
||||||
} Fetch;
|
} Fetch;
|
||||||
} AudioCallback;
|
} AudioCallback;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned char Vector;
|
unsigned char Vector;
|
||||||
} InterruptInfo;
|
} InterruptInfo;
|
||||||
};
|
};
|
||||||
unsigned long raw;
|
unsigned long raw;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
union CPURegisters
|
union CPURegisters
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
#if defined(__x86_64__) || defined(__amd64__)
|
#if defined(__x86_64__) || defined(__amd64__)
|
||||||
unsigned long r15;
|
unsigned long r15;
|
||||||
unsigned long r14;
|
unsigned long r14;
|
||||||
unsigned long r13;
|
unsigned long r13;
|
||||||
unsigned long r12;
|
unsigned long r12;
|
||||||
unsigned long r11;
|
unsigned long r11;
|
||||||
unsigned long r10;
|
unsigned long r10;
|
||||||
unsigned long r9;
|
unsigned long r9;
|
||||||
unsigned long r8;
|
unsigned long r8;
|
||||||
|
|
||||||
unsigned long rbp;
|
unsigned long rbp;
|
||||||
unsigned long rdi;
|
unsigned long rdi;
|
||||||
unsigned long rsi;
|
unsigned long rsi;
|
||||||
unsigned long rdx;
|
unsigned long rdx;
|
||||||
unsigned long rcx;
|
unsigned long rcx;
|
||||||
unsigned long rbx;
|
unsigned long rbx;
|
||||||
unsigned long rax;
|
unsigned long rax;
|
||||||
|
|
||||||
unsigned long InterruptNumber;
|
unsigned long InterruptNumber;
|
||||||
unsigned long ErrorCode;
|
unsigned long ErrorCode;
|
||||||
unsigned long rip;
|
unsigned long rip;
|
||||||
unsigned long cs;
|
unsigned long cs;
|
||||||
unsigned long rflags;
|
unsigned long rflags;
|
||||||
unsigned long rsp;
|
unsigned long rsp;
|
||||||
unsigned long ss;
|
unsigned long ss;
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
unsigned int ebp;
|
unsigned int ebp;
|
||||||
unsigned int edi;
|
unsigned int edi;
|
||||||
unsigned int esi;
|
unsigned int esi;
|
||||||
unsigned int edx;
|
unsigned int edx;
|
||||||
unsigned int ecx;
|
unsigned int ecx;
|
||||||
unsigned int ebx;
|
unsigned int ebx;
|
||||||
unsigned int eax;
|
unsigned int eax;
|
||||||
|
|
||||||
unsigned int InterruptNumber;
|
unsigned int InterruptNumber;
|
||||||
unsigned int ErrorCode;
|
unsigned int ErrorCode;
|
||||||
unsigned int eip;
|
unsigned int eip;
|
||||||
unsigned int cs;
|
unsigned int cs;
|
||||||
unsigned int eflags;
|
unsigned int eflags;
|
||||||
unsigned int esp;
|
unsigned int esp;
|
||||||
unsigned int ss;
|
unsigned int ss;
|
||||||
#else
|
#else
|
||||||
#warning "Unsupported architecture"
|
#warning "Unsupported architecture"
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
unsigned long raw;
|
unsigned long raw;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
#endif // !__FENNIX_DRIVER_API_H__
|
#endif // !__FENNIX_DRIVER_API_H__
|
||||||
|
311
Drivers/AHCI/AdvancedHostControllerInterface.cpp
Normal file
311
Drivers/AHCI/AdvancedHostControllerInterface.cpp
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ahci.hpp"
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
#include <pci.hpp>
|
||||||
|
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
#include "../drv.hpp"
|
||||||
|
|
||||||
|
using namespace PCI;
|
||||||
|
|
||||||
|
namespace AdvancedHostControllerInterface
|
||||||
|
{
|
||||||
|
KernelAPI KAPI;
|
||||||
|
|
||||||
|
HBAMemory *ABAR;
|
||||||
|
Port *Ports[32];
|
||||||
|
uint8_t PortCount = 0;
|
||||||
|
|
||||||
|
PCIDeviceHeader *PCIBaseAddress;
|
||||||
|
|
||||||
|
const char *PortTypeName[] = {"None",
|
||||||
|
"SATA",
|
||||||
|
"SEMB",
|
||||||
|
"PM",
|
||||||
|
"SATAPI"};
|
||||||
|
|
||||||
|
PortType CheckPortType(HBAPort *Port)
|
||||||
|
{
|
||||||
|
uint32_t SataStatus = Port->SataStatus;
|
||||||
|
uint8_t InterfacePowerManagement = (SataStatus >> 8) & 0b111;
|
||||||
|
uint8_t DeviceDetection = SataStatus & 0b111;
|
||||||
|
|
||||||
|
if (DeviceDetection != HBA_PORT_DEV_PRESENT)
|
||||||
|
return PortType::None;
|
||||||
|
if (InterfacePowerManagement != HBA_PORT_IPM_ACTIVE)
|
||||||
|
return PortType::None;
|
||||||
|
|
||||||
|
switch (Port->Signature)
|
||||||
|
{
|
||||||
|
case SATA_SIG_ATAPI:
|
||||||
|
return PortType::SATAPI;
|
||||||
|
case SATA_SIG_ATA:
|
||||||
|
return PortType::SATA;
|
||||||
|
case SATA_SIG_PM:
|
||||||
|
return PortType::PM;
|
||||||
|
case SATA_SIG_SEMB:
|
||||||
|
return PortType::SEMB;
|
||||||
|
default:
|
||||||
|
return PortType::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Port::Port(PortType Type, HBAPort *PortPtr, uint8_t PortNumber)
|
||||||
|
{
|
||||||
|
this->AHCIPortType = Type;
|
||||||
|
this->HBAPortPtr = PortPtr;
|
||||||
|
this->Buffer = static_cast<uint8_t *>(KAPI.Memory.RequestPage(1));
|
||||||
|
memset(this->Buffer, 0, KAPI.Memory.PageSize);
|
||||||
|
this->PortNumber = PortNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
Port::~Port()
|
||||||
|
{
|
||||||
|
KAPI.Memory.FreePage(this->Buffer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Port::StartCMD()
|
||||||
|
{
|
||||||
|
while (HBAPortPtr->CommandStatus & HBA_PxCMD_CR)
|
||||||
|
;
|
||||||
|
HBAPortPtr->CommandStatus |= HBA_PxCMD_FRE;
|
||||||
|
HBAPortPtr->CommandStatus |= HBA_PxCMD_ST;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Port::StopCMD()
|
||||||
|
{
|
||||||
|
HBAPortPtr->CommandStatus &= ~HBA_PxCMD_ST;
|
||||||
|
HBAPortPtr->CommandStatus &= ~HBA_PxCMD_FRE;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (HBAPortPtr->CommandStatus & HBA_PxCMD_FR)
|
||||||
|
continue;
|
||||||
|
if (HBAPortPtr->CommandStatus & HBA_PxCMD_CR)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Port::Configure()
|
||||||
|
{
|
||||||
|
StopCMD();
|
||||||
|
void *NewBase = KAPI.Memory.RequestPage(1);
|
||||||
|
HBAPortPtr->CommandListBase = (uint32_t)(uint64_t)NewBase;
|
||||||
|
HBAPortPtr->CommandListBaseUpper = (uint32_t)((uint64_t)NewBase >> 32);
|
||||||
|
memset(reinterpret_cast<void *>(HBAPortPtr->CommandListBase), 0, 1024);
|
||||||
|
|
||||||
|
void *FISBase = KAPI.Memory.RequestPage(1);
|
||||||
|
HBAPortPtr->FISBaseAddress = (uint32_t)(uint64_t)FISBase;
|
||||||
|
HBAPortPtr->FISBaseAddressUpper = (uint32_t)((uint64_t)FISBase >> 32);
|
||||||
|
memset(FISBase, 0, 256);
|
||||||
|
|
||||||
|
HBACommandHeader *CommandHeader = (HBACommandHeader *)((uint64_t)HBAPortPtr->CommandListBase + ((uint64_t)HBAPortPtr->CommandListBaseUpper << 32));
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
CommandHeader[i].PRDTLength = 8;
|
||||||
|
void *CommandTableAddress = KAPI.Memory.RequestPage(1);
|
||||||
|
uint64_t Address = (uint64_t)CommandTableAddress + (i << 8);
|
||||||
|
CommandHeader[i].CommandTableBaseAddress = (uint32_t)(uint64_t)Address;
|
||||||
|
CommandHeader[i].CommandTableBaseAddressUpper = (uint32_t)((uint64_t)Address >> 32);
|
||||||
|
memset(CommandTableAddress, 0, 256);
|
||||||
|
}
|
||||||
|
StartCMD();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Port::ReadWrite(uint64_t Sector, uint32_t SectorCount, uint8_t *Buffer, bool Write)
|
||||||
|
{
|
||||||
|
if (this->PortNumber == PortType::SATAPI && Write)
|
||||||
|
{
|
||||||
|
error("SATAPI port does not support write.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SectorL = (uint32_t)Sector;
|
||||||
|
uint32_t SectorH = (uint32_t)(Sector >> 32);
|
||||||
|
|
||||||
|
HBAPortPtr->InterruptStatus = (uint32_t)-1; // Clear pending interrupt bits
|
||||||
|
|
||||||
|
HBACommandHeader *CommandHeader = reinterpret_cast<HBACommandHeader *>(HBAPortPtr->CommandListBase);
|
||||||
|
CommandHeader->CommandFISLength = sizeof(FIS_REG_H2D) / sizeof(uint32_t);
|
||||||
|
if (Write)
|
||||||
|
CommandHeader->Write = 1;
|
||||||
|
else
|
||||||
|
CommandHeader->Write = 0;
|
||||||
|
CommandHeader->PRDTLength = 1;
|
||||||
|
|
||||||
|
HBACommandTable *CommandTable = reinterpret_cast<HBACommandTable *>(CommandHeader->CommandTableBaseAddress);
|
||||||
|
memset(CommandTable, 0, sizeof(HBACommandTable) + (CommandHeader->PRDTLength - 1) * sizeof(HBAPRDTEntry));
|
||||||
|
|
||||||
|
CommandTable->PRDTEntry[0].DataBaseAddress = (uint32_t)(uint64_t)Buffer;
|
||||||
|
CommandTable->PRDTEntry[0].DataBaseAddressUpper = (uint32_t)((uint64_t)Buffer >> 32);
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
/* conversion from ‘uint32_t’ {aka ‘unsigned int’} to ‘unsigned int:22’ may change value */
|
||||||
|
#pragma GCC diagnostic ignored "-Wconversion"
|
||||||
|
CommandTable->PRDTEntry[0].ByteCount = (SectorCount << 9) - 1; /* 512 bytes per sector */
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
CommandTable->PRDTEntry[0].InterruptOnCompletion = 1;
|
||||||
|
|
||||||
|
FIS_REG_H2D *CommandFIS = (FIS_REG_H2D *)(&CommandTable->CommandFIS);
|
||||||
|
|
||||||
|
CommandFIS->FISType = FIS_TYPE_REG_H2D;
|
||||||
|
CommandFIS->CommandControl = 1;
|
||||||
|
if (Write)
|
||||||
|
CommandFIS->Command = ATA_CMD_WRITE_DMA_EX;
|
||||||
|
else
|
||||||
|
CommandFIS->Command = ATA_CMD_READ_DMA_EX;
|
||||||
|
|
||||||
|
CommandFIS->LBA0 = (uint8_t)SectorL;
|
||||||
|
CommandFIS->LBA1 = (uint8_t)(SectorL >> 8);
|
||||||
|
CommandFIS->LBA2 = (uint8_t)(SectorL >> 16);
|
||||||
|
CommandFIS->LBA3 = (uint8_t)SectorH;
|
||||||
|
CommandFIS->LBA4 = (uint8_t)(SectorH >> 8);
|
||||||
|
CommandFIS->LBA5 = (uint8_t)(SectorH >> 16);
|
||||||
|
|
||||||
|
CommandFIS->DeviceRegister = 1 << 6; // LBA mode
|
||||||
|
CommandFIS->CountLow = SectorCount & 0xFF;
|
||||||
|
CommandFIS->CountHigh = (SectorCount >> 8) & 0xFF;
|
||||||
|
|
||||||
|
uint64_t Spin = 0;
|
||||||
|
|
||||||
|
while ((HBAPortPtr->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && Spin < 1000000)
|
||||||
|
Spin++;
|
||||||
|
if (Spin == 1000000)
|
||||||
|
{
|
||||||
|
error("Port not responding.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HBAPortPtr->CommandIssue = 1;
|
||||||
|
|
||||||
|
Spin = 0;
|
||||||
|
int TryCount = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (Spin > 100000000)
|
||||||
|
{
|
||||||
|
error("Port %d not responding. (%d)", this->PortNumber, TryCount);
|
||||||
|
Spin = 0;
|
||||||
|
TryCount++;
|
||||||
|
if (TryCount > 10)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (HBAPortPtr->CommandIssue == 0)
|
||||||
|
break;
|
||||||
|
Spin++;
|
||||||
|
if (HBAPortPtr->InterruptStatus & HBA_PxIS_TFES)
|
||||||
|
{
|
||||||
|
error("Error reading/writing (%d).", Write);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DriverEntry(void *Data)
|
||||||
|
{
|
||||||
|
if (!Data)
|
||||||
|
return INVALID_KERNEL_API;
|
||||||
|
KAPI = *(KernelAPI *)Data;
|
||||||
|
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
|
||||||
|
return KERNEL_API_VERSION_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CallbackHandler(KernelCallback *Data)
|
||||||
|
{
|
||||||
|
switch (Data->Reason)
|
||||||
|
{
|
||||||
|
case AcknowledgeReason:
|
||||||
|
{
|
||||||
|
debug("Kernel acknowledged the driver.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ConfigurationReason:
|
||||||
|
{
|
||||||
|
debug("Driver received configuration data.");
|
||||||
|
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
|
||||||
|
ABAR = reinterpret_cast<HBAMemory *>(((PCIHeader0 *)PCIBaseAddress)->BAR5);
|
||||||
|
KAPI.Memory.Map((void *)ABAR, (void *)ABAR, (1 << 1));
|
||||||
|
|
||||||
|
uint32_t PortsImplemented = ABAR->PortsImplemented;
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
if (PortsImplemented & (1 << i))
|
||||||
|
{
|
||||||
|
PortType portType = CheckPortType(&ABAR->Ports[i]);
|
||||||
|
if (portType == PortType::SATA || portType == PortType::SATAPI)
|
||||||
|
{
|
||||||
|
trace("%s drive found at port %d", PortTypeName[portType], i);
|
||||||
|
Ports[PortCount] = new Port(portType, &ABAR->Ports[i], PortCount);
|
||||||
|
PortCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (portType != PortType::None)
|
||||||
|
warn("Unsupported drive type %s found at port %d", PortTypeName[portType], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < PortCount; i++)
|
||||||
|
Ports[i]->Configure();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FetchReason:
|
||||||
|
{
|
||||||
|
Data->DiskCallback.Fetch.Ports = PortCount;
|
||||||
|
Data->DiskCallback.Fetch.BytesPerSector = 512;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StopReason:
|
||||||
|
{
|
||||||
|
// TODO: Stop the driver.
|
||||||
|
debug("Driver stopped.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SendReason:
|
||||||
|
case ReceiveReason:
|
||||||
|
{
|
||||||
|
Ports[Data->DiskCallback.RW.Port]->ReadWrite(Data->DiskCallback.RW.Sector,
|
||||||
|
(uint32_t)Data->DiskCallback.RW.SectorCount,
|
||||||
|
Data->DiskCallback.RW.Buffer,
|
||||||
|
Data->DiskCallback.RW.Write);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown reason.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InterruptCallback(CPURegisters *)
|
||||||
|
{
|
||||||
|
/* There's no need to do anything here. */
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
193
Drivers/AHCI/ahci.hpp
Normal file
193
Drivers/AHCI/ahci.hpp
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_AHCI_H__
|
||||||
|
#define __FENNIX_KERNEL_AHCI_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
|
||||||
|
namespace AdvancedHostControllerInterface
|
||||||
|
{
|
||||||
|
#define ATA_DEV_BUSY 0x80
|
||||||
|
#define ATA_DEV_DRQ 0x08
|
||||||
|
#define ATA_CMD_WRITE_DMA_EX 0x35
|
||||||
|
#define ATA_CMD_READ_DMA_EX 0x25
|
||||||
|
#define HBA_PxIS_TFES (1 << 30)
|
||||||
|
|
||||||
|
#define HBA_PORT_DEV_PRESENT 0x3
|
||||||
|
#define HBA_PORT_IPM_ACTIVE 0x1
|
||||||
|
#define SATA_SIG_ATAPI 0xEB140101
|
||||||
|
#define SATA_SIG_ATA 0x00000101
|
||||||
|
#define SATA_SIG_SEMB 0xC33C0101
|
||||||
|
#define SATA_SIG_PM 0x96690101
|
||||||
|
|
||||||
|
#define HBA_PxCMD_CR 0x8000
|
||||||
|
#define HBA_PxCMD_FRE 0x0010
|
||||||
|
#define HBA_PxCMD_ST 0x0001
|
||||||
|
#define HBA_PxCMD_FR 0x4000
|
||||||
|
|
||||||
|
enum PortType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
SATA = 1,
|
||||||
|
SEMB = 2,
|
||||||
|
PM = 3,
|
||||||
|
SATAPI = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FIS_TYPE
|
||||||
|
{
|
||||||
|
FIS_TYPE_REG_H2D = 0x27,
|
||||||
|
FIS_TYPE_REG_D2H = 0x34,
|
||||||
|
FIS_TYPE_DMA_ACT = 0x39,
|
||||||
|
FIS_TYPE_DMA_SETUP = 0x41,
|
||||||
|
FIS_TYPE_DATA = 0x46,
|
||||||
|
FIS_TYPE_BIST = 0x58,
|
||||||
|
FIS_TYPE_PIO_SETUP = 0x5F,
|
||||||
|
FIS_TYPE_DEV_BITS = 0xA1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HBAPort
|
||||||
|
{
|
||||||
|
uint32_t CommandListBase;
|
||||||
|
uint32_t CommandListBaseUpper;
|
||||||
|
uint32_t FISBaseAddress;
|
||||||
|
uint32_t FISBaseAddressUpper;
|
||||||
|
uint32_t InterruptStatus;
|
||||||
|
uint32_t InterruptEnable;
|
||||||
|
uint32_t CommandStatus;
|
||||||
|
uint32_t Reserved0;
|
||||||
|
uint32_t TaskFileData;
|
||||||
|
uint32_t Signature;
|
||||||
|
uint32_t SataStatus;
|
||||||
|
uint32_t SataControl;
|
||||||
|
uint32_t SataError;
|
||||||
|
uint32_t SataActive;
|
||||||
|
uint32_t CommandIssue;
|
||||||
|
uint32_t SataNotification;
|
||||||
|
uint32_t FISSwitchControl;
|
||||||
|
uint32_t Reserved1[11];
|
||||||
|
uint32_t Vendor[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HBAMemory
|
||||||
|
{
|
||||||
|
uint32_t HostCapability;
|
||||||
|
uint32_t GlobalHostControl;
|
||||||
|
uint32_t InterruptStatus;
|
||||||
|
uint32_t PortsImplemented;
|
||||||
|
uint32_t Version;
|
||||||
|
uint32_t CCCControl;
|
||||||
|
uint32_t CCCPorts;
|
||||||
|
uint32_t EnclosureManagementLocation;
|
||||||
|
uint32_t EnclosureManagementControl;
|
||||||
|
uint32_t HostCapabilitiesExtended;
|
||||||
|
uint32_t BIOSHandoffControlStatus;
|
||||||
|
uint8_t Reserved0[0x74];
|
||||||
|
uint8_t Vendor[0x60];
|
||||||
|
HBAPort Ports[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HBACommandHeader
|
||||||
|
{
|
||||||
|
uint8_t CommandFISLength : 5;
|
||||||
|
uint8_t ATAPI : 1;
|
||||||
|
uint8_t Write : 1;
|
||||||
|
uint8_t Preferable : 1;
|
||||||
|
uint8_t Reset : 1;
|
||||||
|
uint8_t BIST : 1;
|
||||||
|
uint8_t ClearBusy : 1;
|
||||||
|
uint8_t Reserved0 : 1;
|
||||||
|
uint8_t PortMultiplier : 4;
|
||||||
|
uint16_t PRDTLength;
|
||||||
|
uint32_t PRDBCount;
|
||||||
|
uint32_t CommandTableBaseAddress;
|
||||||
|
uint32_t CommandTableBaseAddressUpper;
|
||||||
|
uint32_t Reserved1[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HBAPRDTEntry
|
||||||
|
{
|
||||||
|
uint32_t DataBaseAddress;
|
||||||
|
uint32_t DataBaseAddressUpper;
|
||||||
|
uint32_t Reserved0;
|
||||||
|
uint32_t ByteCount : 22;
|
||||||
|
uint32_t Reserved1 : 9;
|
||||||
|
uint32_t InterruptOnCompletion : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HBACommandTable
|
||||||
|
{
|
||||||
|
uint8_t CommandFIS[64];
|
||||||
|
uint8_t ATAPICommand[16];
|
||||||
|
uint8_t Reserved[48];
|
||||||
|
HBAPRDTEntry PRDTEntry[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FIS_REG_H2D
|
||||||
|
{
|
||||||
|
uint8_t FISType;
|
||||||
|
uint8_t PortMultiplier : 4;
|
||||||
|
uint8_t Reserved0 : 3;
|
||||||
|
uint8_t CommandControl : 1;
|
||||||
|
uint8_t Command;
|
||||||
|
uint8_t FeatureLow;
|
||||||
|
uint8_t LBA0;
|
||||||
|
uint8_t LBA1;
|
||||||
|
uint8_t LBA2;
|
||||||
|
uint8_t DeviceRegister;
|
||||||
|
uint8_t LBA3;
|
||||||
|
uint8_t LBA4;
|
||||||
|
uint8_t LBA5;
|
||||||
|
uint8_t FeatureHigh;
|
||||||
|
uint8_t CountLow;
|
||||||
|
uint8_t CountHigh;
|
||||||
|
uint8_t ISOCommandCompletion;
|
||||||
|
uint8_t Control;
|
||||||
|
uint8_t Reserved1[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BARData
|
||||||
|
{
|
||||||
|
uint8_t Type;
|
||||||
|
uint16_t IOBase;
|
||||||
|
uint64_t MemoryBase;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Port
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PortType AHCIPortType;
|
||||||
|
HBAPort *HBAPortPtr;
|
||||||
|
uint8_t *Buffer;
|
||||||
|
uint8_t PortNumber;
|
||||||
|
|
||||||
|
Port(PortType Type, HBAPort *PortPtr, uint8_t PortNumber);
|
||||||
|
~Port();
|
||||||
|
void StartCMD();
|
||||||
|
void StopCMD();
|
||||||
|
void Configure();
|
||||||
|
bool ReadWrite(uint64_t Sector, uint32_t SectorCount, uint8_t *Buffer, bool Write);
|
||||||
|
};
|
||||||
|
|
||||||
|
int DriverEntry(void *);
|
||||||
|
int CallbackHandler(KernelCallback *);
|
||||||
|
int InterruptCallback(CPURegisters *);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_AHCI_H__
|
91
Drivers/ATA/AdvancedTechnologyAttachment.cpp
Normal file
91
Drivers/ATA/AdvancedTechnologyAttachment.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include "ata.hpp"
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
#include <pci.hpp>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
#include "../drv.hpp"
|
||||||
|
|
||||||
|
namespace AdvancedTechnologyAttachment
|
||||||
|
{
|
||||||
|
KernelAPI KAPI;
|
||||||
|
|
||||||
|
bool IsATAPresent()
|
||||||
|
{
|
||||||
|
outb(0x1F0 + 2, 0);
|
||||||
|
outb(0x1F0 + 3, 0);
|
||||||
|
outb(0x1F0 + 4, 0);
|
||||||
|
outb(0x1F0 + 5, 0);
|
||||||
|
outb(0x1F0 + 7, 0xEC);
|
||||||
|
if (inb(0x1F0 + 7) == 0 || inb(0x1F0 + 1) != 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DriverEntry(void *Data)
|
||||||
|
{
|
||||||
|
if (!Data)
|
||||||
|
return INVALID_KERNEL_API;
|
||||||
|
KAPI = *(KernelAPI *)Data;
|
||||||
|
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
|
||||||
|
return KERNEL_API_VERSION_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
if (!IsATAPresent())
|
||||||
|
return NOT_AVAILABLE;
|
||||||
|
trace("ATA device found.");
|
||||||
|
|
||||||
|
return NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CallbackHandler(KernelCallback *Data)
|
||||||
|
{
|
||||||
|
switch (Data->Reason)
|
||||||
|
{
|
||||||
|
case AcknowledgeReason:
|
||||||
|
{
|
||||||
|
debug("Kernel acknowledged the driver.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ConfigurationReason:
|
||||||
|
{
|
||||||
|
debug("Driver received configuration data.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FetchReason:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SendReason:
|
||||||
|
case ReceiveReason:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StopReason:
|
||||||
|
{
|
||||||
|
// TODO: Stop the driver.
|
||||||
|
debug("Driver stopped.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown reason.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InterruptCallback(CPURegisters *Registers)
|
||||||
|
{
|
||||||
|
if (Registers->InterruptNumber == 0xE)
|
||||||
|
{
|
||||||
|
fixme("IRQ14");
|
||||||
|
}
|
||||||
|
else if (Registers->InterruptNumber == 0xF)
|
||||||
|
{
|
||||||
|
fixme("IRQ15");
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
@ -15,26 +15,17 @@
|
|||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../../api.hpp"
|
#ifndef __FENNIX_KERNEL_ATA_H__
|
||||||
|
#define __FENNIX_KERNEL_ATA_H__
|
||||||
|
|
||||||
#include <ints.hpp>
|
#include <types.h>
|
||||||
#include <memory.hpp>
|
#include "../../DAPI.hpp"
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
namespace AdvancedTechnologyAttachment
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
{
|
||||||
DriverCode Driver::BindInputAudio(Memory::MemMgr *mem, void *fex)
|
int DriverEntry(void *);
|
||||||
{
|
int CallbackHandler(KernelCallback *);
|
||||||
UNUSED(mem);
|
int InterruptCallback(CPURegisters *);
|
||||||
UNUSED(fex);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_ATA_H__
|
114
Drivers/AdvancedMicroDevices/PCNET.cpp
Normal file
114
Drivers/AdvancedMicroDevices/PCNET.cpp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#include "pcnet.hpp"
|
||||||
|
|
||||||
|
#include <net/net.hpp>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <pci.hpp>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
#include "../drv.hpp"
|
||||||
|
|
||||||
|
using namespace PCI;
|
||||||
|
|
||||||
|
namespace PCNET
|
||||||
|
{
|
||||||
|
KernelAPI KAPI;
|
||||||
|
|
||||||
|
PCIDeviceHeader *PCIBaseAddress;
|
||||||
|
BARData BAR;
|
||||||
|
|
||||||
|
MediaAccessControl MAC;
|
||||||
|
InternetProtocol::Version4 IP;
|
||||||
|
|
||||||
|
void WriteRAP32(uint32_t Value) { outportl(BAR.IOBase + 0x14, Value); }
|
||||||
|
void WriteRAP16(uint16_t Value) { outportw(BAR.IOBase + 0x12, Value); }
|
||||||
|
|
||||||
|
uint32_t ReadCSR32(uint32_t CSR)
|
||||||
|
{
|
||||||
|
WriteRAP32(CSR);
|
||||||
|
return inportl(BAR.IOBase + 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ReadCSR16(uint16_t CSR)
|
||||||
|
{
|
||||||
|
WriteRAP32(CSR);
|
||||||
|
return inportw(BAR.IOBase + 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteCSR32(uint32_t CSR, uint32_t Value)
|
||||||
|
{
|
||||||
|
WriteRAP32(CSR);
|
||||||
|
outportl(BAR.IOBase + 0x10, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteCSR16(uint16_t CSR, uint16_t Value)
|
||||||
|
{
|
||||||
|
WriteRAP16(CSR);
|
||||||
|
outportw(BAR.IOBase + 0x10, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DriverEntry(void *Data)
|
||||||
|
{
|
||||||
|
if (!Data)
|
||||||
|
return INVALID_KERNEL_API;
|
||||||
|
KAPI = *(KernelAPI *)Data;
|
||||||
|
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
|
||||||
|
return KERNEL_API_VERSION_NOT_SUPPORTED;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CallbackHandler(KernelCallback *Data)
|
||||||
|
{
|
||||||
|
switch (Data->Reason)
|
||||||
|
{
|
||||||
|
case AcknowledgeReason:
|
||||||
|
{
|
||||||
|
debug("Kernel acknowledged the driver.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ConfigurationReason:
|
||||||
|
{
|
||||||
|
debug("Driver received configuration data.");
|
||||||
|
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
|
||||||
|
if (PCIBaseAddress->VendorID == 0x1022 && PCIBaseAddress->DeviceID == 0x2000)
|
||||||
|
{
|
||||||
|
trace("Found AMD PCNET.");
|
||||||
|
uint32_t PCIBAR = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
|
||||||
|
BAR.Type = PCIBAR & 1;
|
||||||
|
BAR.IOBase = (uint16_t)(PCIBAR & (~3));
|
||||||
|
BAR.MemoryBase = PCIBAR & (~15);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return DEVICE_NOT_SUPPORTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FetchReason:
|
||||||
|
{
|
||||||
|
memcpy(Data->NetworkCallback.Fetch.Name, (void *)"AMD PCNET", 10);
|
||||||
|
Data->NetworkCallback.Fetch.MAC = MAC.ToHex();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SendReason:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StopReason:
|
||||||
|
{
|
||||||
|
// TODO: Stop the driver.
|
||||||
|
debug("Driver stopped.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown reason.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InterruptCallback(CPURegisters *)
|
||||||
|
{
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
@ -15,26 +15,24 @@
|
|||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../../api.hpp"
|
#ifndef __FENNIX_KERNEL_AMD_PCNET_H__
|
||||||
|
#define __FENNIX_KERNEL_AMD_PCNET_H__
|
||||||
|
|
||||||
#include <ints.hpp>
|
#include <types.h>
|
||||||
#include <memory.hpp>
|
#include "../../DAPI.hpp"
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
namespace PCNET
|
||||||
#include "../../../../DAPI.hpp"
|
|
||||||
#include "../../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
{
|
||||||
DriverCode Driver::BindInputDisplay(Memory::MemMgr *mem, void *fex)
|
struct BARData
|
||||||
{
|
{
|
||||||
UNUSED(mem);
|
uint8_t Type;
|
||||||
UNUSED(fex);
|
uint16_t IOBase;
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
uint64_t MemoryBase;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
int DriverEntry(void *);
|
||||||
|
int CallbackHandler(KernelCallback *);
|
||||||
|
int InterruptCallback(CPURegisters *);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_AMD_PCNET_H__
|
370
Drivers/AudioCodec97/AudioCodec97Driver.cpp
Normal file
370
Drivers/AudioCodec97/AudioCodec97Driver.cpp
Normal file
@ -0,0 +1,370 @@
|
|||||||
|
#include "ac97.hpp"
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
#include <pci.hpp>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
#include "../drv.hpp"
|
||||||
|
|
||||||
|
using namespace PCI;
|
||||||
|
|
||||||
|
namespace AudioCodec97
|
||||||
|
{
|
||||||
|
KernelAPI KAPI;
|
||||||
|
|
||||||
|
/* https://wiki.osdev.org/AC97 */
|
||||||
|
|
||||||
|
PCIDeviceHeader *PCIBaseAddress;
|
||||||
|
BARData BAR;
|
||||||
|
BufferDescriptorList *DescriptorList = nullptr;
|
||||||
|
|
||||||
|
AudioEncodingValues Encoding = AE_PCMs16le;
|
||||||
|
char Channels = 2;
|
||||||
|
uint8_t Volume = AV_Maximum;
|
||||||
|
bool Mute = false;
|
||||||
|
int SampleRate = 48000;
|
||||||
|
char SampleSize = 2;
|
||||||
|
|
||||||
|
uint16_t MixerVolume(uint8_t Left, uint8_t Right, bool Mute)
|
||||||
|
{
|
||||||
|
return ((uint16_t)((Right & 0x3F) |
|
||||||
|
((Left & 0x3F) << 0x8) |
|
||||||
|
(Mute & 1 << 0xF)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int DriverEntry(void *Data)
|
||||||
|
{
|
||||||
|
if (!Data)
|
||||||
|
return INVALID_KERNEL_API;
|
||||||
|
KAPI = *(KernelAPI *)Data;
|
||||||
|
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
|
||||||
|
return KERNEL_API_VERSION_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CallbackHandler(KernelCallback *Data)
|
||||||
|
{
|
||||||
|
switch (Data->Reason)
|
||||||
|
{
|
||||||
|
case AcknowledgeReason:
|
||||||
|
{
|
||||||
|
debug("Kernel acknowledged the driver.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ConfigurationReason:
|
||||||
|
{
|
||||||
|
debug("Driver received configuration data.");
|
||||||
|
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
|
||||||
|
PCIBaseAddress->Command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
|
||||||
|
|
||||||
|
/* Native Audio Mixer Base Address */
|
||||||
|
uint32_t PCIBAR0 = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
|
||||||
|
|
||||||
|
/* Native Audio Bus Master Base Address */
|
||||||
|
uint32_t PCIBAR1 = ((PCIHeader0 *)PCIBaseAddress)->BAR1;
|
||||||
|
|
||||||
|
BAR.Type = PCIBAR0 & 1;
|
||||||
|
BAR.MixerAddress = (uint16_t)(PCIBAR0 & (~3));
|
||||||
|
BAR.BusMasterAddress = PCIBAR1 & (~15);
|
||||||
|
|
||||||
|
if (BAR.Type != 1)
|
||||||
|
{
|
||||||
|
error("BAR0 is not I/O.");
|
||||||
|
return INVALID_PCI_BAR;
|
||||||
|
}
|
||||||
|
uint16_t OutputPCMTransferControl = (uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl);
|
||||||
|
|
||||||
|
/* DescriptorList address MUST be physical. */
|
||||||
|
DescriptorList = (BufferDescriptorList *)KAPI.Memory.RequestPage((sizeof(BufferDescriptorList) * DescriptorListLength) / KAPI.Memory.PageSize + 1);
|
||||||
|
memset(DescriptorList, 0, sizeof(BufferDescriptorList) * DescriptorListLength);
|
||||||
|
|
||||||
|
uint16_t DLSampleCount = (uint16_t)(KAPI.Memory.PageSize / SampleSize);
|
||||||
|
for (int i = 0; i < DescriptorListLength; i++)
|
||||||
|
{
|
||||||
|
int DescriptorPages = (int)(sizeof(uint16_t *) / KAPI.Memory.PageSize + 1);
|
||||||
|
DescriptorList[i].Address = (uint32_t)(uint64_t)KAPI.Memory.RequestPage(DescriptorPages);
|
||||||
|
DescriptorList[i].SampleCount = DLSampleCount;
|
||||||
|
DescriptorList[i].Flags = 0;
|
||||||
|
debug("DescriptorList[%d] = { Address: 0x%x (%d %s), SampleCount: %d, Flags: 0x%x }",
|
||||||
|
i,
|
||||||
|
DescriptorList[i].Address, DescriptorPages, DescriptorPages == 1 ? "page" : "pages",
|
||||||
|
DescriptorList[i].SampleCount,
|
||||||
|
DescriptorList[i].Flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
outw(BAR.MixerAddress + NAM_MasterVolume, MixerVolume(Volume, Volume, Mute));
|
||||||
|
outw(BAR.MixerAddress + NAM_PCMOutVolume, MixerVolume(Volume, Volume, Mute));
|
||||||
|
|
||||||
|
outb(OutputPCMTransferControl, inb(OutputPCMTransferControl) | TC_TransferReset);
|
||||||
|
while (inb(OutputPCMTransferControl) & TC_TransferReset)
|
||||||
|
;
|
||||||
|
|
||||||
|
uint32_t GlobalControl = inl((uint16_t)(BAR.BusMasterAddress + NABM_GlobalControl));
|
||||||
|
GlobalControl = (GlobalControl & ~((0x3U) << 22)); /* PCM 16-bit mode */
|
||||||
|
GlobalControl = (GlobalControl & ~((0x3U) << 20)); /* 2 channels */
|
||||||
|
GlobalControl |= GC_GlobalInterruptEnable;
|
||||||
|
GlobalControl &= ~GC_ShutDown;
|
||||||
|
|
||||||
|
outl((uint16_t)(BAR.BusMasterAddress + PCMOUT_BufferDescriptorList), (uint32_t)(uint64_t)DescriptorList);
|
||||||
|
outl((uint16_t)(BAR.BusMasterAddress + NABM_GlobalControl), GlobalControl);
|
||||||
|
|
||||||
|
uint8_t TransferControl = inb(OutputPCMTransferControl);
|
||||||
|
TransferControl |= TC_LastBufferEntryInterruptEnable | TC_IOCInterruptEnable | TC_FifoERRORInterruptEnable;
|
||||||
|
outb(OutputPCMTransferControl, TransferControl);
|
||||||
|
|
||||||
|
// Stop DMA
|
||||||
|
outb(OutputPCMTransferControl, inb(OutputPCMTransferControl) & ~TC_DMAControllerControl);
|
||||||
|
debug("AC'97 configured.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AdjustReason:
|
||||||
|
{
|
||||||
|
if (Data->AudioCallback.Adjust._Volume)
|
||||||
|
{
|
||||||
|
Volume = (uint8_t)(0x3F - (0x3F * Data->AudioCallback.Adjust.Volume / 100));
|
||||||
|
outw(BAR.MixerAddress + NAM_MasterVolume, MixerVolume(Volume, Volume, Mute));
|
||||||
|
// outw(BAR.MixerAddress + NAM_PCMOutVolume, MixerVolume(Volume, Volume, Mute));
|
||||||
|
}
|
||||||
|
else if (Data->AudioCallback.Adjust._Encoding)
|
||||||
|
{
|
||||||
|
fixme("Encoding changing not supported yet.");
|
||||||
|
}
|
||||||
|
else if (Data->AudioCallback.Adjust._SampleRate)
|
||||||
|
{
|
||||||
|
switch (Data->AudioCallback.Adjust.SampleRate)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
SampleRate = 8000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
SampleRate = 11025;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
SampleRate = 16000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
SampleRate = 22050;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
SampleRate = 32000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5:
|
||||||
|
{
|
||||||
|
SampleRate = 44100;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6:
|
||||||
|
{
|
||||||
|
SampleRate = 48000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7:
|
||||||
|
{
|
||||||
|
SampleRate = 88200;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
SampleRate = 96000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
SampleRate = 16000;
|
||||||
|
error("Invalid sample rate. Defaulting to 16000.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Data->AudioCallback.Adjust._Channels)
|
||||||
|
{
|
||||||
|
switch (Data->AudioCallback.Adjust.Channels)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
Channels = 1; // Mono
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
Channels = 2; // Stereo
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Channels = 2;
|
||||||
|
error("Invalid channel count. Defaulting to 2.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FetchReason:
|
||||||
|
{
|
||||||
|
Data->AudioCallback.Fetch.Volume = (unsigned char)((inw(BAR.MixerAddress + NAM_MasterVolume) & 0x3F) * 100 / 0x3F);
|
||||||
|
Data->AudioCallback.Fetch.Encoding = Encoding; /* FIXME */
|
||||||
|
// Data->AudioCallback.Fetch.SampleRate = SampleRate; /* FIXME */
|
||||||
|
Data->AudioCallback.Fetch.Channels = Channels;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SendReason:
|
||||||
|
{
|
||||||
|
unsigned char *Buffer = (unsigned char *)Data->AudioCallback.Send.Data;
|
||||||
|
unsigned int Length = (unsigned int)Data->AudioCallback.Send.Length;
|
||||||
|
|
||||||
|
if (Buffer == nullptr)
|
||||||
|
{
|
||||||
|
error("Invalid buffer.");
|
||||||
|
return INVALID_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Length == 0) || (Length % (SampleSize * Channels)))
|
||||||
|
{
|
||||||
|
error("Invalid buffer length.");
|
||||||
|
return INVALID_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TotalBDLToFill = (int)((Length + KAPI.Memory.PageSize - 1) >> 12);
|
||||||
|
|
||||||
|
while (Length > 0)
|
||||||
|
{
|
||||||
|
bool ActiveDMA = !(inw((uint16_t)(BAR.BusMasterAddress + PCMOUT_Status)) & TC_DMAControllerControl);
|
||||||
|
|
||||||
|
if (ActiveDMA)
|
||||||
|
{
|
||||||
|
int RemainingBDL = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int CurrentBDL = inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_BufferDescriptorEntry));
|
||||||
|
int LastBDL = inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_DescriptorEntries));
|
||||||
|
|
||||||
|
RemainingBDL = LastBDL - CurrentBDL;
|
||||||
|
if (RemainingBDL < 0)
|
||||||
|
RemainingBDL += DescriptorListLength;
|
||||||
|
|
||||||
|
RemainingBDL += 1;
|
||||||
|
|
||||||
|
if (RemainingBDL >= DescriptorListLength - 1)
|
||||||
|
{
|
||||||
|
long SampleCount = DescriptorList[(CurrentBDL + 1) % DescriptorListLength].SampleCount / Channels;
|
||||||
|
if (SampleCount > 0)
|
||||||
|
KAPI.Util.Sleep(SampleCount * 1000 / SampleRate); // milliseconds
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (RemainingBDL >= DescriptorListLength - 1 && !(inw((uint16_t)(BAR.BusMasterAddress + PCMOUT_Status)) & TC_DMAControllerControl));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t CurrentBDL = inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_BufferDescriptorEntry));
|
||||||
|
uint8_t LastBDL = inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_DescriptorEntries));
|
||||||
|
uint8_t NextBDL = LastBDL % DescriptorListLength;
|
||||||
|
|
||||||
|
ActiveDMA = !(inw((uint16_t)(BAR.BusMasterAddress + PCMOUT_Status)) & TC_DMAControllerControl);
|
||||||
|
if (ActiveDMA)
|
||||||
|
{
|
||||||
|
NextBDL = (uint8_t)((LastBDL + 1) % DescriptorListLength);
|
||||||
|
if (NextBDL == CurrentBDL)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
size_t Wrote = (KAPI.Memory.PageSize > Length) ? Length : KAPI.Memory.PageSize;
|
||||||
|
|
||||||
|
if (Wrote == 0)
|
||||||
|
break;
|
||||||
|
memcpy((void *)((uint64_t)DescriptorList[NextBDL].Address), Buffer, Wrote);
|
||||||
|
DescriptorList[NextBDL].Flags = 0;
|
||||||
|
|
||||||
|
Buffer += Wrote;
|
||||||
|
Length -= (unsigned int)Wrote;
|
||||||
|
|
||||||
|
DescriptorList[NextBDL].SampleCount = (uint16_t)(Wrote / SampleSize);
|
||||||
|
TotalBDLToFill--;
|
||||||
|
NextBDL = (uint8_t)((NextBDL + 1) % DescriptorListLength);
|
||||||
|
} while (TotalBDLToFill-- && NextBDL != CurrentBDL);
|
||||||
|
|
||||||
|
outb((uint16_t)(BAR.BusMasterAddress + PCMOUT_DescriptorEntries), NextBDL - 1);
|
||||||
|
|
||||||
|
ActiveDMA = !(inw((uint16_t)(BAR.BusMasterAddress + PCMOUT_Status)) & TC_DMAControllerControl);
|
||||||
|
if (!ActiveDMA)
|
||||||
|
{
|
||||||
|
// Start DMA
|
||||||
|
outb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl), inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl) | TC_DMAControllerControl));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StopReason:
|
||||||
|
{
|
||||||
|
outw(BAR.MixerAddress + NAM_MasterVolume, MixerVolume(AV_Maximum, AV_Maximum, true));
|
||||||
|
outw(BAR.MixerAddress + NAM_PCMOutVolume, MixerVolume(AV_Maximum, AV_Maximum, true));
|
||||||
|
|
||||||
|
// Stop DMA
|
||||||
|
outb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl), inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl)) & ~TC_DMAControllerControl);
|
||||||
|
|
||||||
|
// Disable interrupts
|
||||||
|
uint8_t TransferControl = inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl));
|
||||||
|
TransferControl &= ~(TC_LastBufferEntryInterruptEnable | TC_IOCInterruptEnable | TC_FifoERRORInterruptEnable);
|
||||||
|
outb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl), TransferControl);
|
||||||
|
|
||||||
|
// Disable global control
|
||||||
|
uint32_t GlobalControl = inl((uint16_t)(BAR.BusMasterAddress + NABM_GlobalControl));
|
||||||
|
GlobalControl &= ~GC_GlobalInterruptEnable;
|
||||||
|
GlobalControl |= GC_ShutDown;
|
||||||
|
outl((uint16_t)(BAR.BusMasterAddress + NABM_GlobalControl), GlobalControl);
|
||||||
|
|
||||||
|
debug("Driver stopped.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown reason.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InterruptCallback(CPURegisters *)
|
||||||
|
{
|
||||||
|
uint16_t Status = inw(BAR.MixerAddress + PCMOUT_Status);
|
||||||
|
|
||||||
|
if (Status & TC_IOCInterruptEnable)
|
||||||
|
{
|
||||||
|
debug("Interrupt on completion.");
|
||||||
|
}
|
||||||
|
else if (Status & TC_LastBufferEntryInterruptEnable)
|
||||||
|
{
|
||||||
|
debug("Last buffer entry.");
|
||||||
|
// Stop DMA
|
||||||
|
outb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl), inb((uint16_t)(BAR.BusMasterAddress + PCMOUT_TransferControl)) & ~TC_DMAControllerControl);
|
||||||
|
}
|
||||||
|
else if (Status & TC_FifoERRORInterruptEnable)
|
||||||
|
{
|
||||||
|
debug("FIFO error.");
|
||||||
|
}
|
||||||
|
else if (Status != 0x0)
|
||||||
|
{
|
||||||
|
error("Unknown status: %#lx", Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
outw(BAR.MixerAddress + PCMOUT_Status, 0xFFFF);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
348
Drivers/AudioCodec97/ac97.hpp
Normal file
348
Drivers/AudioCodec97/ac97.hpp
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_AC97_H__
|
||||||
|
#define __FENNIX_KERNEL_AC97_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
|
||||||
|
namespace AudioCodec97
|
||||||
|
{
|
||||||
|
#define DescriptorListLength 0x20
|
||||||
|
|
||||||
|
enum AudioVolumeValues
|
||||||
|
{
|
||||||
|
AV_Maximum = 0x0,
|
||||||
|
AV_Minimum = 0x3F,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AudioEncodingValues
|
||||||
|
{
|
||||||
|
AE_PCMs8,
|
||||||
|
AE_PCMu8,
|
||||||
|
|
||||||
|
AE_PCMs16le,
|
||||||
|
AE_PCMs20le,
|
||||||
|
AE_PCMs24le,
|
||||||
|
AE_PCMs32le,
|
||||||
|
|
||||||
|
AE_PCMu16le,
|
||||||
|
AE_PCMu20le,
|
||||||
|
AE_PCMu24le,
|
||||||
|
AE_PCMu32le,
|
||||||
|
|
||||||
|
AE_PCMs16be,
|
||||||
|
AE_PCMs20be,
|
||||||
|
AE_PCMs24be,
|
||||||
|
AE_PCMs32be,
|
||||||
|
|
||||||
|
AE_PCMu16be,
|
||||||
|
AE_PCMu20be,
|
||||||
|
AE_PCMu24be,
|
||||||
|
AE_PCMu32be,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NativeAudioMixerRegisters
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Reset Register
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
NAM_Reset = 0x00,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Master Volume Register
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
NAM_MasterVolume = 0x02,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Microphone Volume Register
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
NAM_MicrophoneVolume = 0x0E,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PCM Out Volume Register
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
NAM_PCMOutVolume = 0x18,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Select Record Input Register
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
NAM_SelectRecordInput = 0x1A,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Record Gain Register
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
NAM_RecordGain = 0x1C,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Record Gain Microphone Register
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
NAM_RecordGainMicrophone = 0x1E,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NativeAudioBusMasterRegisters
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Register box for PCM IN
|
||||||
|
* @note Length: below
|
||||||
|
*/
|
||||||
|
NABM_PCMInBox = 0x00,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register box for PCM OUT
|
||||||
|
* @note Length: below
|
||||||
|
*/
|
||||||
|
NABM_PCMOutBox = 0x10,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register box for Microphone
|
||||||
|
* @note Length: below
|
||||||
|
*/
|
||||||
|
NABM_MicrophoneBox = 0x20,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Global Control Register
|
||||||
|
* @note Length: dword
|
||||||
|
*/
|
||||||
|
NABM_GlobalControl = 0x2C, /* 0x30 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Global Status Register
|
||||||
|
* @note Length: dword
|
||||||
|
*/
|
||||||
|
NABM_GlobalStatus = 0x30, /* 0x34 */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NativeAudioBusMasterBoxOffsets
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Physical Address of Buffer Descriptor List
|
||||||
|
* @note Length: dword
|
||||||
|
*/
|
||||||
|
NABMBOFF_BufferDescriptorList = 0x00,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of Actual Processed Buffer Descriptor Entry
|
||||||
|
* @note Length: byte
|
||||||
|
*/
|
||||||
|
NABMBOFF_BufferDescriptorEntry = 0x04,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of all Descriptor Entries
|
||||||
|
* @note Length: byte
|
||||||
|
*/
|
||||||
|
NABMBOFF_DescriptorEntries = 0x05,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Status of transferring Data
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
NABMBOFF_Status = 0x06,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of transferred Samples in Actual Processed Entry
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
NABMBOFF_TransferredSamples = 0x08,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of next processed Buffer Entry
|
||||||
|
* @note Length: byte
|
||||||
|
*/
|
||||||
|
NABMBOFF_NextProcessedBufferEntry = 0x0A,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transfer Control
|
||||||
|
* @note Length: byte
|
||||||
|
*/
|
||||||
|
NABMBOFF_TransferControl = 0x0B,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum OutputPulseCodeModulationRegisters
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Physical Address of Buffer Descriptor List
|
||||||
|
* @note Length: dword
|
||||||
|
*/
|
||||||
|
PCMOUT_BufferDescriptorList = (int)NABM_PCMOutBox + (int)NABMBOFF_BufferDescriptorList,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of Actual Processed Buffer Descriptor Entry
|
||||||
|
* @note Length: byte
|
||||||
|
*/
|
||||||
|
PCMOUT_BufferDescriptorEntry = (int)NABM_PCMOutBox + (int)NABMBOFF_BufferDescriptorEntry,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of all Descriptor Entries
|
||||||
|
* @note Length: byte
|
||||||
|
*/
|
||||||
|
PCMOUT_DescriptorEntries = (int)NABM_PCMOutBox + (int)NABMBOFF_DescriptorEntries,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Status of transferring Data
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
PCMOUT_Status = (int)NABM_PCMOutBox + (int)NABMBOFF_Status,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of transferred Samples in Actual Processed Entry
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
PCMOUT_TransferredSamples = (int)NABM_PCMOutBox + (int)NABMBOFF_TransferredSamples,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of next processed Buffer Entry
|
||||||
|
* @note Length: byte
|
||||||
|
*/
|
||||||
|
PCMOUT_NextProcessedBufferEntry = (int)NABM_PCMOutBox + (int)NABMBOFF_NextProcessedBufferEntry,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transfer Control
|
||||||
|
* @note Length: byte
|
||||||
|
*/
|
||||||
|
PCMOUT_TransferControl = (int)NABM_PCMOutBox + (int)NABMBOFF_TransferControl,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TransferControlRegisters
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief DMA controller control
|
||||||
|
* 0 = Pause transfer
|
||||||
|
* 1 = Transfer sound data
|
||||||
|
*/
|
||||||
|
TC_DMAControllerControl = 0x01,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset
|
||||||
|
* 0 = Remove reset condition
|
||||||
|
* 1 = Reset this NABM register box, this bit is cleared by card when is reset complete
|
||||||
|
*/
|
||||||
|
TC_TransferReset = 0x02,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Last Buffer Entry Interrupt enable
|
||||||
|
* 0 = Disable interrupt
|
||||||
|
* 1 = Enable interrupt
|
||||||
|
*/
|
||||||
|
TC_LastBufferEntryInterruptEnable = 0x04,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief IOC Interrupt enable
|
||||||
|
* 0 = Disable interrupt
|
||||||
|
* 1 = Enable interrupt
|
||||||
|
*/
|
||||||
|
TC_IOCInterruptEnable = 0x08,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Fifo ERROR Interrupt enable
|
||||||
|
* 0 = Disable interrupt
|
||||||
|
* 1 = Enable interrupt
|
||||||
|
*/
|
||||||
|
TC_FifoERRORInterruptEnable = 0x10,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GlobalControlRegisters
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Global Interrupt Enable
|
||||||
|
* 0 = Disable Interrupts
|
||||||
|
* 1 = Enable Interrupts
|
||||||
|
*/
|
||||||
|
GC_GlobalInterruptEnable = 0x01,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cold reset
|
||||||
|
* 0 = Device is in reset and can not be used
|
||||||
|
* 1 = Resume to operational state
|
||||||
|
*/
|
||||||
|
GC_ColdReset = 0x02,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Warm reset
|
||||||
|
*/
|
||||||
|
GC_WarmReset = 0x04,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Shut down
|
||||||
|
* 0 = Device is powered
|
||||||
|
* 1 = Shut down
|
||||||
|
*/
|
||||||
|
GC_ShutDown = 0x08,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Channels for PCM Output
|
||||||
|
* 00 = 2 channels
|
||||||
|
* 01 = 4 channels
|
||||||
|
* 10 = 6 channels
|
||||||
|
* 11 = Reserved
|
||||||
|
*/
|
||||||
|
GC_ChannelsForPCMOutput = 0x30,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PCM Output mode
|
||||||
|
* 00 = 16 bit samples
|
||||||
|
* 01 = 20 bit samples
|
||||||
|
*/
|
||||||
|
GC_PCMOutputMode = 0xC0,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BufferDescriptorList
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Physical Address to sound data in memory
|
||||||
|
* @note Length: dword
|
||||||
|
*/
|
||||||
|
uint32_t Address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of samples in this buffer
|
||||||
|
* @note Length: word
|
||||||
|
*/
|
||||||
|
uint16_t SampleCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flags
|
||||||
|
* @note Length: word
|
||||||
|
*
|
||||||
|
* Bit 15 = Interrupt fired when data from this entry is transferred
|
||||||
|
* Bit 14 = Last entry of buffer, stop playing
|
||||||
|
* Other bits = Reserved
|
||||||
|
*/
|
||||||
|
uint16_t Flags;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct BARData
|
||||||
|
{
|
||||||
|
uint8_t Type;
|
||||||
|
uint16_t MixerAddress;
|
||||||
|
uint64_t BusMasterAddress;
|
||||||
|
};
|
||||||
|
|
||||||
|
int DriverEntry(void *);
|
||||||
|
int CallbackHandler(KernelCallback *);
|
||||||
|
int InterruptCallback(CPURegisters *);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_AC97_H__
|
278
Drivers/BuiltinDriverLoader.cpp
Normal file
278
Drivers/BuiltinDriverLoader.cpp
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "drv.hpp"
|
||||||
|
|
||||||
|
#include "AHCI/ahci.hpp"
|
||||||
|
#include "VMware/mouse.hpp"
|
||||||
|
#include "PersonalSystem2/mouse.hpp"
|
||||||
|
#include "ATA/ata.hpp"
|
||||||
|
#include "AudioCodec97/ac97.hpp"
|
||||||
|
#include "Realtek/rtl8139.hpp"
|
||||||
|
#include "AdvancedMicroDevices/pcnet.hpp"
|
||||||
|
#include "Intel/gigabit.hpp"
|
||||||
|
|
||||||
|
#include <pci.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../Core/Driver/api.hpp"
|
||||||
|
#include "../kernel.h"
|
||||||
|
#include "../DAPI.hpp"
|
||||||
|
#include "../Fex.hpp"
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||||
|
|
||||||
|
FexExtended AHCIExtendedHeader = {
|
||||||
|
.Driver = {
|
||||||
|
.Name = "Advanced Host Controller Interface",
|
||||||
|
.Type = FexDriverType_Storage,
|
||||||
|
.Callback = AdvancedHostControllerInterface::CallbackHandler,
|
||||||
|
.InterruptCallback = AdvancedHostControllerInterface::InterruptCallback,
|
||||||
|
.Bind = {
|
||||||
|
.Type = BIND_PCI,
|
||||||
|
.PCI = {
|
||||||
|
.VendorID = {0x8086, 0x15AD},
|
||||||
|
.DeviceID = {0x2922, 0x2829, 0x07E0},
|
||||||
|
.Class = 0x1,
|
||||||
|
.SubClass = 0x6,
|
||||||
|
.ProgIF = 0x1,
|
||||||
|
}}}};
|
||||||
|
|
||||||
|
FexExtended VMwareVirtualMouseExtendedHeader = {
|
||||||
|
.Driver = {
|
||||||
|
.Name = "VMware Virtual Mouse",
|
||||||
|
.Type = FexDriverType_Input,
|
||||||
|
.TypeFlags = FexDriverInputTypes_Mouse,
|
||||||
|
.OverrideOnConflict = true,
|
||||||
|
.Callback = VMwareMouse::CallbackHandler,
|
||||||
|
.InterruptCallback = VMwareMouse::InterruptCallback,
|
||||||
|
.Bind = {
|
||||||
|
.Type = BIND_INTERRUPT,
|
||||||
|
.Interrupt = {
|
||||||
|
.Vector = {12}, // IRQ12
|
||||||
|
}}}};
|
||||||
|
|
||||||
|
FexExtended PS2MouseExtendedHeader = {
|
||||||
|
.Driver = {
|
||||||
|
.Name = "PS/2 Mouse",
|
||||||
|
.Type = FexDriverType_Input,
|
||||||
|
.TypeFlags = FexDriverInputTypes_Mouse,
|
||||||
|
.Callback = PS2Mouse::CallbackHandler,
|
||||||
|
.InterruptCallback = PS2Mouse::InterruptCallback,
|
||||||
|
.Bind = {
|
||||||
|
.Type = BIND_INTERRUPT,
|
||||||
|
.Interrupt = {
|
||||||
|
.Vector = {12}, // IRQ12
|
||||||
|
}}}};
|
||||||
|
|
||||||
|
FexExtended ATAExtendedHeader = {
|
||||||
|
.Driver = {
|
||||||
|
.Name = "Advanced Technology Attachment",
|
||||||
|
.Type = FexDriverType_Storage,
|
||||||
|
.Callback = AdvancedTechnologyAttachment::CallbackHandler,
|
||||||
|
.InterruptCallback = AdvancedTechnologyAttachment::InterruptCallback,
|
||||||
|
.Bind = {
|
||||||
|
.Type = BIND_INTERRUPT,
|
||||||
|
.Interrupt = {
|
||||||
|
.Vector = {14, 15}, // IRQ14, IRQ15
|
||||||
|
}}}};
|
||||||
|
|
||||||
|
FexExtended AC97ExtendedHeader = {
|
||||||
|
.Driver = {
|
||||||
|
.Name = "Audio Codec '97 Driver",
|
||||||
|
.Type = FexDriverType_Audio,
|
||||||
|
.TypeFlags = FexDriverInputTypes_None,
|
||||||
|
.OverrideOnConflict = false,
|
||||||
|
.Callback = AudioCodec97::CallbackHandler,
|
||||||
|
.InterruptCallback = AudioCodec97::InterruptCallback,
|
||||||
|
.Bind = {
|
||||||
|
.Type = BIND_PCI,
|
||||||
|
.PCI = {
|
||||||
|
.VendorID = {0x8086},
|
||||||
|
.DeviceID = {0x2415},
|
||||||
|
.Class = 0x4,
|
||||||
|
.SubClass = 0x3,
|
||||||
|
.ProgIF = 0x0,
|
||||||
|
}}}};
|
||||||
|
|
||||||
|
FexExtended RTL8139ExtendedHeader = {
|
||||||
|
.Driver = {
|
||||||
|
.Name = "Realtek RTL8139",
|
||||||
|
.Type = FexDriverType_Network,
|
||||||
|
.Callback = RTL8139::CallbackHandler,
|
||||||
|
.InterruptCallback = RTL8139::InterruptCallback,
|
||||||
|
.Bind = {
|
||||||
|
.Type = BIND_PCI,
|
||||||
|
.PCI = {
|
||||||
|
.VendorID = {0x10EC},
|
||||||
|
.DeviceID = {0x8139},
|
||||||
|
.Class = 0x2,
|
||||||
|
.SubClass = 0x0,
|
||||||
|
.ProgIF = 0x0,
|
||||||
|
}}}};
|
||||||
|
|
||||||
|
FexExtended AMDPCNETExtendedHeader = {
|
||||||
|
.Driver = {
|
||||||
|
.Name = "Advanced Micro Devices PCNET",
|
||||||
|
.Type = FexDriverType_Network,
|
||||||
|
.Callback = PCNET::CallbackHandler,
|
||||||
|
.InterruptCallback = PCNET::InterruptCallback,
|
||||||
|
.Bind = {
|
||||||
|
.Type = BIND_PCI,
|
||||||
|
.PCI = {
|
||||||
|
.VendorID = {0x1022},
|
||||||
|
.DeviceID = {0x2000},
|
||||||
|
.Class = 0x2,
|
||||||
|
.SubClass = 0x0,
|
||||||
|
.ProgIF = 0x0,
|
||||||
|
}}}};
|
||||||
|
|
||||||
|
FexExtended IntelGigabitExtendedHeader = {
|
||||||
|
.Driver = {
|
||||||
|
.Name = "Intel Gigabit Ethernet Controller",
|
||||||
|
.Type = FexDriverType_Network,
|
||||||
|
.Callback = Gigabit::CallbackHandler,
|
||||||
|
.InterruptCallback = Gigabit::InterruptCallback,
|
||||||
|
.Bind = {
|
||||||
|
.Type = BIND_PCI,
|
||||||
|
.PCI = {
|
||||||
|
.VendorID = {0x8086},
|
||||||
|
.DeviceID = {0x100E, 0x100F, 0x10D3, 0x10EA, 0x153A},
|
||||||
|
.Class = 0x2,
|
||||||
|
.SubClass = 0x0,
|
||||||
|
.ProgIF = 0x0,
|
||||||
|
}}}};
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
std::vector<PCI::PCIDeviceHeader *> FindPCI(uint16_t VendorID[16], uint16_t DeviceID[16])
|
||||||
|
{
|
||||||
|
for (uint16_t Vidx = 0; Vidx < 16; Vidx++)
|
||||||
|
{
|
||||||
|
for (uint16_t Didx = 0; Didx < 16; Didx++)
|
||||||
|
{
|
||||||
|
if (VendorID[Vidx] == 0 || DeviceID[Didx] == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
std::vector<PCI::PCIDeviceHeader *> devices = PCIManager->FindPCIDevice(VendorID[Vidx], DeviceID[Didx]);
|
||||||
|
if (devices.size() == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
warn("No PCI device found");
|
||||||
|
return std::vector<PCI::PCIDeviceHeader *>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartAHCI()
|
||||||
|
{
|
||||||
|
Driver::BuiltInDriverInfo BIDI = {
|
||||||
|
.EntryPoint = AdvancedHostControllerInterface::DriverEntry,
|
||||||
|
.ExtendedHeader = &AHCIExtendedHeader};
|
||||||
|
|
||||||
|
if (DriverManager->DriverLoadBindPCI((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartVMwareMouse()
|
||||||
|
{
|
||||||
|
Driver::BuiltInDriverInfo BIDI = {
|
||||||
|
.EntryPoint = VMwareMouse::DriverEntry,
|
||||||
|
.ExtendedHeader = &VMwareVirtualMouseExtendedHeader};
|
||||||
|
|
||||||
|
if (DriverManager->DriverLoadBindInterrupt((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartPS2Mouse()
|
||||||
|
{
|
||||||
|
Driver::BuiltInDriverInfo BIDI = {
|
||||||
|
.EntryPoint = PS2Mouse::DriverEntry,
|
||||||
|
.ExtendedHeader = &PS2MouseExtendedHeader};
|
||||||
|
|
||||||
|
if (DriverManager->DriverLoadBindInterrupt((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartATA()
|
||||||
|
{
|
||||||
|
Driver::BuiltInDriverInfo BIDI = {
|
||||||
|
.EntryPoint = AdvancedTechnologyAttachment::DriverEntry,
|
||||||
|
.ExtendedHeader = &ATAExtendedHeader};
|
||||||
|
|
||||||
|
if (DriverManager->DriverLoadBindInterrupt((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartAC97()
|
||||||
|
{
|
||||||
|
Driver::BuiltInDriverInfo BIDI = {
|
||||||
|
.EntryPoint = AudioCodec97::DriverEntry,
|
||||||
|
.ExtendedHeader = &AC97ExtendedHeader};
|
||||||
|
|
||||||
|
if (DriverManager->DriverLoadBindPCI((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartRTL8139()
|
||||||
|
{
|
||||||
|
Driver::BuiltInDriverInfo BIDI = {
|
||||||
|
.EntryPoint = RTL8139::DriverEntry,
|
||||||
|
.ExtendedHeader = &RTL8139ExtendedHeader};
|
||||||
|
|
||||||
|
if (DriverManager->DriverLoadBindPCI((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartPCNET()
|
||||||
|
{
|
||||||
|
Driver::BuiltInDriverInfo BIDI = {
|
||||||
|
.EntryPoint = PCNET::DriverEntry,
|
||||||
|
.ExtendedHeader = &AMDPCNETExtendedHeader};
|
||||||
|
|
||||||
|
if (DriverManager->DriverLoadBindPCI((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartGigabit()
|
||||||
|
{
|
||||||
|
Driver::BuiltInDriverInfo BIDI = {
|
||||||
|
.EntryPoint = Gigabit::DriverEntry,
|
||||||
|
.ExtendedHeader = &IntelGigabitExtendedHeader};
|
||||||
|
|
||||||
|
if (DriverManager->DriverLoadBindPCI((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
369
Drivers/Intel/Gigabit.cpp
Normal file
369
Drivers/Intel/Gigabit.cpp
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
#include "gigabit.hpp"
|
||||||
|
|
||||||
|
#include <net/net.hpp>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <pci.hpp>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
#include "../drv.hpp"
|
||||||
|
|
||||||
|
using namespace PCI;
|
||||||
|
|
||||||
|
namespace Gigabit
|
||||||
|
{
|
||||||
|
KernelAPI KAPI;
|
||||||
|
|
||||||
|
PCIDeviceHeader *PCIBaseAddress;
|
||||||
|
uint32_t CurrentPacket;
|
||||||
|
BARData BAR;
|
||||||
|
bool EEPROMAvailable;
|
||||||
|
|
||||||
|
uint16_t RXCurrent;
|
||||||
|
uint16_t TXCurrent;
|
||||||
|
RXDescriptor *RX[E1000_NUM_RX_DESC];
|
||||||
|
TXDescriptor *TX[E1000_NUM_TX_DESC];
|
||||||
|
|
||||||
|
MediaAccessControl MAC;
|
||||||
|
InternetProtocol::Version4 IP;
|
||||||
|
|
||||||
|
void WriteCMD(uint16_t Address, uint32_t Value)
|
||||||
|
{
|
||||||
|
if (BAR.Type == 0)
|
||||||
|
mmioout32(BAR.MemoryBase + Address, Value);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outportl(BAR.IOBase, Address);
|
||||||
|
outportl(BAR.IOBase + 4, Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ReadCMD(uint16_t Address)
|
||||||
|
{
|
||||||
|
if (BAR.Type == 0)
|
||||||
|
return mmioin32(BAR.MemoryBase + Address);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outportl(BAR.IOBase, Address);
|
||||||
|
return inportl(BAR.IOBase + 0x4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ReadEEPROM(uint8_t Address)
|
||||||
|
{
|
||||||
|
uint16_t Data = 0;
|
||||||
|
uint32_t temp = 0;
|
||||||
|
if (EEPROMAvailable)
|
||||||
|
{
|
||||||
|
WriteCMD(REG::EEPROM, (1) | ((uint32_t)(Address) << 8));
|
||||||
|
while (!((temp = ReadCMD(REG::EEPROM)) & (1 << 4)))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteCMD(REG::EEPROM, (1) | ((uint32_t)(Address) << 2));
|
||||||
|
while (!((temp = ReadCMD(REG::EEPROM)) & (1 << 1)))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
Data = (uint16_t)((temp >> 16) & 0xFFFF);
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaAccessControl GetMAC()
|
||||||
|
{
|
||||||
|
MediaAccessControl mac;
|
||||||
|
if (EEPROMAvailable)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
temp = ReadEEPROM(0);
|
||||||
|
mac.Address[0] = temp & 0xff;
|
||||||
|
mac.Address[1] = (uint8_t)(temp >> 8);
|
||||||
|
temp = ReadEEPROM(1);
|
||||||
|
mac.Address[2] = temp & 0xff;
|
||||||
|
mac.Address[3] = (uint8_t)(temp >> 8);
|
||||||
|
temp = ReadEEPROM(2);
|
||||||
|
mac.Address[4] = temp & 0xff;
|
||||||
|
mac.Address[5] = (uint8_t)(temp >> 8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint8_t *BaseMac8 = (uint8_t *)(BAR.MemoryBase + 0x5400);
|
||||||
|
uint32_t *BaseMac32 = (uint32_t *)(BAR.MemoryBase + 0x5400);
|
||||||
|
if (BaseMac32[0] != 0)
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
mac.Address[i] = BaseMac8[i];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error("No MAC address found.");
|
||||||
|
return MediaAccessControl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mac;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeRX()
|
||||||
|
{
|
||||||
|
debug("Initializing RX...");
|
||||||
|
uintptr_t Ptr = (uintptr_t)KAPI.Memory.RequestPage((((sizeof(RXDescriptor) * E1000_NUM_RX_DESC + 16)) / KAPI.Memory.PageSize) + 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < E1000_NUM_RX_DESC; i++)
|
||||||
|
{
|
||||||
|
RX[i] = (RXDescriptor *)(Ptr + i * 16);
|
||||||
|
RX[i]->Address = (uint64_t)(uintptr_t)KAPI.Memory.RequestPage(((8192 + 16) / KAPI.Memory.PageSize) + 1);
|
||||||
|
RX[i]->Status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteCMD(REG::TXDESCLO, (uint32_t)(Ptr >> 32));
|
||||||
|
WriteCMD(REG::TXDESCHI, (uint32_t)(Ptr & 0xFFFFFFFF));
|
||||||
|
|
||||||
|
WriteCMD(REG::RXDESCLO, (uint32_t)Ptr);
|
||||||
|
WriteCMD(REG::RXDESCHI, 0);
|
||||||
|
|
||||||
|
WriteCMD(REG::RXDESCLEN, E1000_NUM_RX_DESC * 16);
|
||||||
|
|
||||||
|
WriteCMD(REG::RXDESCHEAD, 0);
|
||||||
|
WriteCMD(REG::RXDESCTAIL, E1000_NUM_RX_DESC - 1);
|
||||||
|
RXCurrent = 0;
|
||||||
|
WriteCMD(REG::RCTRL, RCTL::EN | RCTL::SBP | RCTL::UPE | RCTL::MPE | RCTL::LBM_NONE | RTCL::RDMTS_HALF | RCTL::BAM | RCTL::SECRC | RCTL::BSIZE_8192);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeTX()
|
||||||
|
{
|
||||||
|
debug("Initializing TX...");
|
||||||
|
uintptr_t Ptr = (uintptr_t)KAPI.Memory.RequestPage(((sizeof(TXDescriptor) * E1000_NUM_RX_DESC + 16) / KAPI.Memory.PageSize) + 1);
|
||||||
|
|
||||||
|
for (short i = 0; i < E1000_NUM_TX_DESC; i++)
|
||||||
|
{
|
||||||
|
TX[i] = (TXDescriptor *)((uintptr_t)Ptr + i * 16);
|
||||||
|
TX[i]->Address = 0;
|
||||||
|
TX[i]->Command = 0;
|
||||||
|
TX[i]->Status = TSTA::DD;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteCMD(REG::TXDESCHI, (uint32_t)((uint64_t)Ptr >> 32));
|
||||||
|
WriteCMD(REG::TXDESCLO, (uint32_t)((uint64_t)Ptr & 0xFFFFFFFF));
|
||||||
|
|
||||||
|
WriteCMD(REG::TXDESCLEN, E1000_NUM_TX_DESC * 16);
|
||||||
|
|
||||||
|
WriteCMD(REG::TXDESCHEAD, 0);
|
||||||
|
WriteCMD(REG::TXDESCTAIL, 0);
|
||||||
|
TXCurrent = 0;
|
||||||
|
WriteCMD(REG::TCTRL, TCTL::EN_ | TCTL::PSP | (15 << TCTL::CT_SHIFT) | (64 << TCTL::COLD_SHIFT) | TCTL::RTLC);
|
||||||
|
|
||||||
|
WriteCMD(REG::TCTRL, 0b0110000000000111111000011111010);
|
||||||
|
WriteCMD(REG::TIPG, 0x0060200A);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DriverEntry(void *Data)
|
||||||
|
{
|
||||||
|
if (!Data)
|
||||||
|
return INVALID_KERNEL_API;
|
||||||
|
KAPI = *(KernelAPI *)Data;
|
||||||
|
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
|
||||||
|
return KERNEL_API_VERSION_NOT_SUPPORTED;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CallbackHandler(KernelCallback *Data)
|
||||||
|
{
|
||||||
|
switch (Data->Reason)
|
||||||
|
{
|
||||||
|
case AcknowledgeReason:
|
||||||
|
{
|
||||||
|
debug("Kernel acknowledged the driver.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ConfigurationReason:
|
||||||
|
{
|
||||||
|
debug("Driver received configuration data.");
|
||||||
|
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
|
||||||
|
switch (PCIBaseAddress->DeviceID)
|
||||||
|
{
|
||||||
|
case 0x100E:
|
||||||
|
{
|
||||||
|
trace("Found Intel 82540EM Gigabit Ethernet Controller.");
|
||||||
|
|
||||||
|
PCIBaseAddress->Command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
|
||||||
|
uint32_t PCIBAR0 = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
|
||||||
|
uint32_t PCIBAR1 = ((PCIHeader0 *)PCIBaseAddress)->BAR1;
|
||||||
|
|
||||||
|
BAR.Type = PCIBAR0 & 1;
|
||||||
|
BAR.IOBase = (uint16_t)(PCIBAR1 & (~3));
|
||||||
|
BAR.MemoryBase = PCIBAR0 & (~15);
|
||||||
|
|
||||||
|
// Detect EEPROM
|
||||||
|
WriteCMD(REG::EEPROM, 0x1);
|
||||||
|
for (int i = 0; i < 1000 && !EEPROMAvailable; i++)
|
||||||
|
if (ReadCMD(REG::EEPROM) & 0x10)
|
||||||
|
EEPROMAvailable = true;
|
||||||
|
else
|
||||||
|
EEPROMAvailable = false;
|
||||||
|
|
||||||
|
// Get MAC address
|
||||||
|
if (!GetMAC().Valid())
|
||||||
|
return NOT_AVAILABLE;
|
||||||
|
else
|
||||||
|
debug("MAC address found.");
|
||||||
|
MAC = GetMAC();
|
||||||
|
|
||||||
|
// Start link
|
||||||
|
uint32_t cmdret = ReadCMD(REG::CTRL);
|
||||||
|
WriteCMD(REG::CTRL, cmdret | ECTRL::SLU);
|
||||||
|
|
||||||
|
for (int i = 0; i < 0x80; i++)
|
||||||
|
WriteCMD((uint16_t)(0x5200 + i * 4), 0);
|
||||||
|
|
||||||
|
WriteCMD(REG::IMASK, 0x1F6DC);
|
||||||
|
WriteCMD(REG::IMASK, 0xFF & ~4);
|
||||||
|
ReadCMD(0xC0);
|
||||||
|
|
||||||
|
InitializeRX();
|
||||||
|
InitializeTX();
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
case 0x100F:
|
||||||
|
{
|
||||||
|
trace("Found Intel 82545EM Gigabit Ethernet Controller.");
|
||||||
|
PCIBaseAddress->Command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
|
||||||
|
uint32_t PCIBAR0 = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
|
||||||
|
uint32_t PCIBAR1 = ((PCIHeader0 *)PCIBaseAddress)->BAR1;
|
||||||
|
|
||||||
|
BAR.Type = PCIBAR0 & 1;
|
||||||
|
BAR.IOBase = (uint16_t)(PCIBAR1 & (~3));
|
||||||
|
BAR.MemoryBase = PCIBAR0 & (~15);
|
||||||
|
|
||||||
|
// Detect EEPROM
|
||||||
|
WriteCMD(REG::EEPROM, 0x1);
|
||||||
|
for (int i = 0; i < 1000 && !EEPROMAvailable; i++)
|
||||||
|
if (ReadCMD(REG::EEPROM) & 0x10)
|
||||||
|
EEPROMAvailable = true;
|
||||||
|
else
|
||||||
|
EEPROMAvailable = false;
|
||||||
|
|
||||||
|
// Get MAC address
|
||||||
|
if (!GetMAC().Valid())
|
||||||
|
return NOT_AVAILABLE;
|
||||||
|
else
|
||||||
|
debug("MAC address found.");
|
||||||
|
MAC = GetMAC();
|
||||||
|
|
||||||
|
return NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
case 0x10D3:
|
||||||
|
{
|
||||||
|
trace("Found Intel 82574L Gigabit Ethernet Controller.");
|
||||||
|
|
||||||
|
PCIBaseAddress->Command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
|
||||||
|
uint32_t PCIBAR0 = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
|
||||||
|
uint32_t PCIBAR1 = ((PCIHeader0 *)PCIBaseAddress)->BAR1;
|
||||||
|
|
||||||
|
BAR.Type = PCIBAR0 & 1;
|
||||||
|
BAR.IOBase = (uint16_t)(PCIBAR1 & (~3));
|
||||||
|
BAR.MemoryBase = PCIBAR0 & (~15);
|
||||||
|
|
||||||
|
// Detect EEPROM
|
||||||
|
WriteCMD(REG::EEPROM, 0x1);
|
||||||
|
for (int i = 0; i < 1000 && !EEPROMAvailable; i++)
|
||||||
|
if (ReadCMD(REG::EEPROM) & 0x10)
|
||||||
|
EEPROMAvailable = true;
|
||||||
|
else
|
||||||
|
EEPROMAvailable = false;
|
||||||
|
|
||||||
|
// Get MAC address
|
||||||
|
if (!GetMAC().Valid())
|
||||||
|
return NOT_AVAILABLE;
|
||||||
|
else
|
||||||
|
debug("MAC address found.");
|
||||||
|
MAC = GetMAC();
|
||||||
|
|
||||||
|
return NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
case 0x10EA:
|
||||||
|
{
|
||||||
|
fixme("Found Intel I217-LM Gigabit Ethernet Controller.");
|
||||||
|
return NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
case 0x153A:
|
||||||
|
{
|
||||||
|
fixme("Found Intel 82577LM Gigabit Ethernet Controller.");
|
||||||
|
return NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
error("Unsupported Intel Ethernet Controller.");
|
||||||
|
return DEVICE_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
case FetchReason:
|
||||||
|
{
|
||||||
|
memcpy(Data->NetworkCallback.Fetch.Name, (void *)"Intel Gigabit Ethernet Controller", 34);
|
||||||
|
Data->NetworkCallback.Fetch.MAC = MAC.ToHex();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SendReason:
|
||||||
|
{
|
||||||
|
TX[TXCurrent]->Address = (uint64_t)Data->NetworkCallback.Send.Data;
|
||||||
|
TX[TXCurrent]->Length = (uint16_t)Data->NetworkCallback.Send.Length;
|
||||||
|
TX[TXCurrent]->Command = CMD::EOP | CMD::IFCS | CMD::RS;
|
||||||
|
TX[TXCurrent]->Status = 0;
|
||||||
|
uint16_t OldTXCurrent = TXCurrent;
|
||||||
|
TXCurrent = (uint16_t)((TXCurrent + 1) % E1000_NUM_TX_DESC);
|
||||||
|
WriteCMD(REG::TXDESCTAIL, TXCurrent);
|
||||||
|
while (!(TX[OldTXCurrent]->Status & 0xFF))
|
||||||
|
;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StopReason:
|
||||||
|
{
|
||||||
|
// Clearing Enable bit in Receive Control Register
|
||||||
|
uint32_t cmdret = ReadCMD(REG::RCTRL);
|
||||||
|
WriteCMD(REG::RCTRL, cmdret & ~RCTL::EN);
|
||||||
|
|
||||||
|
// Masking Interrupt Mask, Interrupt Throttling Rate & Interrupt Auto-Mask
|
||||||
|
WriteCMD(REG::IMASK, 0x00000000);
|
||||||
|
WriteCMD(REG::ITR, 0x00000000);
|
||||||
|
WriteCMD(REG::IAM, 0x00000000);
|
||||||
|
|
||||||
|
// Clearing SLU bit in Device Control Register
|
||||||
|
cmdret = ReadCMD(REG::CTRL);
|
||||||
|
WriteCMD(REG::CTRL, cmdret & ~ECTRL::SLU);
|
||||||
|
|
||||||
|
// Clear the Interrupt Cause Read register by reading it
|
||||||
|
ReadCMD(REG::ICR);
|
||||||
|
|
||||||
|
// Powering down the device (?)
|
||||||
|
WriteCMD(REG::CTRL, PCTRL::POWER_DOWN);
|
||||||
|
/* TODO: Stop link; further testing required */
|
||||||
|
debug("Driver stopped.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown reason.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InterruptCallback(CPURegisters *)
|
||||||
|
{
|
||||||
|
WriteCMD(REG::IMASK, 0x1);
|
||||||
|
uint32_t status = ReadCMD(0xC0);
|
||||||
|
UNUSED(status);
|
||||||
|
|
||||||
|
while ((RX[RXCurrent]->Status & 0x1))
|
||||||
|
{
|
||||||
|
uint8_t *Data = (uint8_t *)RX[RXCurrent]->Address;
|
||||||
|
uint16_t DataLength = RX[RXCurrent]->Length;
|
||||||
|
KAPI.Command.Network.ReceivePacket(KAPI.Info.DriverUID, Data, DataLength);
|
||||||
|
RX[RXCurrent]->Status = 0;
|
||||||
|
uint16_t OldRXCurrent = RXCurrent;
|
||||||
|
RXCurrent = (uint16_t)((RXCurrent + 1) % E1000_NUM_RX_DESC);
|
||||||
|
WriteCMD(REG::RXDESCTAIL, OldRXCurrent);
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
177
Drivers/Intel/gigabit.hpp
Normal file
177
Drivers/Intel/gigabit.hpp
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_INTEL_GIGABIT_H__
|
||||||
|
#define __FENNIX_KERNEL_INTEL_GIGABIT_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
|
||||||
|
namespace Gigabit
|
||||||
|
{
|
||||||
|
#define E1000_NUM_RX_DESC 32
|
||||||
|
#define E1000_NUM_TX_DESC 8
|
||||||
|
|
||||||
|
enum REG
|
||||||
|
{
|
||||||
|
CTRL = 0x0000,
|
||||||
|
STATUS = 0x0008,
|
||||||
|
ICR = 0x000C,
|
||||||
|
EEPROM = 0x0014,
|
||||||
|
CTRL_EXT = 0x0018,
|
||||||
|
ITR = 0x00C4,
|
||||||
|
IMASK = 0x00D0,
|
||||||
|
IAM = 0x00D8,
|
||||||
|
RCTRL = 0x0100,
|
||||||
|
RXDESCLO = 0x2800,
|
||||||
|
RXDESCHI = 0x2804,
|
||||||
|
RXDESCLEN = 0x2808,
|
||||||
|
RXDESCHEAD = 0x2810,
|
||||||
|
RXDESCTAIL = 0x2818,
|
||||||
|
TCTRL = 0x0400,
|
||||||
|
TXDESCLO = 0x3800,
|
||||||
|
TXDESCHI = 0x3804,
|
||||||
|
TXDESCLEN = 0x3808,
|
||||||
|
TXDESCHEAD = 0x3810,
|
||||||
|
TXDESCTAIL = 0x3818,
|
||||||
|
RDTR = 0x2820,
|
||||||
|
RXDCTL = 0x3828,
|
||||||
|
RADV = 0x282C,
|
||||||
|
RSRPD = 0x2C00,
|
||||||
|
TIPG = 0x0410
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PCTRL
|
||||||
|
{
|
||||||
|
RESERVED = 0b000000, // bits 5:0
|
||||||
|
SPEED_SELECTION_MSB = 0b010000, // bit 6
|
||||||
|
UPDATE_COLLISION_TEST = 0b001000, // bit 7
|
||||||
|
DUPLEX_MODE = 0b000100, // bit 8
|
||||||
|
RESTART_AUTO_NEGOTIATION = 0b000010, // bit 9
|
||||||
|
ISOLATE = 0b000001, // bit 10
|
||||||
|
POWER_DOWN = 0b100000, // bit 11
|
||||||
|
SPEED_SELECTION_LSB = 0b100000, // bit 13
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ECTRL
|
||||||
|
{
|
||||||
|
SLU = 0x40
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RTCL
|
||||||
|
{
|
||||||
|
RDMTS_HALF = (0 << 8),
|
||||||
|
RDMTS_QUARTER = (1 << 8),
|
||||||
|
RDMTS_EIGHTH = (2 << 8)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RCTL
|
||||||
|
{
|
||||||
|
EN = (1 << 1),
|
||||||
|
SBP = (1 << 2),
|
||||||
|
UPE = (1 << 3),
|
||||||
|
MPE = (1 << 4),
|
||||||
|
LPE = (1 << 5),
|
||||||
|
LBM_NONE = (0 << 6),
|
||||||
|
LBM_PHY = (3 << 6),
|
||||||
|
MO_36 = (0 << 12),
|
||||||
|
MO_35 = (1 << 12),
|
||||||
|
MO_34 = (2 << 12),
|
||||||
|
MO_32 = (3 << 12),
|
||||||
|
BAM = (1 << 15),
|
||||||
|
VFE = (1 << 18),
|
||||||
|
CFIEN = (1 << 19),
|
||||||
|
CFI = (1 << 20),
|
||||||
|
DPF = (1 << 22),
|
||||||
|
PMCF = (1 << 23),
|
||||||
|
SECRC = (1 << 26),
|
||||||
|
BSIZE_256 = (3 << 16),
|
||||||
|
BSIZE_512 = (2 << 16),
|
||||||
|
BSIZE_1024 = (1 << 16),
|
||||||
|
BSIZE_2048 = (0 << 16),
|
||||||
|
BSIZE_4096 = ((3 << 16) | (1 << 25)),
|
||||||
|
BSIZE_8192 = ((2 << 16) | (1 << 25)),
|
||||||
|
BSIZE_16384 = ((1 << 16) | (1 << 25))
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CMD
|
||||||
|
{
|
||||||
|
EOP = (1 << 0),
|
||||||
|
IFCS = (1 << 1),
|
||||||
|
IC = (1 << 2),
|
||||||
|
RS = (1 << 3),
|
||||||
|
RPS = (1 << 4),
|
||||||
|
VLE = (1 << 6),
|
||||||
|
IDE = (1 << 7)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TCTL
|
||||||
|
{
|
||||||
|
EN_ = (1 << 1),
|
||||||
|
PSP = (1 << 3),
|
||||||
|
CT_SHIFT = 4,
|
||||||
|
COLD_SHIFT = 12,
|
||||||
|
SWXOFF = (1 << 22),
|
||||||
|
RTLC = (1 << 24)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TSTA
|
||||||
|
{
|
||||||
|
DD = (1 << 0),
|
||||||
|
EC = (1 << 1),
|
||||||
|
LC = (1 << 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LSTA
|
||||||
|
{
|
||||||
|
LSTA_TU = (1 << 3)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RXDescriptor
|
||||||
|
{
|
||||||
|
volatile uint64_t Address;
|
||||||
|
volatile uint16_t Length;
|
||||||
|
volatile uint16_t Checksum;
|
||||||
|
volatile uint8_t Status;
|
||||||
|
volatile uint8_t Errors;
|
||||||
|
volatile uint16_t Special;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct TXDescriptor
|
||||||
|
{
|
||||||
|
volatile uint64_t Address;
|
||||||
|
volatile uint16_t Length;
|
||||||
|
volatile uint8_t cso;
|
||||||
|
volatile uint8_t Command;
|
||||||
|
volatile uint8_t Status;
|
||||||
|
volatile uint8_t css;
|
||||||
|
volatile uint16_t Special;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct BARData
|
||||||
|
{
|
||||||
|
uint8_t Type;
|
||||||
|
uint16_t IOBase;
|
||||||
|
uint64_t MemoryBase;
|
||||||
|
};
|
||||||
|
|
||||||
|
int DriverEntry(void *);
|
||||||
|
int CallbackHandler(KernelCallback *);
|
||||||
|
int InterruptCallback(CPURegisters *);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_INTEL_GIGABIT_H__
|
234
Drivers/PersonalSystem2/Mouse.cpp
Normal file
234
Drivers/PersonalSystem2/Mouse.cpp
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
#include "mouse.hpp"
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
#include "../drv.hpp"
|
||||||
|
|
||||||
|
namespace PS2Mouse
|
||||||
|
{
|
||||||
|
KernelAPI KAPI;
|
||||||
|
|
||||||
|
int MouseX = 0, MouseY = 0, MouseZ = 0;
|
||||||
|
int MouseLeft = 0, MouseMiddle = 0, MouseRight = 0;
|
||||||
|
|
||||||
|
uint8_t Packet[4];
|
||||||
|
bool PacketReady = false;
|
||||||
|
uint8_t Cycle = 0;
|
||||||
|
|
||||||
|
void WaitRead()
|
||||||
|
{
|
||||||
|
uint64_t Timeout = 100000;
|
||||||
|
while (Timeout--)
|
||||||
|
if (inb(Ports::STATUS) & State::OUTPUT_FULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitWrite()
|
||||||
|
{
|
||||||
|
uint64_t Timeout = 100000;
|
||||||
|
while (Timeout--)
|
||||||
|
if ((inb(Ports::STATUS) & State::INPUT_FULL) == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Read()
|
||||||
|
{
|
||||||
|
WaitRead();
|
||||||
|
return inb(Ports::DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(uint16_t Port, uint8_t Value)
|
||||||
|
{
|
||||||
|
WaitWrite();
|
||||||
|
outb(Port, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DriverEntry(void *Data)
|
||||||
|
{
|
||||||
|
if (!Data)
|
||||||
|
return INVALID_KERNEL_API;
|
||||||
|
KAPI = *(KernelAPI *)Data;
|
||||||
|
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
|
||||||
|
return KERNEL_API_VERSION_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CallbackHandler(KernelCallback *Data)
|
||||||
|
{
|
||||||
|
switch (Data->Reason)
|
||||||
|
{
|
||||||
|
case AcknowledgeReason:
|
||||||
|
{
|
||||||
|
debug("Kernel acknowledged the driver.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ConfigurationReason:
|
||||||
|
{
|
||||||
|
outb(COMMAND, 0xA8);
|
||||||
|
Write(COMMAND, READ_CONFIG);
|
||||||
|
uint8_t Status = Read();
|
||||||
|
Status |= 0b10;
|
||||||
|
Write(COMMAND, WRITE_CONFIG);
|
||||||
|
Write(DATA, Status);
|
||||||
|
Write(COMMAND, 0xD4);
|
||||||
|
Write(DATA, 0xF6);
|
||||||
|
Read();
|
||||||
|
Write(COMMAND, 0xD4);
|
||||||
|
Write(DATA, 0xF4);
|
||||||
|
Read();
|
||||||
|
|
||||||
|
trace("PS/2 mouse configured.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FetchReason:
|
||||||
|
{
|
||||||
|
Data->InputCallback.Mouse.X = MouseX;
|
||||||
|
Data->InputCallback.Mouse.Y = MouseY;
|
||||||
|
Data->InputCallback.Mouse.Z = MouseZ;
|
||||||
|
Data->InputCallback.Mouse.Buttons.Left = MouseLeft;
|
||||||
|
Data->InputCallback.Mouse.Buttons.Right = MouseRight;
|
||||||
|
Data->InputCallback.Mouse.Buttons.Middle = MouseMiddle;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StopReason:
|
||||||
|
{
|
||||||
|
outb(COMMAND, 0xA8);
|
||||||
|
Write(COMMAND, READ_CONFIG);
|
||||||
|
uint8_t Status = Read();
|
||||||
|
Status &= ~0b10;
|
||||||
|
Write(COMMAND, WRITE_CONFIG);
|
||||||
|
Write(DATA, Status);
|
||||||
|
Write(COMMAND, 0xD4);
|
||||||
|
Write(DATA, 0xF5);
|
||||||
|
Read();
|
||||||
|
|
||||||
|
debug("Driver stopped.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown reason.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InterruptCallback(CPURegisters *)
|
||||||
|
{
|
||||||
|
uint8_t Data = inb(0x60);
|
||||||
|
|
||||||
|
if (__builtin_expect(!!(PacketReady), 0))
|
||||||
|
{
|
||||||
|
bool XNegative, YNegative, XOverflow, YOverflow;
|
||||||
|
|
||||||
|
if (Packet[0] & PS2XSign)
|
||||||
|
XNegative = true;
|
||||||
|
else
|
||||||
|
XNegative = false;
|
||||||
|
|
||||||
|
if (Packet[0] & PS2YSign)
|
||||||
|
YNegative = true;
|
||||||
|
else
|
||||||
|
YNegative = false;
|
||||||
|
|
||||||
|
if (Packet[0] & PS2XOverflow)
|
||||||
|
XOverflow = true;
|
||||||
|
else
|
||||||
|
XOverflow = false;
|
||||||
|
|
||||||
|
if (Packet[0] & PS2YOverflow)
|
||||||
|
YOverflow = true;
|
||||||
|
else
|
||||||
|
YOverflow = false;
|
||||||
|
|
||||||
|
if (!XNegative)
|
||||||
|
{
|
||||||
|
MouseX += Packet[1];
|
||||||
|
if (XOverflow)
|
||||||
|
MouseX += 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Packet[1] = (uint8_t)(256 - Packet[1]);
|
||||||
|
MouseX -= Packet[1];
|
||||||
|
if (XOverflow)
|
||||||
|
MouseX -= 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!YNegative)
|
||||||
|
{
|
||||||
|
MouseY -= Packet[2];
|
||||||
|
if (YOverflow)
|
||||||
|
MouseY -= 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Packet[2] = (uint8_t)(256 - Packet[2]);
|
||||||
|
MouseY += Packet[2];
|
||||||
|
if (YOverflow)
|
||||||
|
MouseY += 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Width = KAPI.Display.GetWidth();
|
||||||
|
uint32_t Height = KAPI.Display.GetHeight();
|
||||||
|
|
||||||
|
if (MouseX < 0)
|
||||||
|
MouseX = 0;
|
||||||
|
|
||||||
|
if ((uint32_t)MouseX > Width - 1)
|
||||||
|
MouseX = Width - 1;
|
||||||
|
|
||||||
|
if (MouseY < 0)
|
||||||
|
MouseY = 0;
|
||||||
|
if ((uint32_t)MouseY > Height - 1)
|
||||||
|
MouseY = Height - 1;
|
||||||
|
|
||||||
|
MouseLeft = 0;
|
||||||
|
MouseMiddle = 0;
|
||||||
|
MouseRight = 0;
|
||||||
|
|
||||||
|
if (Packet[0] & PS2LeftButton)
|
||||||
|
MouseLeft = 1;
|
||||||
|
if (Packet[0] & PS2MiddleButton)
|
||||||
|
MouseMiddle = 1;
|
||||||
|
if (Packet[0] & PS2RightButton)
|
||||||
|
MouseRight = 1;
|
||||||
|
PacketReady = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Cycle)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
if ((Data & 0b00001000) == 0)
|
||||||
|
break;
|
||||||
|
Packet[0] = Data;
|
||||||
|
Cycle++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
Packet[1] = Data;
|
||||||
|
Cycle++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
Packet[2] = Data;
|
||||||
|
PacketReady = true;
|
||||||
|
Cycle = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown cycle %d", Cycle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
59
Drivers/PersonalSystem2/mouse.hpp
Normal file
59
Drivers/PersonalSystem2/mouse.hpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_PS2_MOUSE_H__
|
||||||
|
#define __FENNIX_KERNEL_PS2_MOUSE_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
|
||||||
|
namespace PS2Mouse
|
||||||
|
{
|
||||||
|
#define PS2LeftButton 0b00000001
|
||||||
|
#define PS2MiddleButton 0b00000100
|
||||||
|
#define PS2RightButton 0b00000010
|
||||||
|
#define PS2XSign 0b00010000
|
||||||
|
#define PS2YSign 0b00100000
|
||||||
|
#define PS2XOverflow 0b01000000
|
||||||
|
#define PS2YOverflow 0b10000000
|
||||||
|
|
||||||
|
enum Config
|
||||||
|
{
|
||||||
|
READ_CONFIG = 0x20,
|
||||||
|
WRITE_CONFIG = 0x60
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Ports
|
||||||
|
{
|
||||||
|
DATA = 0x60,
|
||||||
|
STATUS = 0x64,
|
||||||
|
COMMAND = 0x64,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum State
|
||||||
|
{
|
||||||
|
OUTPUT_FULL = (1 << 0),
|
||||||
|
INPUT_FULL = (1 << 1),
|
||||||
|
MOUSE_BYTE = (1 << 5)
|
||||||
|
};
|
||||||
|
|
||||||
|
int DriverEntry(void *);
|
||||||
|
int CallbackHandler(KernelCallback *);
|
||||||
|
int InterruptCallback(CPURegisters *);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_PS2_MOUSE_H__
|
190
Drivers/Realtek/RTL8139.cpp
Normal file
190
Drivers/Realtek/RTL8139.cpp
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
#include "rtl8139.hpp"
|
||||||
|
|
||||||
|
#include <net/net.hpp>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <pci.hpp>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
#include "../drv.hpp"
|
||||||
|
|
||||||
|
using namespace PCI;
|
||||||
|
|
||||||
|
namespace RTL8139
|
||||||
|
{
|
||||||
|
KernelAPI KAPI;
|
||||||
|
|
||||||
|
PCIDeviceHeader *PCIBaseAddress;
|
||||||
|
BARData BAR;
|
||||||
|
|
||||||
|
uint8_t *RXBuffer;
|
||||||
|
int TXCurrent;
|
||||||
|
uint16_t CurrentPacket;
|
||||||
|
|
||||||
|
MediaAccessControl MAC;
|
||||||
|
InternetProtocol::Version4 IP;
|
||||||
|
|
||||||
|
uint8_t TSAD[4] = {0x20, 0x24, 0x28, 0x2C};
|
||||||
|
uint8_t TSD[4] = {0x10, 0x14, 0x18, 0x1C};
|
||||||
|
|
||||||
|
void RTLOB(uint16_t Address, uint8_t Value)
|
||||||
|
{
|
||||||
|
if (BAR.Type == 0)
|
||||||
|
mmoutb(reinterpret_cast<void *>(BAR.MemoryBase + Address), Value);
|
||||||
|
else
|
||||||
|
outportb(BAR.IOBase + Address, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTLOW(uint16_t Address, uint16_t Value)
|
||||||
|
{
|
||||||
|
if (BAR.Type == 0)
|
||||||
|
mmoutw(reinterpret_cast<void *>(BAR.MemoryBase + Address), Value);
|
||||||
|
else
|
||||||
|
outportw(BAR.IOBase + Address, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTLOL(uint16_t Address, uint32_t Value)
|
||||||
|
{
|
||||||
|
if (BAR.Type == 0)
|
||||||
|
mmoutl(reinterpret_cast<void *>(BAR.MemoryBase + Address), Value);
|
||||||
|
else
|
||||||
|
outportl(BAR.IOBase + Address, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t RTLIB(uint16_t Address)
|
||||||
|
{
|
||||||
|
if (BAR.Type == 0)
|
||||||
|
return mminb(reinterpret_cast<void *>(BAR.MemoryBase + Address));
|
||||||
|
else
|
||||||
|
return inportb(BAR.IOBase + Address);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t RTLIW(uint16_t Address)
|
||||||
|
{
|
||||||
|
if (BAR.Type == 0)
|
||||||
|
return mminw(reinterpret_cast<void *>(BAR.MemoryBase + Address));
|
||||||
|
else
|
||||||
|
return inportw(BAR.IOBase + Address);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t RTLIL(uint16_t Address)
|
||||||
|
{
|
||||||
|
if (BAR.Type == 0)
|
||||||
|
return mminl(reinterpret_cast<void *>(BAR.MemoryBase + Address));
|
||||||
|
else
|
||||||
|
return inportl(BAR.IOBase + Address);
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaAccessControl GetMAC()
|
||||||
|
{
|
||||||
|
uint32_t MAC1 = RTLIL(0x0);
|
||||||
|
uint16_t MAC2 = RTLIW(0x4);
|
||||||
|
MediaAccessControl mac = {
|
||||||
|
mac.Address[0] = (uint8_t)MAC1,
|
||||||
|
mac.Address[1] = (uint8_t)(MAC1 >> 8),
|
||||||
|
mac.Address[2] = (uint8_t)(MAC1 >> 16),
|
||||||
|
mac.Address[3] = (uint8_t)(MAC1 >> 24),
|
||||||
|
mac.Address[4] = (uint8_t)MAC2,
|
||||||
|
mac.Address[5] = (uint8_t)(MAC2 >> 8)};
|
||||||
|
return mac;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DriverEntry(void *Data)
|
||||||
|
{
|
||||||
|
if (!Data)
|
||||||
|
return INVALID_KERNEL_API;
|
||||||
|
KAPI = *(KernelAPI *)Data;
|
||||||
|
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
|
||||||
|
return KERNEL_API_VERSION_NOT_SUPPORTED;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CallbackHandler(KernelCallback *Data)
|
||||||
|
{
|
||||||
|
switch (Data->Reason)
|
||||||
|
{
|
||||||
|
case AcknowledgeReason:
|
||||||
|
{
|
||||||
|
debug("Kernel acknowledged the driver.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ConfigurationReason:
|
||||||
|
{
|
||||||
|
debug("Driver received configuration data.");
|
||||||
|
PCIBaseAddress = reinterpret_cast<PCIDeviceHeader *>(Data->RawPtr);
|
||||||
|
if (PCIBaseAddress->VendorID == 0x10EC && PCIBaseAddress->DeviceID == 0x8139)
|
||||||
|
{
|
||||||
|
trace("Found RTL-8139.");
|
||||||
|
|
||||||
|
PCIBaseAddress->Command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
|
||||||
|
uint32_t PCIBAR0 = ((PCIHeader0 *)PCIBaseAddress)->BAR0;
|
||||||
|
uint32_t PCIBAR1 = ((PCIHeader0 *)PCIBaseAddress)->BAR1;
|
||||||
|
|
||||||
|
BAR.Type = PCIBAR1 & 1;
|
||||||
|
BAR.IOBase = (uint16_t)(PCIBAR0 & (~3));
|
||||||
|
BAR.MemoryBase = PCIBAR1 & (~15);
|
||||||
|
|
||||||
|
RXBuffer = (uint8_t *)KAPI.Memory.RequestPage(2);
|
||||||
|
RTLOB(0x52, 0x0);
|
||||||
|
RTLOB(0x37, (1 << 4));
|
||||||
|
while ((RTLIB(0x37) & (1 << 4)))
|
||||||
|
;
|
||||||
|
RTLOL(0x30, static_cast<uint32_t>(reinterpret_cast<uint64_t>(RXBuffer)));
|
||||||
|
RTLOW(0x3C, ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) |
|
||||||
|
(1 << 4) | (1 << 5) | (1 << 6) | (1 << 13) |
|
||||||
|
(1 << 14) | (1 << 15)));
|
||||||
|
RTLOL(0x44, ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 7)));
|
||||||
|
RTLOB(0x37, 0x0C);
|
||||||
|
MAC = GetMAC();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return DEVICE_NOT_SUPPORTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FetchReason:
|
||||||
|
{
|
||||||
|
memcpy(Data->NetworkCallback.Fetch.Name, (void *)"RTL-8139", 9);
|
||||||
|
Data->NetworkCallback.Fetch.MAC = MAC.ToHex();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SendReason:
|
||||||
|
{
|
||||||
|
RTLOL(TSAD[TXCurrent], static_cast<uint32_t>(reinterpret_cast<uint64_t>(Data->NetworkCallback.Send.Data)));
|
||||||
|
RTLOL(TSD[TXCurrent++], (uint32_t)Data->NetworkCallback.Send.Length);
|
||||||
|
if (TXCurrent > 3)
|
||||||
|
TXCurrent = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StopReason:
|
||||||
|
{
|
||||||
|
// TODO: Stop the driver.
|
||||||
|
debug("Driver stopped.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown reason.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InterruptCallback(CPURegisters *)
|
||||||
|
{
|
||||||
|
uint16_t Status = RTLIW(0x3E);
|
||||||
|
UNUSED(Status);
|
||||||
|
|
||||||
|
uint16_t *Data = (uint16_t *)(RXBuffer + CurrentPacket);
|
||||||
|
uint16_t DataLength = *(Data + 1);
|
||||||
|
Data = Data + 2;
|
||||||
|
KAPI.Command.Network.ReceivePacket(KAPI.Info.DriverUID, (uint8_t *)Data, DataLength);
|
||||||
|
CurrentPacket = (uint16_t)((CurrentPacket + DataLength + 4 + 3) & (~3));
|
||||||
|
if (CurrentPacket > 8192)
|
||||||
|
CurrentPacket -= 8192;
|
||||||
|
RTLOW(0x38, CurrentPacket - 0x10);
|
||||||
|
|
||||||
|
RTLOW(0x3E, (1 << 0) | (1 << 2));
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
38
Drivers/Realtek/rtl8139.hpp
Normal file
38
Drivers/Realtek/rtl8139.hpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_RTL8139_H__
|
||||||
|
#define __FENNIX_KERNEL_RTL8139_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
|
||||||
|
namespace RTL8139
|
||||||
|
{
|
||||||
|
struct BARData
|
||||||
|
{
|
||||||
|
uint8_t Type;
|
||||||
|
uint16_t IOBase;
|
||||||
|
uint64_t MemoryBase;
|
||||||
|
};
|
||||||
|
|
||||||
|
int DriverEntry(void *);
|
||||||
|
int CallbackHandler(KernelCallback *);
|
||||||
|
int InterruptCallback(CPURegisters *);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_RTL8139_H__
|
225
Drivers/VMware/Mouse.cpp
Normal file
225
Drivers/VMware/Mouse.cpp
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
#include "mouse.hpp"
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
#include "../drv.hpp"
|
||||||
|
|
||||||
|
/* https://wiki.osdev.org/VMware_tools */
|
||||||
|
|
||||||
|
namespace VMwareMouse
|
||||||
|
{
|
||||||
|
KernelAPI KAPI;
|
||||||
|
|
||||||
|
void CommandSend(VMwareCommand *cmd)
|
||||||
|
{
|
||||||
|
cmd->magic = VMWARE_MAGIC;
|
||||||
|
cmd->port = VMWARE_PORT;
|
||||||
|
asm volatile("in %%dx, %0"
|
||||||
|
: "+a"(cmd->ax), "+b"(cmd->bx), "+c"(cmd->cx), "+d"(cmd->dx), "+S"(cmd->si), "+D"(cmd->di));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsVMwareBackdoorAvailable(void)
|
||||||
|
{
|
||||||
|
VMwareCommand cmd;
|
||||||
|
cmd.bx = ~VMWARE_MAGIC;
|
||||||
|
cmd.command = CMD_GETVERSION;
|
||||||
|
CommandSend(&cmd);
|
||||||
|
if (cmd.bx != VMWARE_MAGIC || cmd.ax == 0xFFFFFFFF)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DriverEntry(void *Data)
|
||||||
|
{
|
||||||
|
if (!Data)
|
||||||
|
return INVALID_KERNEL_API;
|
||||||
|
KAPI = *(KernelAPI *)Data;
|
||||||
|
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
|
||||||
|
return KERNEL_API_VERSION_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
if (!IsVMwareBackdoorAvailable())
|
||||||
|
return SYSTEM_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Absolute(void)
|
||||||
|
{
|
||||||
|
VMwareCommand cmd;
|
||||||
|
|
||||||
|
/* Enable */
|
||||||
|
cmd.bx = ABSPOINTER_ENABLE;
|
||||||
|
cmd.command = CMD_ABSPOINTER_COMMAND;
|
||||||
|
CommandSend(&cmd);
|
||||||
|
|
||||||
|
/* Status */
|
||||||
|
cmd.bx = 0;
|
||||||
|
cmd.command = CMD_ABSPOINTER_STATUS;
|
||||||
|
CommandSend(&cmd);
|
||||||
|
|
||||||
|
/* Read data (1) */
|
||||||
|
cmd.bx = 1;
|
||||||
|
cmd.command = CMD_ABSPOINTER_DATA;
|
||||||
|
CommandSend(&cmd);
|
||||||
|
|
||||||
|
/* Enable absolute */
|
||||||
|
cmd.bx = ABSPOINTER_ABSOLUTE;
|
||||||
|
cmd.command = CMD_ABSPOINTER_COMMAND;
|
||||||
|
CommandSend(&cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Relative(void)
|
||||||
|
{
|
||||||
|
VMwareCommand cmd;
|
||||||
|
cmd.bx = ABSPOINTER_RELATIVE;
|
||||||
|
cmd.command = CMD_ABSPOINTER_COMMAND;
|
||||||
|
CommandSend(&cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Config
|
||||||
|
{
|
||||||
|
READ_CONFIG = 0x20,
|
||||||
|
WRITE_CONFIG = 0x60
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Ports
|
||||||
|
{
|
||||||
|
DATA = 0x60,
|
||||||
|
STATUS = 0x64,
|
||||||
|
COMMAND = 0x64,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum State
|
||||||
|
{
|
||||||
|
OUTPUT_FULL = (1 << 0),
|
||||||
|
INPUT_FULL = (1 << 1),
|
||||||
|
MOUSE_BYTE = (1 << 5)
|
||||||
|
};
|
||||||
|
|
||||||
|
void WaitRead()
|
||||||
|
{
|
||||||
|
uint64_t Timeout = 100000;
|
||||||
|
while (Timeout--)
|
||||||
|
if (inb(Ports::STATUS) & State::OUTPUT_FULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitWrite()
|
||||||
|
{
|
||||||
|
uint64_t Timeout = 100000;
|
||||||
|
while (Timeout--)
|
||||||
|
if ((inb(Ports::STATUS) & State::INPUT_FULL) == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(uint16_t Port, uint8_t Value)
|
||||||
|
{
|
||||||
|
WaitWrite();
|
||||||
|
outb(Port, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Read()
|
||||||
|
{
|
||||||
|
WaitRead();
|
||||||
|
return inb(Ports::DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MouseX = 0, MouseY = 0, MouseZ = 0;
|
||||||
|
int MouseButton = 0;
|
||||||
|
|
||||||
|
int CallbackHandler(KernelCallback *Data)
|
||||||
|
{
|
||||||
|
switch (Data->Reason)
|
||||||
|
{
|
||||||
|
case AcknowledgeReason:
|
||||||
|
{
|
||||||
|
debug("Kernel acknowledged the driver.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ConfigurationReason:
|
||||||
|
{
|
||||||
|
outb(COMMAND, 0xA8);
|
||||||
|
Write(COMMAND, READ_CONFIG);
|
||||||
|
uint8_t Status = Read();
|
||||||
|
Status |= 0b10;
|
||||||
|
Write(COMMAND, WRITE_CONFIG);
|
||||||
|
Write(DATA, Status);
|
||||||
|
Write(COMMAND, 0xD4);
|
||||||
|
Write(DATA, 0xF6);
|
||||||
|
Read();
|
||||||
|
Write(COMMAND, 0xD4);
|
||||||
|
Write(DATA, 0xF4);
|
||||||
|
Read();
|
||||||
|
Absolute();
|
||||||
|
trace("VMware mouse configured.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FetchReason:
|
||||||
|
{
|
||||||
|
Data->InputCallback.Mouse.X = (MouseX * KAPI.Display.GetWidth()) / 0xFFFF;
|
||||||
|
Data->InputCallback.Mouse.Y = (MouseY * KAPI.Display.GetHeight()) / 0xFFFF;
|
||||||
|
Data->InputCallback.Mouse.Z = MouseZ;
|
||||||
|
Data->InputCallback.Mouse.Buttons.Left = MouseButton & 0x20;
|
||||||
|
Data->InputCallback.Mouse.Buttons.Right = MouseButton & 0x10;
|
||||||
|
Data->InputCallback.Mouse.Buttons.Middle = MouseButton & 0x08;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StopReason:
|
||||||
|
{
|
||||||
|
Relative();
|
||||||
|
// TODO: UNTESTED!!!
|
||||||
|
outb(COMMAND, 0xA8);
|
||||||
|
Write(COMMAND, READ_CONFIG);
|
||||||
|
uint8_t Status = Read();
|
||||||
|
Status &= ~0b10;
|
||||||
|
Write(COMMAND, WRITE_CONFIG);
|
||||||
|
Write(DATA, Status);
|
||||||
|
Write(COMMAND, 0xD4);
|
||||||
|
Write(DATA, 0xF5);
|
||||||
|
Read();
|
||||||
|
debug("Driver stopped.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown reason.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InterruptCallback(CPURegisters *)
|
||||||
|
{
|
||||||
|
uint8_t Data = inb(0x60);
|
||||||
|
(void)Data;
|
||||||
|
VMwareCommand cmd;
|
||||||
|
cmd.bx = 0;
|
||||||
|
cmd.command = CMD_ABSPOINTER_STATUS;
|
||||||
|
CommandSend(&cmd);
|
||||||
|
|
||||||
|
if (cmd.ax == 0xFFFF0000)
|
||||||
|
{
|
||||||
|
warn("VMware mouse is not connected?");
|
||||||
|
Relative();
|
||||||
|
Absolute();
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
if ((cmd.ax & 0xFFFF) < 4)
|
||||||
|
return ERROR;
|
||||||
|
|
||||||
|
cmd.bx = 4;
|
||||||
|
cmd.command = CMD_ABSPOINTER_DATA;
|
||||||
|
CommandSend(&cmd);
|
||||||
|
|
||||||
|
int flags = (cmd.ax & 0xFFFF0000) >> 16; /* Not important */
|
||||||
|
(void)flags;
|
||||||
|
MouseButton = (cmd.ax & 0xFFFF); /* 0x10 = Right, 0x20 = Left, 0x08 = Middle */
|
||||||
|
MouseX = cmd.bx; /* Both X and Y are scaled from 0 to 0xFFFF */
|
||||||
|
MouseY = cmd.cx; /* You should map these somewhere to the actual resolution. */
|
||||||
|
MouseZ = (int8_t)cmd.dx; /* Z is a single signed byte indicating scroll direction. */
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
69
Drivers/VMware/mouse.hpp
Normal file
69
Drivers/VMware/mouse.hpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_VMWARE_MOUSE_H__
|
||||||
|
#define __FENNIX_KERNEL_VMWARE_MOUSE_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include "../../DAPI.hpp"
|
||||||
|
|
||||||
|
namespace VMwareMouse
|
||||||
|
{
|
||||||
|
#define VMWARE_MAGIC 0x564D5868 /* hXMV */
|
||||||
|
#define VMWARE_PORT 0x5658
|
||||||
|
|
||||||
|
#define CMD_GETVERSION 0xA
|
||||||
|
#define CMD_ABSPOINTER_DATA 0x27
|
||||||
|
#define CMD_ABSPOINTER_STATUS 0x28
|
||||||
|
#define CMD_ABSPOINTER_COMMAND 0x29
|
||||||
|
|
||||||
|
#define ABSPOINTER_ENABLE 0x45414552 /* Q E A E */
|
||||||
|
#define ABSPOINTER_RELATIVE 0xF5
|
||||||
|
#define ABSPOINTER_ABSOLUTE 0x53424152 /* R A B S */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32_t ax;
|
||||||
|
uint32_t magic;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32_t bx;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32_t cx;
|
||||||
|
uint16_t command;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32_t dx;
|
||||||
|
uint16_t port;
|
||||||
|
};
|
||||||
|
uint32_t si;
|
||||||
|
uint32_t di;
|
||||||
|
} VMwareCommand;
|
||||||
|
|
||||||
|
int DriverEntry(void *);
|
||||||
|
int CallbackHandler(KernelCallback *);
|
||||||
|
int InterruptCallback(CPURegisters *);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_VMWARE_MOUSE_H__
|
32
Drivers/drv.hpp
Normal file
32
Drivers/drv.hpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_DRV_H__
|
||||||
|
#define __FENNIX_KERNEL_DRV_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
bool StartAHCI();
|
||||||
|
bool StartVMwareMouse();
|
||||||
|
bool StartPS2Mouse();
|
||||||
|
bool StartATA();
|
||||||
|
bool StartAC97();
|
||||||
|
bool StartRTL8139();
|
||||||
|
bool StartPCNET();
|
||||||
|
bool StartGigabit();
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_DRV_H__
|
136
Fex.hpp
136
Fex.hpp
@ -48,48 +48,48 @@
|
|||||||
|
|
||||||
enum FexFormatType
|
enum FexFormatType
|
||||||
{
|
{
|
||||||
FexFormatType_Unknown,
|
FexFormatType_Unknown,
|
||||||
FexFormatType_Executable,
|
FexFormatType_Executable,
|
||||||
FexFormatType_Driver
|
FexFormatType_Driver
|
||||||
/* ... */
|
/* ... */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FexOSType
|
enum FexOSType
|
||||||
{
|
{
|
||||||
FexOSType_Unknown,
|
FexOSType_Unknown,
|
||||||
FexOSType_Fennix,
|
FexOSType_Fennix,
|
||||||
FexOSType_Linux
|
FexOSType_Linux
|
||||||
/* ... */
|
/* ... */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FexDriverType
|
enum FexDriverType
|
||||||
{
|
{
|
||||||
FexDriverType_Unknown,
|
FexDriverType_Unknown,
|
||||||
FexDriverType_Generic,
|
FexDriverType_Generic,
|
||||||
FexDriverType_Display,
|
FexDriverType_Display,
|
||||||
FexDriverType_Network,
|
FexDriverType_Network,
|
||||||
FexDriverType_Storage,
|
FexDriverType_Storage,
|
||||||
FexDriverType_FileSystem,
|
FexDriverType_FileSystem,
|
||||||
FexDriverType_Input,
|
FexDriverType_Input,
|
||||||
FexDriverType_Audio,
|
FexDriverType_Audio,
|
||||||
FexDriverType_ACPI,
|
FexDriverType_ACPI,
|
||||||
/* ... */
|
/* ... */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FexDriverInputTypes
|
enum FexDriverInputTypes
|
||||||
{
|
{
|
||||||
FexDriverInputTypes_None = 0b00000000,
|
FexDriverInputTypes_None = 0b00000000,
|
||||||
FexDriverInputTypes_Mouse = 0b00000001,
|
FexDriverInputTypes_Mouse = 0b00000001,
|
||||||
FexDriverInputTypes_Keyboard = 0b00000010,
|
FexDriverInputTypes_Keyboard = 0b00000010,
|
||||||
/* ... */
|
/* ... */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Fex
|
struct Fex
|
||||||
{
|
{
|
||||||
char Magic[4];
|
char Magic[4];
|
||||||
enum FexFormatType Type : 4;
|
enum FexFormatType Type : 4;
|
||||||
enum FexOSType OS : 4;
|
enum FexOSType OS : 4;
|
||||||
int (*EntryPoint)(void *);
|
int (*EntryPoint)(void *);
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
union KernelCallback;
|
union KernelCallback;
|
||||||
@ -97,49 +97,49 @@ union CPURegisters;
|
|||||||
|
|
||||||
struct FexExtended
|
struct FexExtended
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
||||||
} Executable;
|
} Executable;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
char Name[64];
|
char Name[64];
|
||||||
enum FexDriverType Type : 4;
|
enum FexDriverType Type : 4;
|
||||||
enum FexDriverInputTypes TypeFlags : 4;
|
enum FexDriverInputTypes TypeFlags : 4;
|
||||||
char OverrideOnConflict : 1;
|
char OverrideOnConflict;
|
||||||
int (*Callback)(union KernelCallback *);
|
int (*Callback)(union KernelCallback *);
|
||||||
int (*InterruptCallback)(union CPURegisters *);
|
int (*InterruptCallback)(union CPURegisters *);
|
||||||
|
|
||||||
struct DriverBind
|
struct DriverBind
|
||||||
{
|
{
|
||||||
int Type;
|
int Type;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned char Vector[16];
|
unsigned char Vector[16];
|
||||||
} Interrupt;
|
} Interrupt;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned int ProcessId[16];
|
unsigned int ProcessId[16];
|
||||||
} Process;
|
} Process;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned short VendorID[16];
|
unsigned short VendorID[16];
|
||||||
unsigned short DeviceID[16];
|
unsigned short DeviceID[16];
|
||||||
unsigned short Class;
|
unsigned short Class;
|
||||||
unsigned short SubClass;
|
unsigned short SubClass;
|
||||||
unsigned short ProgIF;
|
unsigned short ProgIF;
|
||||||
} PCI;
|
} PCI;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
char AttachToMouse;
|
char AttachToMouse;
|
||||||
char AttachToKeyboard;
|
char AttachToKeyboard;
|
||||||
} Input;
|
} Input;
|
||||||
} Bind;
|
} Bind;
|
||||||
} Driver;
|
} Driver;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -152,10 +152,10 @@ struct FexExtended
|
|||||||
* @note Must include ".header : { *(.header .header.*) }" in linker script
|
* @note Must include ".header : { *(.header .header.*) }" in linker script
|
||||||
*/
|
*/
|
||||||
#define HEAD(FormatType, OperatingSystem, Address) \
|
#define HEAD(FormatType, OperatingSystem, Address) \
|
||||||
__attribute__((section(".header"))) struct Fex FexHeader = { \
|
__attribute__((section(".header"))) struct Fex FexHeader = { \
|
||||||
.Magic = {'F', 'E', 'X', '\0'}, \
|
.Magic = {'F', 'E', 'X', '\0'}, \
|
||||||
.Type = FormatType, \
|
.Type = FormatType, \
|
||||||
.OS = OperatingSystem, \
|
.OS = OperatingSystem, \
|
||||||
.EntryPoint = Address}
|
.EntryPoint = Address}
|
||||||
|
|
||||||
#endif // !__FENNIX_FILE_FEX_H__
|
#endif // !__FENNIX_FILE_FEX_H__
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -28,132 +28,132 @@
|
|||||||
|
|
||||||
namespace GraphicalUserInterface
|
namespace GraphicalUserInterface
|
||||||
{
|
{
|
||||||
void WidgetCollection::OnPaintBackground(Event *e)
|
void WidgetCollection::OnPaintBackground(Event *e)
|
||||||
{
|
{
|
||||||
UNUSED(e);
|
UNUSED(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetCollection::OnPaintForeground(Event *e)
|
void WidgetCollection::OnPaintForeground(Event *e)
|
||||||
{
|
{
|
||||||
UNUSED(e);
|
UNUSED(e);
|
||||||
foreach (auto Panel in this->Panels)
|
foreach (auto Panel in this->Panels)
|
||||||
{
|
{
|
||||||
PutRect(this->Buffer, Panel->rect, Panel->Color);
|
PutRect(this->Buffer, Panel->rect, Panel->Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (auto Label in this->Labels)
|
foreach (auto Label in this->Labels)
|
||||||
{
|
{
|
||||||
Label->CharCursorX = Label->rect.Left;
|
Label->CharCursorX = Label->rect.Left;
|
||||||
Label->CharCursorY = Label->rect.Top;
|
Label->CharCursorY = Label->rect.Top;
|
||||||
for (uint64_t i = 0; i < strlen(Label->Text); i++)
|
for (uint64_t i = 0; i < strlen(Label->Text); i++)
|
||||||
PaintChar(this->CurrentFont, this->Buffer, Label->Text[i], 0xFFFFFF, &Label->CharCursorX, &Label->CharCursorY);
|
PaintChar(this->CurrentFont, this->Buffer, Label->Text[i], 0xFFFFFF, &Label->CharCursorX, &Label->CharCursorY);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (auto Button in this->Buttons)
|
foreach (auto Button in this->Buttons)
|
||||||
{
|
{
|
||||||
if (Button->Pressed)
|
if (Button->Pressed)
|
||||||
PutRect(this->Buffer, Button->rect, Button->PressedColor);
|
PutRect(this->Buffer, Button->rect, Button->PressedColor);
|
||||||
else if (Button->Hover)
|
else if (Button->Hover)
|
||||||
PutRect(this->Buffer, Button->rect, Button->HoverColor);
|
PutRect(this->Buffer, Button->rect, Button->HoverColor);
|
||||||
else
|
else
|
||||||
PutRect(this->Buffer, Button->rect, Button->Color);
|
PutRect(this->Buffer, Button->rect, Button->Color);
|
||||||
Button->CharCursorX = Button->rect.Left + (((Button->rect.Width / 2) - (this->CurrentFont->GetInfo().Width * strlen(Button->Text) / 2)));
|
Button->CharCursorX = Button->rect.Left + (((Button->rect.Width / 2) - (this->CurrentFont->GetInfo().Width * strlen(Button->Text) / 2)));
|
||||||
Button->CharCursorY = Button->rect.Top + (((Button->rect.Height / 2) - (this->CurrentFont->GetInfo().Height / 2)));
|
Button->CharCursorY = Button->rect.Top + (((Button->rect.Height / 2) - (this->CurrentFont->GetInfo().Height / 2)));
|
||||||
for (uint64_t i = 0; i < strlen(Button->Text); i++)
|
for (uint64_t i = 0; i < strlen(Button->Text); i++)
|
||||||
PaintChar(this->CurrentFont, this->Buffer, Button->Text[i], 0xFFFFFF, &Button->CharCursorX, &Button->CharCursorY);
|
PaintChar(this->CurrentFont, this->Buffer, Button->Text[i], 0xFFFFFF, &Button->CharCursorX, &Button->CharCursorY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetCollection::OnPaint(Event *e)
|
void WidgetCollection::OnPaint(Event *e)
|
||||||
{
|
{
|
||||||
static int64_t LastWidth = 0;
|
static size_t LastWidth = 0;
|
||||||
static int64_t LastHeight = 0;
|
static size_t LastHeight = 0;
|
||||||
|
|
||||||
if (LastWidth != ((Window *)this->ParentWindow)->GetPosition().Width ||
|
if (LastWidth != ((Window *)this->ParentWindow)->GetPosition().Width ||
|
||||||
LastHeight != ((Window *)this->ParentWindow)->GetPosition().Height)
|
LastHeight != ((Window *)this->ParentWindow)->GetPosition().Height)
|
||||||
{
|
{
|
||||||
LastWidth = ((Window *)this->ParentWindow)->GetPosition().Width;
|
LastWidth = ((Window *)this->ParentWindow)->GetPosition().Width;
|
||||||
LastHeight = ((Window *)this->ParentWindow)->GetPosition().Height;
|
LastHeight = ((Window *)this->ParentWindow)->GetPosition().Height;
|
||||||
|
|
||||||
this->mem->FreePages(this->Buffer->Data, TO_PAGES(this->Buffer->Size + 1));
|
this->mem->FreePages(this->Buffer->Data, TO_PAGES(this->Buffer->Size + 1));
|
||||||
this->Buffer->Data = nullptr;
|
this->Buffer->Data = nullptr;
|
||||||
delete this->Buffer, this->Buffer = nullptr;
|
delete this->Buffer, this->Buffer = nullptr;
|
||||||
|
|
||||||
this->Buffer = new ScreenBitmap;
|
this->Buffer = new ScreenBitmap;
|
||||||
this->Buffer->Width = LastWidth;
|
this->Buffer->Width = LastWidth;
|
||||||
this->Buffer->Height = LastHeight;
|
this->Buffer->Height = LastHeight;
|
||||||
this->Buffer->BitsPerPixel = Display->GetBitsPerPixel();
|
this->Buffer->BitsPerPixel = Display->GetBitsPerPixel();
|
||||||
this->Buffer->Pitch = Display->GetPitch();
|
this->Buffer->Pitch = Display->GetPitch();
|
||||||
this->Buffer->Size = this->Buffer->Pitch * (size_t)LastHeight;
|
this->Buffer->Size = this->Buffer->Pitch * (size_t)LastHeight;
|
||||||
this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1));
|
this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1));
|
||||||
memset(this->Buffer->Data, 0, this->Buffer->Size);
|
memset(this->Buffer->Data, 0, this->Buffer->Size);
|
||||||
|
|
||||||
this->NeedRedraw = true;
|
this->NeedRedraw = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->NeedRedraw)
|
if (this->NeedRedraw)
|
||||||
{
|
{
|
||||||
memset(this->Buffer->Data, 0, this->Buffer->Size);
|
memset(this->Buffer->Data, 0, this->Buffer->Size);
|
||||||
this->OnPaintBackground(e);
|
this->OnPaintBackground(e);
|
||||||
this->OnPaintForeground(e);
|
this->OnPaintForeground(e);
|
||||||
this->NeedRedraw = false;
|
this->NeedRedraw = false;
|
||||||
}
|
}
|
||||||
DrawOverBitmap(((Window *)this->ParentWindow)->GetBuffer(), this->Buffer, 0, 0);
|
DrawOverBitmap(((Window *)this->ParentWindow)->GetBuffer(), this->Buffer, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetCollection::OnMouseDown(Event *e)
|
void WidgetCollection::OnMouseDown(Event *e)
|
||||||
{
|
{
|
||||||
foreach (auto Button in this->Buttons)
|
foreach (auto Button in this->Buttons)
|
||||||
{
|
{
|
||||||
if (Button->rect.Contains(e->MouseDown.X, e->MouseDown.Y))
|
if (Button->rect.Contains(e->MouseDown.X, e->MouseDown.Y))
|
||||||
{
|
{
|
||||||
if (e->MouseDown.Left)
|
if (e->MouseDown.Left)
|
||||||
{
|
{
|
||||||
debug("Button Hold");
|
debug("Button Hold");
|
||||||
Button->Pressed = true;
|
Button->Pressed = true;
|
||||||
this->NeedRedraw = true;
|
this->NeedRedraw = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetCollection::OnMouseUp(Event *e)
|
void WidgetCollection::OnMouseUp(Event *e)
|
||||||
{
|
{
|
||||||
foreach (auto Button in this->Buttons)
|
foreach (auto Button in this->Buttons)
|
||||||
{
|
{
|
||||||
if (Button->rect.Contains(e->MouseUp.X, e->MouseUp.Y))
|
if (Button->rect.Contains(e->MouseUp.X, e->MouseUp.Y))
|
||||||
{
|
{
|
||||||
if (e->MouseUp.Left)
|
if (e->MouseUp.Left)
|
||||||
{
|
{
|
||||||
debug("Button Release");
|
debug("Button Release");
|
||||||
if (Button->Pressed)
|
if (Button->Pressed)
|
||||||
{
|
{
|
||||||
debug("Button Clicked");
|
debug("Button Clicked");
|
||||||
if (Button->OnClick != (uintptr_t) nullptr)
|
if (Button->OnClick != (uintptr_t) nullptr)
|
||||||
((void (*)(void))Button->OnClick)();
|
((void (*)(void))Button->OnClick)();
|
||||||
|
|
||||||
Button->Pressed = false;
|
Button->Pressed = false;
|
||||||
this->NeedRedraw = true;
|
this->NeedRedraw = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetCollection::OnMouseMove(Event *e)
|
void WidgetCollection::OnMouseMove(Event *e)
|
||||||
{
|
{
|
||||||
foreach (auto Button in this->Buttons)
|
foreach (auto Button in this->Buttons)
|
||||||
{
|
{
|
||||||
if (Button->rect.Contains(e->MouseMove.X, e->MouseMove.Y))
|
if (Button->rect.Contains(e->MouseMove.X, e->MouseMove.Y))
|
||||||
{
|
{
|
||||||
Button->Hover = true;
|
Button->Hover = true;
|
||||||
this->NeedRedraw = true;
|
this->NeedRedraw = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Button->Hover = false;
|
Button->Hover = false;
|
||||||
this->NeedRedraw = true;
|
this->NeedRedraw = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,110 +28,110 @@
|
|||||||
|
|
||||||
namespace GraphicalUserInterface
|
namespace GraphicalUserInterface
|
||||||
{
|
{
|
||||||
void Window::OnResize(Event *e)
|
void Window::OnResize(Event *e)
|
||||||
{
|
{
|
||||||
// TODO: Optimize this
|
// TODO: Optimize this
|
||||||
this->mem->FreePages(this->Buffer->Data, TO_PAGES(this->Buffer->Size + 1));
|
this->mem->FreePages(this->Buffer->Data, TO_PAGES(this->Buffer->Size + 1));
|
||||||
this->Buffer->Data = nullptr;
|
this->Buffer->Data = nullptr;
|
||||||
delete this->Buffer, this->Buffer = nullptr;
|
delete this->Buffer, this->Buffer = nullptr;
|
||||||
|
|
||||||
this->Buffer = new ScreenBitmap;
|
this->Buffer = new ScreenBitmap;
|
||||||
this->Buffer->Width = e->Resize.Width;
|
this->Buffer->Width = e->Resize.Width;
|
||||||
this->Buffer->Height = e->Resize.Height;
|
this->Buffer->Height = e->Resize.Height;
|
||||||
this->Buffer->BitsPerPixel = Display->GetBitsPerPixel();
|
this->Buffer->BitsPerPixel = Display->GetBitsPerPixel();
|
||||||
this->Buffer->Pitch = Display->GetPitch();
|
this->Buffer->Pitch = Display->GetPitch();
|
||||||
this->Buffer->Size = this->Buffer->Pitch * e->Resize.Height;
|
this->Buffer->Size = this->Buffer->Pitch * e->Resize.Height;
|
||||||
this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1));
|
this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1));
|
||||||
memset(this->Buffer->Data, 0, this->Buffer->Size);
|
memset(this->Buffer->Data, 0, this->Buffer->Size);
|
||||||
this->OnPaint(e);
|
this->OnPaint(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::OnMinimize(Event *e)
|
void Window::OnMinimize(Event *e)
|
||||||
{
|
{
|
||||||
UNUSED(e);
|
UNUSED(e);
|
||||||
fixme("Window::OnMinimize() not implemented");
|
fixme("Window::OnMinimize() not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::OnMaximize(Event *e)
|
void Window::OnMaximize(Event *e)
|
||||||
{
|
{
|
||||||
UNUSED(e);
|
UNUSED(e);
|
||||||
fixme("Window::OnMaximize() not implemented");
|
fixme("Window::OnMaximize() not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::OnClose(Event *e)
|
void Window::OnClose(Event *e)
|
||||||
{
|
{
|
||||||
UNUSED(e);
|
UNUSED(e);
|
||||||
fixme("Window::OnClose() not implemented");
|
fixme("Window::OnClose() not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::OnPaintBackground(Event *e)
|
void Window::OnPaintBackground(Event *e)
|
||||||
{
|
{
|
||||||
UNUSED(e);
|
UNUSED(e);
|
||||||
Rect PaintPosition = this->Position;
|
Rect PaintPosition = this->Position;
|
||||||
PaintPosition.Left = 0;
|
PaintPosition.Left = 0;
|
||||||
PaintPosition.Top = 0;
|
PaintPosition.Top = 0;
|
||||||
PutRect(this->Buffer, PaintPosition, 0x121212);
|
PutRect(this->Buffer, PaintPosition, 0x121212);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::OnPaintForeground(Event *e)
|
void Window::OnPaintForeground(Event *e)
|
||||||
{
|
{
|
||||||
// Window content
|
// Window content
|
||||||
if (!this->Maximized)
|
if (!this->Maximized)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
sprintf(buf, "Left:\eAA11FF%lld\eFFFFFF Top:\eAA11FF%lld\eFFFFFF W:\eAA11FF%ld\eFFFFFF H:\eAA11FF%ld\eFFFFFF", this->Position.Left, this->Position.Top, this->Position.Width, this->Position.Height);
|
sprintf(buf, "Left:\eAA11FF%ld\eFFFFFF Top:\eAA11FF%ld\eFFFFFF W:\eAA11FF%ld\eFFFFFF H:\eAA11FF%ld\eFFFFFF", this->Position.Left, this->Position.Top, this->Position.Width, this->Position.Height);
|
||||||
// Display->DrawString(buf, this->Position.Left + 20, this->Position.Top + 25, 200);
|
// Display->DrawString(buf, this->Position.Left + 20, this->Position.Top + 25, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (auto var in this->Widgets)
|
foreach (auto var in this->Widgets)
|
||||||
{
|
{
|
||||||
var->OnPaint(e);
|
var->OnPaint(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::OnPaint(Event *e)
|
void Window::OnPaint(Event *e)
|
||||||
{
|
{
|
||||||
memset(this->Buffer->Data, 0, this->Buffer->Size);
|
memset(this->Buffer->Data, 0, this->Buffer->Size);
|
||||||
this->OnPaintBackground(e);
|
this->OnPaintBackground(e);
|
||||||
this->OnPaintForeground(e);
|
this->OnPaintForeground(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::OnMouseDown(Event *e)
|
void Window::OnMouseDown(Event *e)
|
||||||
{
|
{
|
||||||
Event WindowPos = *e;
|
Event WindowPos = *e;
|
||||||
|
|
||||||
WindowPos.MouseDown.X -= this->Position.Left;
|
WindowPos.MouseDown.X -= this->Position.Left;
|
||||||
WindowPos.MouseDown.Y -= this->Position.Top;
|
WindowPos.MouseDown.Y -= this->Position.Top;
|
||||||
|
|
||||||
foreach (auto var in this->Widgets)
|
foreach (auto var in this->Widgets)
|
||||||
{
|
{
|
||||||
var->OnMouseDown(&WindowPos);
|
var->OnMouseDown(&WindowPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::OnMouseUp(Event *e)
|
void Window::OnMouseUp(Event *e)
|
||||||
{
|
{
|
||||||
Event WindowPos = *e;
|
Event WindowPos = *e;
|
||||||
|
|
||||||
WindowPos.MouseUp.X -= this->Position.Left;
|
WindowPos.MouseUp.X -= this->Position.Left;
|
||||||
WindowPos.MouseUp.Y -= this->Position.Top;
|
WindowPos.MouseUp.Y -= this->Position.Top;
|
||||||
|
|
||||||
foreach (auto var in this->Widgets)
|
foreach (auto var in this->Widgets)
|
||||||
{
|
{
|
||||||
var->OnMouseUp(&WindowPos);
|
var->OnMouseUp(&WindowPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::OnMouseMove(Event *e)
|
void Window::OnMouseMove(Event *e)
|
||||||
{
|
{
|
||||||
Event WindowPos = *e;
|
Event WindowPos = *e;
|
||||||
|
|
||||||
WindowPos.MouseMove.X -= this->Position.Left;
|
WindowPos.MouseMove.X -= this->Position.Left;
|
||||||
WindowPos.MouseMove.Y -= this->Position.Top;
|
WindowPos.MouseMove.Y -= this->Position.Top;
|
||||||
|
|
||||||
foreach (auto var in this->Widgets)
|
foreach (auto var in this->Widgets)
|
||||||
{
|
{
|
||||||
var->OnMouseMove(&WindowPos);
|
var->OnMouseMove(&WindowPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
573
Kernel.cpp
573
Kernel.cpp
@ -76,6 +76,7 @@ LockClass mExtTrkLock;
|
|||||||
* - [ ] Update SMBIOS functions to support newer versions and actually use it.
|
* - [ ] Update SMBIOS functions to support newer versions and actually use it.
|
||||||
* - [ ] COW (Copy On Write) for the virtual memory. (https://en.wikipedia.org/wiki/Copy-on-write)
|
* - [ ] COW (Copy On Write) for the virtual memory. (https://en.wikipedia.org/wiki/Copy-on-write)
|
||||||
* - [ ] Bootstrap should have a separate bss section + PHDR.
|
* - [ ] Bootstrap should have a separate bss section + PHDR.
|
||||||
|
* - [ ] Reimplement the driver conflict detection.
|
||||||
*
|
*
|
||||||
* ISSUES:
|
* ISSUES:
|
||||||
* - [x] Kernel stack is smashed when an interrupt occurs. (this bug it occurs when an interrupt like IRQ1 or IRQ12 occurs)
|
* - [x] Kernel stack is smashed when an interrupt occurs. (this bug it occurs when an interrupt like IRQ1 or IRQ12 occurs)
|
||||||
@ -207,16 +208,16 @@ VirtualFileSystem::Virtual *vfs = nullptr;
|
|||||||
VirtualFileSystem::Virtual *bootanim_vfs = nullptr;
|
VirtualFileSystem::Virtual *bootanim_vfs = nullptr;
|
||||||
|
|
||||||
KernelConfig Config = {
|
KernelConfig Config = {
|
||||||
.AllocatorType = Memory::MemoryAllocatorType::XallocV1,
|
.AllocatorType = Memory::MemoryAllocatorType::XallocV1,
|
||||||
.SchedulerType = 1,
|
.SchedulerType = 1,
|
||||||
.DriverDirectory = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\0'},
|
.DriverDirectory = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\0'},
|
||||||
.InitPath = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'i', 'n', 'i', 't', '\0'},
|
.InitPath = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'i', 'n', 'i', 't', '\0'},
|
||||||
.InterruptsOnCrash = true,
|
.InterruptsOnCrash = true,
|
||||||
.Cores = 0,
|
.Cores = 0,
|
||||||
.IOAPICInterruptCore = 0,
|
.IOAPICInterruptCore = 0,
|
||||||
.UnlockDeadLock = false,
|
.UnlockDeadLock = false,
|
||||||
.SIMD = false,
|
.SIMD = false,
|
||||||
.BootAnimation = false,
|
.BootAnimation = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool EnableProfiler;
|
extern bool EnableProfiler;
|
||||||
@ -225,264 +226,264 @@ extern bool EnableProfiler;
|
|||||||
int PutCharBufferIndex = 0;
|
int PutCharBufferIndex = 0;
|
||||||
EXTERNC void putchar(char c)
|
EXTERNC void putchar(char c)
|
||||||
{
|
{
|
||||||
if (Display)
|
if (Display)
|
||||||
Display->Print(c, PutCharBufferIndex);
|
Display->Print(c, PutCharBufferIndex);
|
||||||
else
|
else
|
||||||
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(c);
|
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXTERNC void KPrint(const char *Format, ...)
|
EXTERNC void KPrint(const char *Format, ...)
|
||||||
{
|
{
|
||||||
SmartLock(KernelLock);
|
SmartLock(KernelLock);
|
||||||
|
|
||||||
if (TimeManager)
|
if (TimeManager)
|
||||||
{
|
{
|
||||||
uint64_t Nanoseconds = TimeManager->GetNanosecondsSinceClassCreation();
|
uint64_t Nanoseconds = TimeManager->GetNanosecondsSinceClassCreation();
|
||||||
if (Nanoseconds != 0)
|
if (Nanoseconds != 0)
|
||||||
{
|
{
|
||||||
printf("\eCCCCCC[\e00AEFF%llu.%07llu\eCCCCCC] ",
|
printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ",
|
||||||
Nanoseconds / 10000000,
|
Nanoseconds / 10000000,
|
||||||
Nanoseconds % 10000000);
|
Nanoseconds % 10000000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, Format);
|
va_start(args, Format);
|
||||||
vprintf(Format, args);
|
vprintf(Format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
printf("\eCCCCCC\n");
|
printf("\eCCCCCC\n");
|
||||||
if (!Config.BootAnimation && Display)
|
if (!Config.BootAnimation && Display)
|
||||||
Display->SetBuffer(0);
|
Display->SetBuffer(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXTERNC NIF void Main()
|
EXTERNC NIF void Main()
|
||||||
{
|
{
|
||||||
Display = new Video::Display(bInfo.Framebuffer[0]);
|
Display = new Video::Display(bInfo.Framebuffer[0]);
|
||||||
KPrint("%s - %s [\e058C19%s\eFFFFFF]", KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT);
|
KPrint("%s - %s [\e058C19%s\eFFFFFF]", KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT);
|
||||||
KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s", CPU::Hypervisor(), CPU::Vendor(), CPU::Name());
|
KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s", CPU::Hypervisor(), CPU::Vendor(), CPU::Name());
|
||||||
if (DebuggerIsAttached)
|
if (DebuggerIsAttached)
|
||||||
KPrint("\eFFA500Kernel debugger detected.");
|
KPrint("\eFFA500Kernel debugger detected.");
|
||||||
|
|
||||||
/**************************************************************************************/
|
/**************************************************************************************/
|
||||||
|
|
||||||
KPrint("Initializing GDT and IDT");
|
KPrint("Initializing GDT and IDT");
|
||||||
Interrupts::Initialize(0);
|
Interrupts::Initialize(0);
|
||||||
|
|
||||||
KPrint("Loading Kernel Symbols");
|
KPrint("Loading Kernel Symbols");
|
||||||
KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)bInfo.Kernel.FileBase);
|
KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)bInfo.Kernel.FileBase);
|
||||||
|
|
||||||
if (KernelSymbolTable->GetTotalEntries() == 0 &&
|
if (KernelSymbolTable->GetTotalEntries() == 0 &&
|
||||||
bInfo.Kernel.Symbols.Num &&
|
bInfo.Kernel.Symbols.Num &&
|
||||||
bInfo.Kernel.Symbols.EntSize &&
|
bInfo.Kernel.Symbols.EntSize &&
|
||||||
bInfo.Kernel.Symbols.Shndx)
|
bInfo.Kernel.Symbols.Shndx)
|
||||||
KernelSymbolTable->AddBySymbolInfo(bInfo.Kernel.Symbols.Num,
|
KernelSymbolTable->AddBySymbolInfo(bInfo.Kernel.Symbols.Num,
|
||||||
bInfo.Kernel.Symbols.EntSize,
|
bInfo.Kernel.Symbols.EntSize,
|
||||||
bInfo.Kernel.Symbols.Shndx,
|
bInfo.Kernel.Symbols.Shndx,
|
||||||
bInfo.Kernel.Symbols.Sections);
|
bInfo.Kernel.Symbols.Sections);
|
||||||
|
|
||||||
KPrint("Reading Kernel Parameters");
|
KPrint("Reading Kernel Parameters");
|
||||||
ParseConfig((char *)bInfo.Kernel.CommandLine, &Config);
|
ParseConfig((char *)bInfo.Kernel.CommandLine, &Config);
|
||||||
|
|
||||||
if (Config.BootAnimation)
|
if (Config.BootAnimation)
|
||||||
{
|
{
|
||||||
Display->CreateBuffer(0, 0, 1);
|
Display->CreateBuffer(0, 0, 1);
|
||||||
|
|
||||||
Display->SetDoNotScroll(true, 1);
|
Display->SetDoNotScroll(true, 1);
|
||||||
Video::ScreenBuffer *buf = Display->GetBuffer(1);
|
Video::ScreenBuffer *buf = Display->GetBuffer(1);
|
||||||
Video::FontInfo fi = Display->GetCurrentFont()->GetInfo();
|
Video::FontInfo fi = Display->GetCurrentFont()->GetInfo();
|
||||||
Display->SetBufferCursor(1, 0, buf->Height - fi.Height);
|
Display->SetBufferCursor(1, 0, buf->Height - fi.Height);
|
||||||
PutCharBufferIndex = 1;
|
PutCharBufferIndex = 1;
|
||||||
printf("Fennix Operating System - %s [\e058C19%s\eFFFFFF]\n", KERNEL_VERSION, GIT_COMMIT_SHORT);
|
printf("Fennix Operating System - %s [\e058C19%s\eFFFFFF]\n", KERNEL_VERSION, GIT_COMMIT_SHORT);
|
||||||
Display->SetBuffer(1);
|
Display->SetBuffer(1);
|
||||||
PutCharBufferIndex = 0;
|
PutCharBufferIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
KPrint("Initializing CPU Features");
|
KPrint("Initializing CPU Features");
|
||||||
CPU::InitializeFeatures(0);
|
CPU::InitializeFeatures(0);
|
||||||
|
|
||||||
KPrint("Initializing Power Manager");
|
KPrint("Initializing Power Manager");
|
||||||
PowerManager = new Power::Power;
|
PowerManager = new Power::Power;
|
||||||
|
|
||||||
KPrint("Enabling Interrupts on Bootstrap Processor");
|
KPrint("Enabling Interrupts on Bootstrap Processor");
|
||||||
Interrupts::Enable(0);
|
Interrupts::Enable(0);
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
PowerManager->InitDSDT();
|
PowerManager->InitDSDT();
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
// FIXME: Add ACPI support for i386
|
// FIXME: Add ACPI support for i386
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
KPrint("Initializing Timers");
|
KPrint("Initializing Timers");
|
||||||
TimeManager = new Time::time;
|
TimeManager = new Time::time;
|
||||||
TimeManager->FindTimers(PowerManager->GetACPI());
|
TimeManager->FindTimers(PowerManager->GetACPI());
|
||||||
|
|
||||||
KPrint("Initializing PCI Manager");
|
KPrint("Initializing PCI Manager");
|
||||||
PCIManager = new PCI::PCI;
|
PCIManager = new PCI::PCI;
|
||||||
|
|
||||||
foreach (auto Device in PCIManager->GetDevices())
|
foreach (auto Device in PCIManager->GetDevices())
|
||||||
{
|
{
|
||||||
KPrint("PCI: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
KPrint("PCI: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
||||||
PCI::Descriptors::GetVendorName(Device->VendorID),
|
PCI::Descriptors::GetVendorName(Device->VendorID),
|
||||||
PCI::Descriptors::GetDeviceName(Device->VendorID, Device->DeviceID),
|
PCI::Descriptors::GetDeviceName(Device->VendorID, Device->DeviceID),
|
||||||
PCI::Descriptors::DeviceClasses[Device->Class],
|
PCI::Descriptors::DeviceClasses[Device->Class],
|
||||||
PCI::Descriptors::GetSubclassName(Device->Class, Device->Subclass),
|
PCI::Descriptors::GetSubclassName(Device->Class, Device->Subclass),
|
||||||
PCI::Descriptors::GetProgIFName(Device->Class, Device->Subclass, Device->ProgIF));
|
PCI::Descriptors::GetProgIFName(Device->Class, Device->Subclass, Device->ProgIF));
|
||||||
}
|
}
|
||||||
|
|
||||||
KPrint("Initializing Bootstrap Processor Timer");
|
KPrint("Initializing Bootstrap Processor Timer");
|
||||||
Interrupts::InitializeTimer(0);
|
Interrupts::InitializeTimer(0);
|
||||||
|
|
||||||
KPrint("Initializing SMP");
|
KPrint("Initializing SMP");
|
||||||
SMP::Initialize(PowerManager->GetMADT());
|
SMP::Initialize(PowerManager->GetMADT());
|
||||||
|
|
||||||
if (SMBIOS::CheckSMBIOS())
|
if (SMBIOS::CheckSMBIOS())
|
||||||
{
|
{
|
||||||
SMBIOS::SMBIOSEntryPoint *smbios = SMBIOS::GetSMBIOSEntryPoint();
|
SMBIOS::SMBIOSEntryPoint *smbios = SMBIOS::GetSMBIOSEntryPoint();
|
||||||
SMBIOS::SMBIOSBIOSInformation *bios = SMBIOS::GetBIOSInformation();
|
SMBIOS::SMBIOSBIOSInformation *bios = SMBIOS::GetBIOSInformation();
|
||||||
SMBIOS::SMBIOSSystemInformation *system = SMBIOS::GetSystemInformation();
|
SMBIOS::SMBIOSSystemInformation *system = SMBIOS::GetSystemInformation();
|
||||||
SMBIOS::SMBIOSBaseBoardInformation *baseboard = SMBIOS::GetBaseBoardInformation();
|
SMBIOS::SMBIOSBaseBoardInformation *baseboard = SMBIOS::GetBaseBoardInformation();
|
||||||
|
|
||||||
debug("SMBIOS: %p", smbios);
|
debug("SMBIOS: %p", smbios);
|
||||||
debug("BIOS: %p", bios);
|
debug("BIOS: %p", bios);
|
||||||
debug("System: %p", system);
|
debug("System: %p", system);
|
||||||
debug("Baseboard: %p", baseboard);
|
debug("Baseboard: %p", baseboard);
|
||||||
|
|
||||||
if (smbios)
|
if (smbios)
|
||||||
KPrint("SMBIOS: \eCCCCCCString:\e8888FF%.4s \eCCCCCCVersion (Major Minor):\e8888FF%d %d \eCCCCCCTable:\e8888FF%#x \eCCCCCCLength:\e8888FF%d",
|
KPrint("SMBIOS: \eCCCCCCString:\e8888FF%.4s \eCCCCCCVersion (Major Minor):\e8888FF%d %d \eCCCCCCTable:\e8888FF%#x \eCCCCCCLength:\e8888FF%d",
|
||||||
smbios->EntryPointString, smbios->MajorVersion, smbios->MinorVersion,
|
smbios->EntryPointString, smbios->MajorVersion, smbios->MinorVersion,
|
||||||
smbios->TableAddress, smbios->TableLength);
|
smbios->TableAddress, smbios->TableLength);
|
||||||
else
|
else
|
||||||
KPrint("SMBIOS: \e8888FFSMBIOS found but not supported?");
|
KPrint("SMBIOS: \e8888FFSMBIOS found but not supported?");
|
||||||
|
|
||||||
if (bios)
|
if (bios)
|
||||||
{
|
{
|
||||||
const char *BIOSVendor = bios->GetString(bios->Vendor);
|
const char *BIOSVendor = bios->GetString(bios->Vendor);
|
||||||
const char *BIOSVersion = bios->GetString(bios->Version);
|
const char *BIOSVersion = bios->GetString(bios->Version);
|
||||||
const char *BIOSReleaseDate = bios->GetString(bios->ReleaseDate);
|
const char *BIOSReleaseDate = bios->GetString(bios->ReleaseDate);
|
||||||
debug("%d %d %d", bios->Vendor, bios->Version, bios->ReleaseDate);
|
debug("%d %d %d", bios->Vendor, bios->Version, bios->ReleaseDate);
|
||||||
KPrint("BIOS: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
KPrint("BIOS: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
||||||
BIOSVendor, BIOSVersion, BIOSReleaseDate);
|
BIOSVendor, BIOSVersion, BIOSReleaseDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system)
|
if (system)
|
||||||
{
|
{
|
||||||
const char *SystemManufacturer = system->GetString(system->Manufacturer);
|
const char *SystemManufacturer = system->GetString(system->Manufacturer);
|
||||||
const char *SystemProductName = system->GetString(system->ProductName);
|
const char *SystemProductName = system->GetString(system->ProductName);
|
||||||
const char *SystemVersion = system->GetString(system->Version);
|
const char *SystemVersion = system->GetString(system->Version);
|
||||||
const char *SystemSerialNumber = system->GetString(system->SerialNumber);
|
const char *SystemSerialNumber = system->GetString(system->SerialNumber);
|
||||||
const char *SystemSKU = system->GetString(system->SKU);
|
const char *SystemSKU = system->GetString(system->SKU);
|
||||||
const char *SystemFamily = system->GetString(system->Family);
|
const char *SystemFamily = system->GetString(system->Family);
|
||||||
debug("%d %d %d %d %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c %d %d", system->Manufacturer, system->ProductName, system->Version,
|
debug("%d %d %d %d %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c %d %d", system->Manufacturer, system->ProductName, system->Version,
|
||||||
system->SerialNumber,
|
system->SerialNumber,
|
||||||
system->UUID[0], system->UUID[1], system->UUID[2], system->UUID[3],
|
system->UUID[0], system->UUID[1], system->UUID[2], system->UUID[3],
|
||||||
system->UUID[4], system->UUID[5], system->UUID[6], system->UUID[7],
|
system->UUID[4], system->UUID[5], system->UUID[6], system->UUID[7],
|
||||||
system->UUID[8], system->UUID[9], system->UUID[10], system->UUID[11],
|
system->UUID[8], system->UUID[9], system->UUID[10], system->UUID[11],
|
||||||
system->UUID[12], system->UUID[13], system->UUID[14], system->UUID[15],
|
system->UUID[12], system->UUID[13], system->UUID[14], system->UUID[15],
|
||||||
system->SKU, system->Family);
|
system->SKU, system->Family);
|
||||||
KPrint("System: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
KPrint("System: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
||||||
SystemManufacturer, SystemProductName, SystemVersion, SystemSerialNumber, SystemSKU, SystemFamily);
|
SystemManufacturer, SystemProductName, SystemVersion, SystemSerialNumber, SystemSKU, SystemFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (baseboard)
|
if (baseboard)
|
||||||
{
|
{
|
||||||
const char *Manufacturer = baseboard->GetString(baseboard->Manufacturer);
|
const char *Manufacturer = baseboard->GetString(baseboard->Manufacturer);
|
||||||
const char *Product = baseboard->GetString(baseboard->Product);
|
const char *Product = baseboard->GetString(baseboard->Product);
|
||||||
const char *Version = baseboard->GetString(baseboard->Version);
|
const char *Version = baseboard->GetString(baseboard->Version);
|
||||||
const char *SerialNumber = baseboard->GetString(baseboard->SerialNumber);
|
const char *SerialNumber = baseboard->GetString(baseboard->SerialNumber);
|
||||||
debug("%d %d %d %d", baseboard->Manufacturer, baseboard->Product, baseboard->Version, baseboard->SerialNumber);
|
debug("%d %d %d %d", baseboard->Manufacturer, baseboard->Product, baseboard->Version, baseboard->SerialNumber);
|
||||||
KPrint("Baseboard: \eCCCCCC\e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
KPrint("Baseboard: \eCCCCCC\e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
||||||
Manufacturer, Product, Version, SerialNumber);
|
Manufacturer, Product, Version, SerialNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
KPrint("SMBIOS: \eFF0000Not Found");
|
KPrint("SMBIOS: \eFF0000Not Found");
|
||||||
|
|
||||||
KPrint("Initializing Filesystem...");
|
KPrint("Initializing Filesystem...");
|
||||||
vfs = new VirtualFileSystem::Virtual;
|
vfs = new VirtualFileSystem::Virtual;
|
||||||
|
|
||||||
if (Config.BootAnimation)
|
if (Config.BootAnimation)
|
||||||
bootanim_vfs = new VirtualFileSystem::Virtual;
|
bootanim_vfs = new VirtualFileSystem::Virtual;
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_MODULES; i++)
|
for (size_t i = 0; i < MAX_MODULES; i++)
|
||||||
{
|
{
|
||||||
if (!bInfo.Modules[i].Address)
|
if (!bInfo.Modules[i].Address)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strcmp(bInfo.Modules[i].CommandLine, "initrd") == 0)
|
if (strcmp(bInfo.Modules[i].CommandLine, "initrd") == 0)
|
||||||
{
|
{
|
||||||
debug("Found initrd at %p", bInfo.Modules[i].Address);
|
debug("Found initrd at %p", bInfo.Modules[i].Address);
|
||||||
static char initrd = 0;
|
static char initrd = 0;
|
||||||
if (!initrd++)
|
if (!initrd++)
|
||||||
new VirtualFileSystem::USTAR((uintptr_t)bInfo.Modules[i].Address, vfs);
|
new VirtualFileSystem::USTAR((uintptr_t)bInfo.Modules[i].Address, vfs);
|
||||||
}
|
}
|
||||||
if (strcmp(bInfo.Modules[i].CommandLine, "bootanim") == 0 && Config.BootAnimation)
|
if (strcmp(bInfo.Modules[i].CommandLine, "bootanim") == 0 && Config.BootAnimation)
|
||||||
{
|
{
|
||||||
debug("Found bootanim at %p", bInfo.Modules[i].Address);
|
debug("Found bootanim at %p", bInfo.Modules[i].Address);
|
||||||
static char bootanim = 0;
|
static char bootanim = 0;
|
||||||
if (!bootanim++)
|
if (!bootanim++)
|
||||||
new VirtualFileSystem::USTAR((uintptr_t)bInfo.Modules[i].Address, bootanim_vfs);
|
new VirtualFileSystem::USTAR((uintptr_t)bInfo.Modules[i].Address, bootanim_vfs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vfs->GetRootNode()->Children.size() == 0)
|
if (vfs->GetRootNode()->Children.size() == 0)
|
||||||
{
|
{
|
||||||
VirtualFileSystem::FileSystemOperations null_op = {
|
VirtualFileSystem::FileSystemOperations null_op = {
|
||||||
.Name = "null",
|
.Name = "null",
|
||||||
};
|
};
|
||||||
|
|
||||||
vfs->CreateRoot("/", &null_op);
|
vfs->CreateRoot("/", &null_op);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vfs->PathExists("/system"))
|
if (!vfs->PathExists("/system"))
|
||||||
vfs->Create("/system", NodeFlags::DIRECTORY);
|
vfs->Create("/system", NodeFlags::DIRECTORY);
|
||||||
|
|
||||||
if (!vfs->PathExists("/system/dev"))
|
if (!vfs->PathExists("/system/dev"))
|
||||||
DevFS = vfs->Create("/system/dev", NodeFlags::DIRECTORY);
|
DevFS = vfs->Create("/system/dev", NodeFlags::DIRECTORY);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
File dev = vfs->Open("/system/dev");
|
File dev = vfs->Open("/system/dev");
|
||||||
if (dev.node->Flags != NodeFlags::DIRECTORY)
|
if (dev.node->Flags != NodeFlags::DIRECTORY)
|
||||||
{
|
{
|
||||||
KPrint("\eE85230/system/dev is not a directory! Halting...");
|
KPrint("\eE85230/system/dev is not a directory! Halting...");
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
vfs->Close(dev);
|
vfs->Close(dev);
|
||||||
DevFS = dev.node;
|
DevFS = dev.node;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vfs->PathExists("/system/mnt"))
|
if (!vfs->PathExists("/system/mnt"))
|
||||||
MntFS = vfs->Create("/system/mnt", NodeFlags::DIRECTORY);
|
MntFS = vfs->Create("/system/mnt", NodeFlags::DIRECTORY);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
File mnt = vfs->Open("/system/mnt");
|
File mnt = vfs->Open("/system/mnt");
|
||||||
if (mnt.node->Flags != NodeFlags::DIRECTORY)
|
if (mnt.node->Flags != NodeFlags::DIRECTORY)
|
||||||
{
|
{
|
||||||
KPrint("\eE85230/system/mnt is not a directory! Halting...");
|
KPrint("\eE85230/system/mnt is not a directory! Halting...");
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
vfs->Close(mnt);
|
vfs->Close(mnt);
|
||||||
MntFS = mnt.node;
|
MntFS = mnt.node;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vfs->PathExists("/system/proc"))
|
if (!vfs->PathExists("/system/proc"))
|
||||||
ProcFS = vfs->Create("/system/proc", NodeFlags::DIRECTORY);
|
ProcFS = vfs->Create("/system/proc", NodeFlags::DIRECTORY);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
File proc = vfs->Open("/system/proc", nullptr);
|
File proc = vfs->Open("/system/proc", nullptr);
|
||||||
if (proc.node->Flags != NodeFlags::DIRECTORY)
|
if (proc.node->Flags != NodeFlags::DIRECTORY)
|
||||||
{
|
{
|
||||||
KPrint("\eE85230/system/proc is not a directory! Halting...");
|
KPrint("\eE85230/system/proc is not a directory! Halting...");
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
vfs->Close(proc);
|
vfs->Close(proc);
|
||||||
ProcFS = proc.node;
|
ProcFS = proc.node;
|
||||||
}
|
}
|
||||||
|
|
||||||
KPrint("\e058C19################################");
|
KPrint("\e058C19################################");
|
||||||
TaskManager = new Tasking::Task((Tasking::IP)KernelMainThread);
|
TaskManager = new Tasking::Task((Tasking::IP)KernelMainThread);
|
||||||
CPU::Halt(true);
|
CPU::Halt(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*CallPtr)(void);
|
typedef void (*CallPtr)(void);
|
||||||
@ -491,104 +492,104 @@ extern CallPtr __fini_array_start[0], __fini_array_end[0];
|
|||||||
|
|
||||||
EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info)
|
EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info)
|
||||||
{
|
{
|
||||||
trace("Hello, World!");
|
trace("Hello, World!");
|
||||||
|
|
||||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
|
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
|
||||||
{
|
{
|
||||||
debug("\n\n----------------------------------------\nDEBUGGER DETECTED\n----------------------------------------\n\n");
|
debug("\n\n----------------------------------------\nDEBUGGER DETECTED\n----------------------------------------\n\n");
|
||||||
DebuggerIsAttached = true;
|
DebuggerIsAttached = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&bInfo, Info, sizeof(BootInfo));
|
memcpy(&bInfo, Info, sizeof(BootInfo));
|
||||||
debug("BootInfo structure is at %p", &bInfo);
|
debug("BootInfo structure is at %p", &bInfo);
|
||||||
|
|
||||||
// https://wiki.osdev.org/Calling_Global_Constructors
|
// https://wiki.osdev.org/Calling_Global_Constructors
|
||||||
trace("There are %d constructors to call", __init_array_end - __init_array_start);
|
trace("There are %d constructors to call", __init_array_end - __init_array_start);
|
||||||
for (CallPtr *func = __init_array_start; func != __init_array_end; func++)
|
for (CallPtr *func = __init_array_start; func != __init_array_end; func++)
|
||||||
(*func)();
|
(*func)();
|
||||||
|
|
||||||
InitializeMemoryManagement();
|
InitializeMemoryManagement();
|
||||||
|
|
||||||
void *KernelStackAddress = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
|
void *KernelStackAddress = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
|
||||||
uintptr_t KernelStack = (uintptr_t)KernelStackAddress + STACK_SIZE - 0x10;
|
uintptr_t KernelStack = (uintptr_t)KernelStackAddress + STACK_SIZE - 0x10;
|
||||||
debug("Kernel stack: %#lx-%#lx", KernelStackAddress, KernelStack);
|
debug("Kernel stack: %#lx-%#lx", KernelStackAddress, KernelStack);
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
asmv("mov %0, %%rsp"
|
asmv("mov %0, %%rsp"
|
||||||
:
|
:
|
||||||
: "r"(KernelStack)
|
: "r"(KernelStack)
|
||||||
: "memory");
|
: "memory");
|
||||||
asmv("mov $0, %rbp");
|
asmv("mov $0, %rbp");
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
asmv("mov %0, %%esp"
|
asmv("mov %0, %%esp"
|
||||||
:
|
:
|
||||||
: "r"(KernelStack)
|
: "r"(KernelStack)
|
||||||
: "memory");
|
: "memory");
|
||||||
asmv("mov $0, %ebp");
|
asmv("mov $0, %ebp");
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
#warning "Kernel stack is not set!"
|
#warning "Kernel stack is not set!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/* I had to do this because KernelAllocator
|
/* I had to do this because KernelAllocator
|
||||||
* is a global constructor but we need
|
* is a global constructor but we need
|
||||||
* memory management to be initialized first.
|
* memory management to be initialized first.
|
||||||
*/
|
*/
|
||||||
TestString();
|
TestString();
|
||||||
TestMemoryAllocation();
|
TestMemoryAllocation();
|
||||||
#endif
|
#endif
|
||||||
EnableProfiler = true;
|
EnableProfiler = true;
|
||||||
Main();
|
Main();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
|
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
|
||||||
|
|
||||||
EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot)
|
EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot)
|
||||||
{
|
{
|
||||||
UNUSED(Reboot);
|
UNUSED(Reboot);
|
||||||
/* TODO: Announce shutdown */
|
/* TODO: Announce shutdown */
|
||||||
|
|
||||||
trace("\n\n\n#################### SYSTEM SHUTTING DOWN ####################\n\n");
|
trace("\n\n\n#################### SYSTEM SHUTTING DOWN ####################\n\n");
|
||||||
|
|
||||||
if (RecoveryScreen)
|
if (RecoveryScreen)
|
||||||
delete RecoveryScreen, RecoveryScreen = nullptr;
|
delete RecoveryScreen, RecoveryScreen = nullptr;
|
||||||
|
|
||||||
if (NIManager)
|
if (NIManager)
|
||||||
delete NIManager, NIManager = nullptr;
|
delete NIManager, NIManager = nullptr;
|
||||||
|
|
||||||
if (DiskManager)
|
if (DiskManager)
|
||||||
delete DiskManager, DiskManager = nullptr;
|
delete DiskManager, DiskManager = nullptr;
|
||||||
|
|
||||||
if (DriverManager)
|
if (DriverManager)
|
||||||
delete DriverManager, DriverManager = nullptr;
|
delete DriverManager, DriverManager = nullptr;
|
||||||
|
|
||||||
if (TaskManager)
|
if (TaskManager)
|
||||||
{
|
{
|
||||||
TaskManager->SignalShutdown();
|
TaskManager->SignalShutdown();
|
||||||
delete TaskManager, TaskManager = nullptr;
|
delete TaskManager, TaskManager = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vfs)
|
if (vfs)
|
||||||
delete vfs, vfs = nullptr;
|
delete vfs, vfs = nullptr;
|
||||||
|
|
||||||
if (bootanim_vfs)
|
if (bootanim_vfs)
|
||||||
delete bootanim_vfs, bootanim_vfs = nullptr;
|
delete bootanim_vfs, bootanim_vfs = nullptr;
|
||||||
|
|
||||||
if (TimeManager)
|
if (TimeManager)
|
||||||
delete TimeManager, TimeManager = nullptr;
|
delete TimeManager, TimeManager = nullptr;
|
||||||
|
|
||||||
if (Display)
|
if (Display)
|
||||||
delete Display, Display = nullptr;
|
delete Display, Display = nullptr;
|
||||||
// PowerManager should not be called
|
// PowerManager should not be called
|
||||||
|
|
||||||
// https://wiki.osdev.org/Calling_Global_Constructors
|
// https://wiki.osdev.org/Calling_Global_Constructors
|
||||||
debug("Calling destructors...");
|
debug("Calling destructors...");
|
||||||
for (CallPtr *func = __fini_array_start; func != __fini_array_end; func++)
|
for (CallPtr *func = __fini_array_start; func != __fini_array_end; func++)
|
||||||
(*func)();
|
(*func)();
|
||||||
debug("Done.");
|
debug("Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
EXTERNC void TaskingPanic()
|
EXTERNC void TaskingPanic()
|
||||||
{
|
{
|
||||||
if (TaskManager)
|
if (TaskManager)
|
||||||
TaskManager->Panic();
|
TaskManager->Panic();
|
||||||
}
|
}
|
||||||
|
697
KernelThread.cpp
697
KernelThread.cpp
@ -57,220 +57,220 @@ NewLock(ShutdownLock);
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void TreeFS(Node *node, int Depth)
|
void TreeFS(Node *node, int Depth)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
foreach (auto Chld in node->Children)
|
foreach (auto Chld in node->Children)
|
||||||
{
|
{
|
||||||
printf("%*c %s\eFFFFFF\n", Depth, ' ', Chld->Name);
|
printf("%*c %s\eFFFFFF\n", Depth, ' ', Chld->Name);
|
||||||
if (!Config.BootAnimation)
|
if (!Config.BootAnimation)
|
||||||
Display->SetBuffer(0);
|
Display->SetBuffer(0);
|
||||||
TaskManager->Sleep(100);
|
TaskManager->Sleep(100);
|
||||||
TreeFS(Chld, Depth + 1);
|
TreeFS(Chld, Depth + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Statuses[] = {
|
const char *Statuses[] = {
|
||||||
"FF0000", /* Unknown */
|
"FF0000", /* Unknown */
|
||||||
"AAFF00", /* Ready */
|
"AAFF00", /* Ready */
|
||||||
"00AA00", /* Running */
|
"00AA00", /* Running */
|
||||||
"FFAA00", /* Sleeping */
|
"FFAA00", /* Sleeping */
|
||||||
"FFAA00", /* Waiting */
|
"FFAA00", /* Waiting */
|
||||||
"FF0088", /* Stopped */
|
"FF0088", /* Stopped */
|
||||||
"FF0000", /* Terminated */
|
"FF0000", /* Terminated */
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *StatusesSign[] = {
|
const char *StatusesSign[] = {
|
||||||
"Unknown",
|
"Unknown",
|
||||||
"Ready",
|
"Ready",
|
||||||
"Run",
|
"Run",
|
||||||
"Sleep",
|
"Sleep",
|
||||||
"Wait",
|
"Wait",
|
||||||
"Stop",
|
"Stop",
|
||||||
"Terminated",
|
"Terminated",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *SuccessSourceStrings[] = {
|
const char *SuccessSourceStrings[] = {
|
||||||
"Unknown",
|
"Unknown",
|
||||||
"GetNextAvailableThread",
|
"GetNextAvailableThread",
|
||||||
"GetNextAvailableProcess",
|
"GetNextAvailableProcess",
|
||||||
"SchedulerSearchProcessThread",
|
"SchedulerSearchProcessThread",
|
||||||
};
|
};
|
||||||
|
|
||||||
void TaskMgr_Dummy100Usage()
|
void TaskMgr_Dummy100Usage()
|
||||||
{
|
{
|
||||||
while (1)
|
while (1)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskMgr_Dummy0Usage()
|
void TaskMgr_Dummy0Usage()
|
||||||
{
|
{
|
||||||
while (1)
|
while (1)
|
||||||
TaskManager->Sleep(1000000);
|
TaskManager->Sleep(1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t GetUsage(uint64_t OldSystemTime, Tasking::TaskInfo *Info)
|
uint64_t GetUsage(uint64_t OldSystemTime, Tasking::TaskInfo *Info)
|
||||||
{
|
{
|
||||||
/* https://github.com/reactos/reactos/blob/560671a784c1e0e0aa7590df5e0598c1e2f41f5a/base/applications/taskmgr/perfdata.c#L347 */
|
/* https://github.com/reactos/reactos/blob/560671a784c1e0e0aa7590df5e0598c1e2f41f5a/base/applications/taskmgr/perfdata.c#L347 */
|
||||||
if (Info->OldKernelTime || Info->OldUserTime)
|
if (Info->OldKernelTime || Info->OldUserTime)
|
||||||
{
|
{
|
||||||
uint64_t SystemTime = TimeManager->GetCounter() - OldSystemTime;
|
uint64_t SystemTime = TimeManager->GetCounter() - OldSystemTime;
|
||||||
uint64_t CurrentTime = Info->KernelTime + Info->UserTime;
|
uint64_t CurrentTime = Info->KernelTime + Info->UserTime;
|
||||||
uint64_t OldTime = Info->OldKernelTime + Info->OldUserTime;
|
uint64_t OldTime = Info->OldKernelTime + Info->OldUserTime;
|
||||||
uint64_t CpuUsage = (CurrentTime - OldTime) / SystemTime;
|
uint64_t CpuUsage = (CurrentTime - OldTime) / SystemTime;
|
||||||
CpuUsage = CpuUsage * 100;
|
CpuUsage = CpuUsage * 100;
|
||||||
|
|
||||||
// debug("CurrentTime: %ld OldTime: %ld Time Diff: %ld Usage: %ld%%",
|
// debug("CurrentTime: %ld OldTime: %ld Time Diff: %ld Usage: %ld%%",
|
||||||
// CurrentTime, OldTime, SystemTime, CpuUsage);
|
// CurrentTime, OldTime, SystemTime, CpuUsage);
|
||||||
|
|
||||||
Info->OldKernelTime = Info->KernelTime;
|
Info->OldKernelTime = Info->KernelTime;
|
||||||
Info->OldUserTime = Info->UserTime;
|
Info->OldUserTime = Info->UserTime;
|
||||||
return CpuUsage;
|
return CpuUsage;
|
||||||
}
|
}
|
||||||
Info->OldKernelTime = Info->KernelTime;
|
Info->OldKernelTime = Info->KernelTime;
|
||||||
Info->OldUserTime = Info->UserTime;
|
Info->OldUserTime = Info->UserTime;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ShowTaskManager = 0;
|
static int ShowTaskManager = 0;
|
||||||
|
|
||||||
void TaskMgr()
|
void TaskMgr()
|
||||||
{
|
{
|
||||||
TaskManager->GetCurrentThread()->Rename("Debug Task Manager");
|
TaskManager->GetCurrentThread()->Rename("Debug Task Manager");
|
||||||
TaskManager->GetCurrentThread()->SetPriority(Tasking::Low);
|
TaskManager->GetCurrentThread()->SetPriority(Tasking::Low);
|
||||||
|
|
||||||
while (ShowTaskManager == 0)
|
while (ShowTaskManager == 0)
|
||||||
CPU::Pause();
|
CPU::Pause();
|
||||||
|
|
||||||
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy100Usage)->Rename("Dummy 100% Usage");
|
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy100Usage)->Rename("Dummy 100% Usage");
|
||||||
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy0Usage)->Rename("Dummy 0% Usage");
|
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy0Usage)->Rename("Dummy 0% Usage");
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
while (ShowTaskManager == 0)
|
while (ShowTaskManager == 0)
|
||||||
CPU::Pause();
|
CPU::Pause();
|
||||||
|
|
||||||
static int sanity = 0;
|
static int sanity = 0;
|
||||||
Video::ScreenBuffer *sb = Display->GetBuffer(0);
|
Video::ScreenBuffer *sb = Display->GetBuffer(0);
|
||||||
for (short i = 0; i < 1000; i++)
|
for (short i = 0; i < 1000; i++)
|
||||||
{
|
{
|
||||||
for (short j = 0; j < 500; j++)
|
for (short j = 0; j < 500; j++)
|
||||||
{
|
{
|
||||||
uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo.Framebuffer[0].BitsPerPixel / 8));
|
uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo.Framebuffer[0].BitsPerPixel / 8));
|
||||||
*Pixel = 0x222222;
|
*Pixel = 0x222222;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tmpX, tmpY;
|
uint32_t tmpX, tmpY;
|
||||||
Display->GetBufferCursor(0, &tmpX, &tmpY);
|
Display->GetBufferCursor(0, &tmpX, &tmpY);
|
||||||
Display->SetBufferCursor(0, 0, 0);
|
Display->SetBufferCursor(0, 0, 0);
|
||||||
printf("\eF02C21Task Manager\n");
|
printf("\eF02C21Task Manager\n");
|
||||||
static uint64_t OldSystemTime = 0;
|
static uint64_t OldSystemTime = 0;
|
||||||
foreach (auto Proc in TaskManager->GetProcessList())
|
foreach (auto Proc in TaskManager->GetProcessList())
|
||||||
{
|
{
|
||||||
if (!Proc)
|
if (!Proc)
|
||||||
continue;
|
continue;
|
||||||
int Status = Proc->Status;
|
int Status = Proc->Status;
|
||||||
uint64_t ProcessCpuUsage = GetUsage(OldSystemTime, &Proc->Info);
|
uint64_t ProcessCpuUsage = GetUsage(OldSystemTime, &Proc->Info);
|
||||||
printf("\e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld)\n",
|
printf("\e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld)\n",
|
||||||
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
|
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
|
||||||
|
|
||||||
foreach (auto Thd in Proc->Threads)
|
foreach (auto Thd in Proc->Threads)
|
||||||
{
|
{
|
||||||
if (!Thd)
|
if (!Thd)
|
||||||
continue;
|
continue;
|
||||||
Status = Thd->Status;
|
Status = Thd->Status;
|
||||||
uint64_t ThreadCpuUsage = GetUsage(OldSystemTime, &Thd->Info);
|
uint64_t ThreadCpuUsage = GetUsage(OldSystemTime, &Thd->Info);
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC",
|
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC",
|
||||||
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
|
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
|
||||||
Thd->Info.UserTime, Thd->Registers.rip,
|
Thd->Info.UserTime, Thd->Registers.rip,
|
||||||
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.rip) : "unknown");
|
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.rip) : "unknown");
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC",
|
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC",
|
||||||
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
|
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
|
||||||
Thd->Info.UserTime, Thd->Registers.eip,
|
Thd->Info.UserTime, Thd->Registers.eip,
|
||||||
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.eip) : "unknown");
|
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.eip) : "unknown");
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OldSystemTime = TimeManager->GetCounter();
|
OldSystemTime = TimeManager->GetCounter();
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
register uintptr_t CurrentStackAddress asm("rsp");
|
register uintptr_t CurrentStackAddress asm("rsp");
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
register uintptr_t CurrentStackAddress asm("esp");
|
register uintptr_t CurrentStackAddress asm("esp");
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
register uintptr_t CurrentStackAddress asm("sp");
|
register uintptr_t CurrentStackAddress asm("sp");
|
||||||
#endif
|
#endif
|
||||||
printf("Sanity: %d, Stack: %#lx", sanity++, CurrentStackAddress);
|
printf("Sanity: %d, Stack: %#lx", sanity++, CurrentStackAddress);
|
||||||
if (sanity > 1000)
|
if (sanity > 1000)
|
||||||
sanity = 0;
|
sanity = 0;
|
||||||
Display->SetBufferCursor(0, tmpX, tmpY);
|
Display->SetBufferCursor(0, tmpX, tmpY);
|
||||||
if (!Config.BootAnimation)
|
if (!Config.BootAnimation)
|
||||||
Display->SetBuffer(0);
|
Display->SetBuffer(0);
|
||||||
|
|
||||||
TaskManager->Sleep(100);
|
TaskManager->Sleep(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSyscallsKernel()
|
void TestSyscallsKernel()
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
KPrint("Testing syscalls...");
|
KPrint("Testing syscalls...");
|
||||||
Tasking::PCB *SyscallsTestProcess = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(),
|
Tasking::PCB *SyscallsTestProcess = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(),
|
||||||
"Syscalls Test",
|
"Syscalls Test",
|
||||||
Tasking::TaskTrustLevel::User,
|
Tasking::TaskTrustLevel::User,
|
||||||
KernelSymbolTable);
|
KernelSymbolTable);
|
||||||
|
|
||||||
Tasking::TCB *SyscallsTestThread = TaskManager->CreateThread(SyscallsTestProcess,
|
Tasking::TCB *SyscallsTestThread = TaskManager->CreateThread(SyscallsTestProcess,
|
||||||
(Tasking::IP)TestSyscalls,
|
(Tasking::IP)TestSyscalls,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
std::vector<AuxiliaryVector>(),
|
std::vector<AuxiliaryVector>(),
|
||||||
0,
|
0,
|
||||||
Tasking::TaskArchitecture::x64,
|
Tasking::TaskArchitecture::x64,
|
||||||
Tasking::TaskCompatibility::Native,
|
Tasking::TaskCompatibility::Native,
|
||||||
true);
|
true);
|
||||||
SyscallsTestThread->SetCritical(true);
|
SyscallsTestThread->SetCritical(true);
|
||||||
TaskManager->GetSecurityManager()->TrustToken(SyscallsTestThread->Security.UniqueToken, Tasking::TTL::FullTrust);
|
TaskManager->GetSecurityManager()->TrustToken(SyscallsTestThread->Security.UniqueToken, Tasking::TTL::FullTrust);
|
||||||
|
|
||||||
Memory::Virtual va = Memory::Virtual(SyscallsTestProcess->PageTable);
|
Memory::Virtual va = Memory::Virtual(SyscallsTestProcess->PageTable);
|
||||||
|
|
||||||
// va.Remap((void *)TestSyscalls, va.GetPhysical((void *)TestSyscalls), Memory::P | Memory::RW | Memory::US);
|
// va.Remap((void *)TestSyscalls, va.GetPhysical((void *)TestSyscalls), Memory::P | Memory::RW | Memory::US);
|
||||||
|
|
||||||
// for (uintptr_t k = (uintptr_t)&_kernel_start; k < (uintptr_t)&_kernel_end; k += PAGE_SIZE)
|
// for (uintptr_t k = (uintptr_t)&_kernel_start; k < (uintptr_t)&_kernel_end; k += PAGE_SIZE)
|
||||||
// {
|
// {
|
||||||
// va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
|
// va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
|
||||||
// debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k));
|
// debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
for (uintptr_t k = (uintptr_t)TestSyscalls - PAGE_SIZE; k < (uintptr_t)TestSyscalls + FROM_PAGES(5); k += PAGE_SIZE)
|
for (uintptr_t k = (uintptr_t)TestSyscalls - PAGE_SIZE; k < (uintptr_t)TestSyscalls + FROM_PAGES(5); k += PAGE_SIZE)
|
||||||
{
|
{
|
||||||
va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
|
va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
|
||||||
debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k));
|
debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k));
|
||||||
}
|
}
|
||||||
|
|
||||||
SyscallsTestThread->Status = Tasking::TaskStatus::Ready;
|
SyscallsTestThread->Status = Tasking::TaskStatus::Ready;
|
||||||
TaskManager->WaitForThread(SyscallsTestThread);
|
TaskManager->WaitForThread(SyscallsTestThread);
|
||||||
KPrint("Test complete");
|
KPrint("Test complete");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Execute::SpawnData SpawnInit()
|
Execute::SpawnData SpawnInit()
|
||||||
{
|
{
|
||||||
const char *envp[5] = {
|
const char *envp[5] = {
|
||||||
"PATH=/system:/system/bin",
|
"PATH=/system:/system/bin",
|
||||||
"TERM=tty",
|
"TERM=tty",
|
||||||
"HOME=/",
|
"HOME=/",
|
||||||
"USER=root",
|
"USER=root",
|
||||||
nullptr};
|
nullptr};
|
||||||
|
|
||||||
const char *argv[4] = {
|
const char *argv[4] = {
|
||||||
Config.InitPath,
|
Config.InitPath,
|
||||||
"--init",
|
"--init",
|
||||||
"--critical",
|
"--critical",
|
||||||
nullptr};
|
nullptr};
|
||||||
|
|
||||||
return Execute::Spawn(Config.InitPath, argv, envp);
|
return Execute::Spawn(Config.InitPath, argv, envp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Files: 0.tga 1.tga ... 26.tga */
|
/* Files: 0.tga 1.tga ... 26.tga */
|
||||||
@ -280,261 +280,262 @@ size_t FrameCount = 1;
|
|||||||
|
|
||||||
void BootLogoAnimationThread()
|
void BootLogoAnimationThread()
|
||||||
{
|
{
|
||||||
char BootAnimPath[16];
|
char BootAnimPath[16];
|
||||||
while (FrameCount < 27)
|
while (FrameCount < 27)
|
||||||
{
|
{
|
||||||
sprintf(BootAnimPath, "%ld.tga", FrameCount);
|
sprintf(BootAnimPath, "%ld.tga", FrameCount);
|
||||||
File ba = bootanim_vfs->Open(BootAnimPath);
|
File ba = bootanim_vfs->Open(BootAnimPath);
|
||||||
if (!ba.IsOK())
|
if (!ba.IsOK())
|
||||||
{
|
{
|
||||||
bootanim_vfs->Close(ba);
|
bootanim_vfs->Close(ba);
|
||||||
debug("Failed to load boot animation frame %s", BootAnimPath);
|
debug("Failed to load boot animation frame %s", BootAnimPath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameSizes[FrameCount] = s_cst(uint32_t, ba.node->Length);
|
FrameSizes[FrameCount] = s_cst(uint32_t, ba.node->Length);
|
||||||
Frames[FrameCount] = new uint8_t[ba.node->Length];
|
Frames[FrameCount] = new uint8_t[ba.node->Length];
|
||||||
memcpy((void *)Frames[FrameCount], (void *)ba.node->Address, ba.node->Length);
|
memcpy((void *)Frames[FrameCount], (void *)ba.node->Address, ba.node->Length);
|
||||||
bootanim_vfs->Close(ba);
|
bootanim_vfs->Close(ba);
|
||||||
FrameCount++;
|
FrameCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t DispX = Display->GetBuffer(1)->Width;
|
uint32_t DispX = Display->GetBuffer(1)->Width;
|
||||||
uint32_t DispY = Display->GetBuffer(1)->Height;
|
uint32_t DispY = Display->GetBuffer(1)->Height;
|
||||||
|
|
||||||
for (size_t i = 1; i < FrameCount; i++)
|
for (size_t i = 1; i < FrameCount; i++)
|
||||||
{
|
{
|
||||||
int x, y, channels;
|
int x, y, channels;
|
||||||
|
|
||||||
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels))
|
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, STBI_rgb_alpha);
|
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, STBI_rgb_alpha);
|
||||||
|
|
||||||
if (img == NULL)
|
if (img == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int offsetX = DispX / 2 - x / 2;
|
int offsetX = DispX / 2 - x / 2;
|
||||||
int offsetY = DispY / 2 - y / 2;
|
int offsetY = DispY / 2 - y / 2;
|
||||||
|
|
||||||
for (int i = 0; i < x * y; i++)
|
for (int i = 0; i < x * y; i++)
|
||||||
{
|
{
|
||||||
uint32_t pixel = ((uint32_t *)img)[i];
|
uint32_t pixel = ((uint32_t *)img)[i];
|
||||||
int r = (pixel >> 16) & 0xFF;
|
int r = (pixel >> 16) & 0xFF;
|
||||||
int g = (pixel >> 8) & 0xFF;
|
int g = (pixel >> 8) & 0xFF;
|
||||||
int b = (pixel >> 0) & 0xFF;
|
int b = (pixel >> 0) & 0xFF;
|
||||||
int a = (pixel >> 24) & 0xFF;
|
int a = (pixel >> 24) & 0xFF;
|
||||||
|
|
||||||
if (a != 0xFF)
|
if (a != 0xFF)
|
||||||
{
|
{
|
||||||
r = (r * a) / 0xFF;
|
r = (r * a) / 0xFF;
|
||||||
g = (g * a) / 0xFF;
|
g = (g * a) / 0xFF;
|
||||||
b = (b * a) / 0xFF;
|
b = (b * a) / 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1);
|
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(img);
|
free(img);
|
||||||
Display->SetBuffer(1);
|
Display->SetBuffer(1);
|
||||||
TaskManager->Sleep(50);
|
TaskManager->Sleep(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
int brightness = 100;
|
int brightness = 100;
|
||||||
while (brightness >= 0)
|
while (brightness >= 0)
|
||||||
{
|
{
|
||||||
brightness -= 10;
|
brightness -= 10;
|
||||||
Display->SetBrightness(brightness, 1);
|
Display->SetBrightness(brightness, 1);
|
||||||
Display->SetBuffer(1);
|
Display->SetBuffer(1);
|
||||||
TaskManager->Sleep(5);
|
TaskManager->Sleep(5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExitLogoAnimationThread()
|
void ExitLogoAnimationThread()
|
||||||
{
|
{
|
||||||
Display->SetBrightness(100, 1);
|
Display->SetBrightness(100, 1);
|
||||||
Display->SetBuffer(1);
|
Display->SetBuffer(1);
|
||||||
|
|
||||||
/* Files: 26.tga 25.tga ... 1.tga */
|
/* Files: 26.tga 25.tga ... 1.tga */
|
||||||
uint32_t DispX = Display->GetBuffer(1)->Width;
|
uint32_t DispX = Display->GetBuffer(1)->Width;
|
||||||
uint32_t DispY = Display->GetBuffer(1)->Height;
|
uint32_t DispY = Display->GetBuffer(1)->Height;
|
||||||
|
|
||||||
for (size_t i = 40; i > 25; i--)
|
for (size_t i = 40; i > 25; i--)
|
||||||
{
|
{
|
||||||
int x, y, channels;
|
int x, y, channels;
|
||||||
|
|
||||||
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels))
|
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, STBI_rgb_alpha);
|
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, STBI_rgb_alpha);
|
||||||
|
|
||||||
if (img == NULL)
|
if (img == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int offsetX = DispX / 2 - x / 2;
|
int offsetX = DispX / 2 - x / 2;
|
||||||
int offsetY = DispY / 2 - y / 2;
|
int offsetY = DispY / 2 - y / 2;
|
||||||
|
|
||||||
for (int i = 0; i < x * y; i++)
|
for (int i = 0; i < x * y; i++)
|
||||||
{
|
{
|
||||||
uint32_t pixel = ((uint32_t *)img)[i];
|
uint32_t pixel = ((uint32_t *)img)[i];
|
||||||
int r = (pixel >> 16) & 0xFF;
|
int r = (pixel >> 16) & 0xFF;
|
||||||
int g = (pixel >> 8) & 0xFF;
|
int g = (pixel >> 8) & 0xFF;
|
||||||
int b = (pixel >> 0) & 0xFF;
|
int b = (pixel >> 0) & 0xFF;
|
||||||
int a = (pixel >> 24) & 0xFF;
|
int a = (pixel >> 24) & 0xFF;
|
||||||
|
|
||||||
if (a != 0xFF)
|
if (a != 0xFF)
|
||||||
{
|
{
|
||||||
r = (r * a) / 0xFF;
|
r = (r * a) / 0xFF;
|
||||||
g = (g * a) / 0xFF;
|
g = (g * a) / 0xFF;
|
||||||
b = (b * a) / 0xFF;
|
b = (b * a) / 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1);
|
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(img);
|
free(img);
|
||||||
Display->SetBuffer(1);
|
Display->SetBuffer(1);
|
||||||
TaskManager->Sleep(50);
|
TaskManager->Sleep(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
int brightness = 100;
|
int brightness = 100;
|
||||||
while (brightness >= 0)
|
while (brightness >= 0)
|
||||||
{
|
{
|
||||||
brightness -= 10;
|
brightness -= 10;
|
||||||
Display->SetBrightness(brightness, 1);
|
Display->SetBrightness(brightness, 1);
|
||||||
Display->SetBuffer(1);
|
Display->SetBuffer(1);
|
||||||
TaskManager->Sleep(5);
|
TaskManager->Sleep(5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CleanupProcessesThreadWrapper() { TaskManager->CleanupProcessesThread(); }
|
void CleanupProcessesThreadWrapper() { TaskManager->CleanupProcessesThread(); }
|
||||||
|
|
||||||
void KernelMainThread()
|
void KernelMainThread()
|
||||||
{
|
{
|
||||||
Tasking::TCB *clnThd = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)CleanupProcessesThreadWrapper);
|
Tasking::TCB *clnThd = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)CleanupProcessesThreadWrapper);
|
||||||
clnThd->SetPriority(Tasking::Idle);
|
clnThd->SetPriority(Tasking::Idle);
|
||||||
TaskManager->SetCleanupThread(clnThd);
|
TaskManager->SetCleanupThread(clnThd);
|
||||||
TaskManager->GetCurrentThread()->SetPriority(Tasking::Critical);
|
TaskManager->GetCurrentThread()->SetPriority(Tasking::Critical);
|
||||||
|
|
||||||
Tasking::TCB *blaThread = nullptr;
|
Tasking::TCB *blaThread = nullptr;
|
||||||
|
|
||||||
if (Config.BootAnimation)
|
if (Config.BootAnimation)
|
||||||
{
|
{
|
||||||
blaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)BootLogoAnimationThread);
|
blaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)BootLogoAnimationThread);
|
||||||
blaThread->Rename("Logo Animation");
|
blaThread->Rename("Logo Animation");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
Tasking::TCB *tskMgr = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr);
|
Tasking::TCB *tskMgr = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr);
|
||||||
TreeFS(vfs->GetRootNode(), 0);
|
TreeFS(vfs->GetRootNode(), 0);
|
||||||
TestSyscallsKernel();
|
TestSyscallsKernel();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
KPrint("Kernel Compiled at: %s %s with C++ Standard: %d", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
|
KPrint("Kernel Compiled at: %s %s with C++ Standard: %d", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
|
||||||
KPrint("C++ Language Version (__cplusplus): %ld", __cplusplus);
|
KPrint("C++ Language Version (__cplusplus): %ld", __cplusplus);
|
||||||
|
|
||||||
KPrint("Initializing Disk Manager...");
|
KPrint("Initializing Disk Manager...");
|
||||||
DiskManager = new Disk::Manager;
|
DiskManager = new Disk::Manager;
|
||||||
|
|
||||||
KPrint("Loading Drivers...");
|
KPrint("Loading Drivers...");
|
||||||
DriverManager = new Driver::Driver;
|
DriverManager = new Driver::Driver;
|
||||||
|
DriverManager->LoadDrivers();
|
||||||
|
|
||||||
KPrint("Fetching Disks...");
|
KPrint("Fetching Disks...");
|
||||||
if (DriverManager->GetDrivers().size() > 0)
|
if (DriverManager->GetDrivers().size() > 0)
|
||||||
{
|
{
|
||||||
foreach (auto Driver in DriverManager->GetDrivers())
|
foreach (auto Driver in DriverManager->GetDrivers())
|
||||||
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Storage)
|
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Storage)
|
||||||
DiskManager->FetchDisks(Driver.DriverUID);
|
DiskManager->FetchDisks(Driver.DriverUID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
KPrint("\eE85230No disk drivers found! Cannot fetch disks!");
|
KPrint("\eE85230No disk drivers found! Cannot fetch disks!");
|
||||||
|
|
||||||
KPrint("Initializing Network Interface Manager...");
|
KPrint("Initializing Network Interface Manager...");
|
||||||
NIManager = new NetworkInterfaceManager::NetworkInterface;
|
NIManager = new NetworkInterfaceManager::NetworkInterface;
|
||||||
KPrint("Starting Network Interface Manager...");
|
KPrint("Starting Network Interface Manager...");
|
||||||
NIManager->StartService();
|
NIManager->StartService();
|
||||||
|
|
||||||
printf("\eCCCCCC[\e00AEFFKernel Thread\eCCCCCC] Setting up userspace");
|
printf("\eCCCCCC[\e00AEFFKernel Thread\eCCCCCC] Setting up userspace");
|
||||||
if (!Config.BootAnimation)
|
if (!Config.BootAnimation)
|
||||||
Display->SetBuffer(0);
|
Display->SetBuffer(0);
|
||||||
|
|
||||||
Execute::SpawnData ret = {Execute::ExStatus::Unknown, nullptr, nullptr};
|
Execute::SpawnData ret = {Execute::ExStatus::Unknown, nullptr, nullptr};
|
||||||
Tasking::TCB *ExecuteThread = nullptr;
|
Tasking::TCB *ExecuteThread = nullptr;
|
||||||
int ExitCode = -1;
|
int ExitCode = -1;
|
||||||
ExecuteThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)Execute::StartExecuteService);
|
ExecuteThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)Execute::StartExecuteService);
|
||||||
ExecuteThread->Rename("Library Manager");
|
ExecuteThread->Rename("Library Manager");
|
||||||
ExecuteThread->SetCritical(true);
|
ExecuteThread->SetCritical(true);
|
||||||
ExecuteThread->SetPriority(Tasking::Idle);
|
ExecuteThread->SetPriority(Tasking::Idle);
|
||||||
|
|
||||||
Display->Print('.', 0);
|
Display->Print('.', 0);
|
||||||
if (!Config.BootAnimation)
|
if (!Config.BootAnimation)
|
||||||
Display->SetBuffer(0);
|
Display->SetBuffer(0);
|
||||||
|
|
||||||
ret = SpawnInit();
|
ret = SpawnInit();
|
||||||
|
|
||||||
Display->Print('.', 0);
|
Display->Print('.', 0);
|
||||||
if (!Config.BootAnimation)
|
if (!Config.BootAnimation)
|
||||||
Display->SetBuffer(0);
|
Display->SetBuffer(0);
|
||||||
|
|
||||||
if (ret.Status != Execute::ExStatus::OK)
|
if (ret.Status != Execute::ExStatus::OK)
|
||||||
{
|
{
|
||||||
KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, ret.Status);
|
KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, ret.Status);
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
ret.Thread->SetCritical(true);
|
ret.Thread->SetCritical(true);
|
||||||
TaskManager->GetSecurityManager()->TrustToken(ret.Process->Security.UniqueToken, Tasking::TTL::FullTrust);
|
TaskManager->GetSecurityManager()->TrustToken(ret.Process->Security.UniqueToken, Tasking::TTL::FullTrust);
|
||||||
TaskManager->GetSecurityManager()->TrustToken(ret.Thread->Security.UniqueToken, Tasking::TTL::FullTrust);
|
TaskManager->GetSecurityManager()->TrustToken(ret.Thread->Security.UniqueToken, Tasking::TTL::FullTrust);
|
||||||
|
|
||||||
Display->Print('.', 0);
|
Display->Print('.', 0);
|
||||||
Display->Print('\n', 0);
|
Display->Print('\n', 0);
|
||||||
if (!Config.BootAnimation)
|
if (!Config.BootAnimation)
|
||||||
Display->SetBuffer(0);
|
Display->SetBuffer(0);
|
||||||
|
|
||||||
KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath);
|
KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath);
|
||||||
TaskManager->GetCurrentThread()->SetPriority(Tasking::Idle);
|
TaskManager->GetCurrentThread()->SetPriority(Tasking::Idle);
|
||||||
|
|
||||||
TaskManager->WaitForThread(ret.Thread);
|
TaskManager->WaitForThread(ret.Thread);
|
||||||
ExitCode = ret.Thread->GetExitCode();
|
ExitCode = ret.Thread->GetExitCode();
|
||||||
Exit:
|
Exit:
|
||||||
if (ExitCode != 0)
|
if (ExitCode != 0)
|
||||||
{
|
{
|
||||||
KPrint("\eE85230Userspace process exited with code %d", ExitCode);
|
KPrint("\eE85230Userspace process exited with code %d", ExitCode);
|
||||||
KPrint("Dropping to recovery screen...");
|
KPrint("Dropping to recovery screen...");
|
||||||
TaskManager->Sleep(2500);
|
TaskManager->Sleep(2500);
|
||||||
TaskManager->WaitForThread(blaThread);
|
TaskManager->WaitForThread(blaThread);
|
||||||
RecoveryScreen = new Recovery::KernelRecovery;
|
RecoveryScreen = new Recovery::KernelRecovery;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
KPrint("\eFF7900%s process exited with code %d and it didn't invoked the shutdown function.",
|
KPrint("\eFF7900%s process exited with code %d and it didn't invoked the shutdown function.",
|
||||||
Config.InitPath, ExitCode);
|
Config.InitPath, ExitCode);
|
||||||
KPrint("System Halted");
|
KPrint("System Halted");
|
||||||
}
|
}
|
||||||
CPU::Halt(true);
|
CPU::Halt(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __no_stack_protector KernelShutdownThread(bool Reboot)
|
void __no_stack_protector KernelShutdownThread(bool Reboot)
|
||||||
{
|
{
|
||||||
SmartLock(ShutdownLock);
|
SmartLock(ShutdownLock);
|
||||||
debug("KernelShutdownThread(%s)", Reboot ? "true" : "false");
|
debug("KernelShutdownThread(%s)", Reboot ? "true" : "false");
|
||||||
if (Config.BootAnimation && TaskManager)
|
if (Config.BootAnimation && TaskManager)
|
||||||
{
|
{
|
||||||
if (RecoveryScreen)
|
if (RecoveryScreen)
|
||||||
delete RecoveryScreen, RecoveryScreen = nullptr;
|
delete RecoveryScreen, RecoveryScreen = nullptr;
|
||||||
|
|
||||||
Tasking::TCB *elaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)ExitLogoAnimationThread);
|
Tasking::TCB *elaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)ExitLogoAnimationThread);
|
||||||
elaThread->Rename("Logo Animation");
|
elaThread->Rename("Logo Animation");
|
||||||
TaskManager->WaitForThread(elaThread);
|
TaskManager->WaitForThread(elaThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
BeforeShutdown(Reboot);
|
BeforeShutdown(Reboot);
|
||||||
|
|
||||||
trace("%s...", Reboot ? "Rebooting" : "Shutting down");
|
trace("%s...", Reboot ? "Rebooting" : "Shutting down");
|
||||||
if (Reboot)
|
if (Reboot)
|
||||||
PowerManager->Reboot();
|
PowerManager->Reboot();
|
||||||
else
|
else
|
||||||
PowerManager->Shutdown();
|
PowerManager->Shutdown();
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KST_Reboot() { KernelShutdownThread(true); }
|
void KST_Reboot() { KernelShutdownThread(true); }
|
||||||
|
@ -34,64 +34,64 @@
|
|||||||
|
|
||||||
namespace NetworkInterfaceManager
|
namespace NetworkInterfaceManager
|
||||||
{
|
{
|
||||||
std::vector<Events *> RegisteredEvents;
|
std::vector<Events *> RegisteredEvents;
|
||||||
|
|
||||||
NetworkInterface::NetworkInterface()
|
NetworkInterface::NetworkInterface()
|
||||||
{
|
{
|
||||||
mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
||||||
if (DriverManager->GetDrivers().size() > 0)
|
if (DriverManager->GetDrivers().size() > 0)
|
||||||
{
|
{
|
||||||
foreach (auto Driver in DriverManager->GetDrivers())
|
foreach (auto Driver in DriverManager->GetDrivers())
|
||||||
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Network)
|
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Network)
|
||||||
this->FetchNetworkCards(Driver.DriverUID);
|
this->FetchNetworkCards(Driver.DriverUID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
KPrint("\eE85230No network drivers found! Cannot fetch network cards!");
|
KPrint("\eE85230No network drivers found! Cannot fetch network cards!");
|
||||||
|
|
||||||
DbgNetwork();
|
DbgNetwork();
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkInterface::~NetworkInterface()
|
NetworkInterface::~NetworkInterface()
|
||||||
{
|
{
|
||||||
debug("Destructor called");
|
debug("Destructor called");
|
||||||
|
|
||||||
// Stop the network stack
|
// Stop the network stack
|
||||||
this->StopNetworkStack();
|
this->StopNetworkStack();
|
||||||
|
|
||||||
// Unregister all events
|
// Unregister all events
|
||||||
RegisteredEvents.clear();
|
RegisteredEvents.clear();
|
||||||
|
|
||||||
foreach (auto inf in Interfaces)
|
foreach (auto inf in Interfaces)
|
||||||
{
|
{
|
||||||
if (inf)
|
if (inf)
|
||||||
{
|
{
|
||||||
Interfaces.remove(inf);
|
Interfaces.remove(inf);
|
||||||
delete inf, inf = nullptr;
|
delete inf, inf = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete all interfaces and their callbacks and free the memory
|
// Delete all interfaces and their callbacks and free the memory
|
||||||
delete mem, mem = nullptr;
|
delete mem, mem = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkInterface::FetchNetworkCards(unsigned long DriverUID)
|
void NetworkInterface::FetchNetworkCards(unsigned long DriverUID)
|
||||||
{
|
{
|
||||||
KernelCallback cb{};
|
KernelCallback cb{};
|
||||||
cb.Reason = FetchReason;
|
cb.Reason = FetchReason;
|
||||||
DriverManager->IOCB(DriverUID, &cb);
|
DriverManager->IOCB(DriverUID, &cb);
|
||||||
|
|
||||||
DeviceInterface *Iface = (DeviceInterface *)mem->RequestPages(TO_PAGES(sizeof(DeviceInterface) + 1));
|
DeviceInterface *Iface = (DeviceInterface *)mem->RequestPages(TO_PAGES(sizeof(DeviceInterface) + 1));
|
||||||
strcpy(Iface->Name, cb.NetworkCallback.Fetch.Name);
|
strcpy(Iface->Name, cb.NetworkCallback.Fetch.Name);
|
||||||
Iface->ID = this->CardIDs++;
|
Iface->ID = this->CardIDs++;
|
||||||
Iface->MAC.FromHex(cb.NetworkCallback.Fetch.MAC);
|
Iface->MAC.FromHex(cb.NetworkCallback.Fetch.MAC);
|
||||||
Iface->DriverID = DriverUID;
|
Iface->DriverID = DriverUID;
|
||||||
Interfaces.push_back(Iface);
|
Interfaces.push_back(Iface);
|
||||||
|
|
||||||
foreach (auto var in RegisteredEvents)
|
foreach (auto var in RegisteredEvents)
|
||||||
var->OnInterfaceAdded(Iface);
|
var->OnInterfaceAdded(Iface);
|
||||||
|
|
||||||
debug("Network Card: %s; MAC: %#lx", Iface->Name, Iface->MAC.ToHex());
|
debug("Network Card: %s; MAC: %#lx", Iface->Name, Iface->MAC.ToHex());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_NETWORK
|
#ifdef DEBUG_NETWORK
|
||||||
#define DbgWriteScreen(x, ...) KPrint(x, ##__VA_ARGS__)
|
#define DbgWriteScreen(x, ...) KPrint(x, ##__VA_ARGS__)
|
||||||
@ -99,152 +99,152 @@ namespace NetworkInterfaceManager
|
|||||||
#define DbgWriteScreen(x, ...) debug(x, ##__VA_ARGS__)
|
#define DbgWriteScreen(x, ...) debug(x, ##__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void NetworkInterface::StartNetworkStack()
|
void NetworkInterface::StartNetworkStack()
|
||||||
{
|
{
|
||||||
TaskManager->GetCurrentThread()->SetPriority(Tasking::TaskPriority::Critical);
|
TaskManager->GetCurrentThread()->SetPriority(Tasking::TaskPriority::Critical);
|
||||||
DeviceInterface *DefaultDevice = nullptr;
|
DeviceInterface *DefaultDevice = nullptr;
|
||||||
foreach (auto inf in Interfaces)
|
foreach (auto inf in Interfaces)
|
||||||
if (inf)
|
if (inf)
|
||||||
{
|
{
|
||||||
DefaultDevice = inf;
|
DefaultDevice = inf;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DefaultDevice)
|
if (!DefaultDevice)
|
||||||
error("No network device found!");
|
error("No network device found!");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DbgWriteScreen("Using %s (%s) as the default network device", DefaultDevice->Name, DefaultDevice->MAC.ToString());
|
DbgWriteScreen("Using %s (%s) as the default network device", DefaultDevice->Name, DefaultDevice->MAC.ToString());
|
||||||
NetworkEthernet::Ethernet *eth = new NetworkEthernet::Ethernet(DefaultDevice); // Use the first device found as the ethernet device
|
NetworkEthernet::Ethernet *eth = new NetworkEthernet::Ethernet(DefaultDevice); // Use the first device found as the ethernet device
|
||||||
NetworkARP::ARP *arp = new NetworkARP::ARP(eth);
|
NetworkARP::ARP *arp = new NetworkARP::ARP(eth);
|
||||||
NetworkIPv4::IPv4 *ipv4 = new NetworkIPv4::IPv4(arp, eth);
|
NetworkIPv4::IPv4 *ipv4 = new NetworkIPv4::IPv4(arp, eth);
|
||||||
NetworkUDP::UDP *udp = new NetworkUDP::UDP(ipv4, DefaultDevice);
|
NetworkUDP::UDP *udp = new NetworkUDP::UDP(ipv4, DefaultDevice);
|
||||||
NetworkUDP::Socket *DHCP_Socket = udp->Connect(InternetProtocol() /* Default value is 255.255.255.255 */, 67);
|
NetworkUDP::Socket *DHCP_Socket = udp->Connect(InternetProtocol() /* Default value is 255.255.255.255 */, 67);
|
||||||
NetworkDHCP::DHCP *dhcp = new NetworkDHCP::DHCP(DHCP_Socket, DefaultDevice);
|
NetworkDHCP::DHCP *dhcp = new NetworkDHCP::DHCP(DHCP_Socket, DefaultDevice);
|
||||||
debug("eth: %p; arp: %p; ipv4: %p; udp: %p; dhcp: %p", eth, arp, ipv4, udp, dhcp);
|
debug("eth: %p; arp: %p; ipv4: %p; udp: %p; dhcp: %p", eth, arp, ipv4, udp, dhcp);
|
||||||
udp->Bind(DHCP_Socket, dhcp);
|
udp->Bind(DHCP_Socket, dhcp);
|
||||||
dhcp->Request();
|
dhcp->Request();
|
||||||
|
|
||||||
DefaultDevice->IP.v4.FromHex(dhcp->IP.v4.ToHex());
|
DefaultDevice->IP.v4.FromHex(dhcp->IP.v4.ToHex());
|
||||||
ipv4->SubNetworkMaskIP = dhcp->SubNetworkMask;
|
ipv4->SubNetworkMaskIP = dhcp->SubNetworkMask;
|
||||||
ipv4->GatewayIP = dhcp->Gateway;
|
ipv4->GatewayIP = dhcp->Gateway;
|
||||||
arp->Broadcast(dhcp->Gateway);
|
arp->Broadcast(dhcp->Gateway);
|
||||||
TaskManager->Sleep(200);
|
TaskManager->Sleep(200);
|
||||||
DbgWriteScreen("IP: %s", dhcp->IP.v4.ToStringLittleEndian());
|
DbgWriteScreen("IP: %s", dhcp->IP.v4.ToStringLittleEndian());
|
||||||
DbgWriteScreen("SubNetwork Mask: %s", dhcp->SubNetworkMask.v4.ToStringLittleEndian());
|
DbgWriteScreen("SubNetwork Mask: %s", dhcp->SubNetworkMask.v4.ToStringLittleEndian());
|
||||||
DbgWriteScreen("Gateway: %s", dhcp->Gateway.v4.ToStringLittleEndian());
|
DbgWriteScreen("Gateway: %s", dhcp->Gateway.v4.ToStringLittleEndian());
|
||||||
DbgWriteScreen("DNS: %s", dhcp->DomainNameSystem.v4.ToStringLittleEndian());
|
DbgWriteScreen("DNS: %s", dhcp->DomainNameSystem.v4.ToStringLittleEndian());
|
||||||
TaskManager->Sleep(200);
|
TaskManager->Sleep(200);
|
||||||
|
|
||||||
/* TODO: This is a quick workaround we need DNS resolver asap.
|
/* TODO: This is a quick workaround we need DNS resolver asap.
|
||||||
|
|
||||||
https://tf.nist.gov/tf-cgi/servers.cgi
|
https://tf.nist.gov/tf-cgi/servers.cgi
|
||||||
https://www.ntppool.org
|
https://www.ntppool.org
|
||||||
|
|
||||||
- 0.ro.pool.ntp.org ( {86, 127, 71, 168} )
|
- 0.ro.pool.ntp.org ( {86, 127, 71, 168} )
|
||||||
- time-a-g.nist.gov ( {129, 6, 15, 28} )
|
- time-a-g.nist.gov ( {129, 6, 15, 28} )
|
||||||
*/
|
*/
|
||||||
// InternetProtocol ip = {.v4 = {.Address = {129, 6, 15, 28}},
|
// InternetProtocol ip = {.v4 = {.Address = {129, 6, 15, 28}},
|
||||||
// .v6 = {.Address = {}}};
|
// .v6 = {.Address = {}}};
|
||||||
// NetworkUDP::Socket *NTP_Socket = udp->Connect(ip, 123);
|
// NetworkUDP::Socket *NTP_Socket = udp->Connect(ip, 123);
|
||||||
// NetworkNTP::NTP *ntp = new NetworkNTP::NTP(NTP_Socket);
|
// NetworkNTP::NTP *ntp = new NetworkNTP::NTP(NTP_Socket);
|
||||||
// udp->Bind(NTP_Socket, ntp);
|
// udp->Bind(NTP_Socket, ntp);
|
||||||
// int UnixTimestamp = ntp->ReadTime();
|
// int UnixTimestamp = ntp->ReadTime();
|
||||||
// Time::Clock time = Time::ConvertFromUnix(UnixTimestamp);
|
// Time::Clock time = Time::ConvertFromUnix(UnixTimestamp);
|
||||||
// DbgWriteScreen("NTP: %d - %d.%d.%d %d:%d:%d", time.Counter,
|
// DbgWriteScreen("NTP: %d - %d.%d.%d %d:%d:%d", time.Counter,
|
||||||
// time.Day, time.Month, time.Year,
|
// time.Day, time.Month, time.Year,
|
||||||
// time.Hour, time.Minute, time.Second);
|
// time.Hour, time.Minute, time.Second);
|
||||||
TaskManager->Sleep(200);
|
TaskManager->Sleep(200);
|
||||||
|
|
||||||
/* TODO: Store everything in an vector and initialize all network cards */
|
/* TODO: Store everything in an vector and initialize all network cards */
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskManager->GetCurrentThread()->SetPriority(Tasking::TaskPriority::Idle);
|
TaskManager->GetCurrentThread()->SetPriority(Tasking::TaskPriority::Idle);
|
||||||
CPU::Halt(true);
|
CPU::Halt(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkInterface::StopNetworkStack()
|
void NetworkInterface::StopNetworkStack()
|
||||||
{
|
{
|
||||||
fixme("Stop network stack");
|
fixme("Stop network stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadFSFunction(NetRead)
|
ReadFSFunction(NetRead)
|
||||||
{
|
{
|
||||||
UNUSED(node);
|
UNUSED(node);
|
||||||
UNUSED(Offset);
|
UNUSED(Offset);
|
||||||
UNUSED(Size);
|
UNUSED(Size);
|
||||||
UNUSED(Buffer);
|
UNUSED(Buffer);
|
||||||
fixme("Not implemented.");
|
fixme("Not implemented.");
|
||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteFSFunction(NetWrite)
|
WriteFSFunction(NetWrite)
|
||||||
{
|
{
|
||||||
UNUSED(node);
|
UNUSED(node);
|
||||||
UNUSED(Offset);
|
UNUSED(Offset);
|
||||||
UNUSED(Size);
|
UNUSED(Size);
|
||||||
UNUSED(Buffer);
|
UNUSED(Buffer);
|
||||||
fixme("Not implemented.");
|
fixme("Not implemented.");
|
||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallStartNetworkStackWrapper() { NIManager->StartNetworkStack(); }
|
void CallStartNetworkStackWrapper() { NIManager->StartNetworkStack(); }
|
||||||
|
|
||||||
void NetworkInterface::StartService()
|
void NetworkInterface::StartService()
|
||||||
{
|
{
|
||||||
this->NetSvcThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)CallStartNetworkStackWrapper);
|
this->NetSvcThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)CallStartNetworkStackWrapper);
|
||||||
this->NetSvcThread->Rename("Network Service");
|
this->NetSvcThread->Rename("Network Service");
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkInterface::DrvSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
void NetworkInterface::DrvSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
||||||
{
|
{
|
||||||
foreach (auto inf in this->Interfaces)
|
foreach (auto inf in this->Interfaces)
|
||||||
if (inf->DriverID == DriverID)
|
if (inf->DriverID == DriverID)
|
||||||
NIManager->Send(inf, Data, Size);
|
NIManager->Send(inf, Data, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkInterface::DrvReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
void NetworkInterface::DrvReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
||||||
{
|
{
|
||||||
foreach (auto inf in this->Interfaces)
|
foreach (auto inf in this->Interfaces)
|
||||||
if (inf->DriverID == DriverID)
|
if (inf->DriverID == DriverID)
|
||||||
NIManager->Receive(inf, Data, Size);
|
NIManager->Receive(inf, Data, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkInterface::Send(DeviceInterface *Interface, uint8_t *Data, size_t Length)
|
void NetworkInterface::Send(DeviceInterface *Interface, uint8_t *Data, size_t Length)
|
||||||
{
|
{
|
||||||
void *DataToBeSent = mem->RequestPages(TO_PAGES(Length + 1));
|
void *DataToBeSent = mem->RequestPages(TO_PAGES(Length + 1));
|
||||||
memcpy(DataToBeSent, Data, Length);
|
memcpy(DataToBeSent, Data, Length);
|
||||||
|
|
||||||
KernelCallback cb{};
|
KernelCallback cb{};
|
||||||
cb.Reason = SendReason;
|
cb.Reason = SendReason;
|
||||||
cb.NetworkCallback.Send.Data = (uint8_t *)DataToBeSent;
|
cb.NetworkCallback.Send.Data = (uint8_t *)DataToBeSent;
|
||||||
cb.NetworkCallback.Send.Length = Length;
|
cb.NetworkCallback.Send.Length = Length;
|
||||||
DriverManager->IOCB(Interface->DriverID, &cb);
|
DriverManager->IOCB(Interface->DriverID, &cb);
|
||||||
|
|
||||||
mem->FreePages(DataToBeSent, TO_PAGES(Length + 1));
|
mem->FreePages(DataToBeSent, TO_PAGES(Length + 1));
|
||||||
foreach (auto var in RegisteredEvents)
|
foreach (auto var in RegisteredEvents)
|
||||||
var->OnInterfaceSent(Interface, Data, Length);
|
var->OnInterfaceSent(Interface, Data, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkInterface::Receive(DeviceInterface *Interface, uint8_t *Data, size_t Length)
|
void NetworkInterface::Receive(DeviceInterface *Interface, uint8_t *Data, size_t Length)
|
||||||
{
|
{
|
||||||
foreach (auto re in RegisteredEvents)
|
foreach (auto re in RegisteredEvents)
|
||||||
re->OnInterfaceReceived(Interface, Data, Length);
|
re->OnInterfaceReceived(Interface, Data, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
Events::Events(DeviceInterface *Interface)
|
Events::Events(DeviceInterface *Interface)
|
||||||
{
|
{
|
||||||
UNUSED(Interface);
|
UNUSED(Interface);
|
||||||
RegisteredEvents.push_back(this);
|
RegisteredEvents.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Events::~Events()
|
Events::~Events()
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < RegisteredEvents.size(); i++)
|
for (size_t i = 0; i < RegisteredEvents.size(); i++)
|
||||||
if (RegisteredEvents[i] == this)
|
if (RegisteredEvents[i] == this)
|
||||||
{
|
{
|
||||||
RegisteredEvents.remove(i);
|
RegisteredEvents.remove(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,327 +44,327 @@ NewLock(PlayAudioLock);
|
|||||||
|
|
||||||
namespace Recovery
|
namespace Recovery
|
||||||
{
|
{
|
||||||
WidgetCollection *wdgDbgWin = nullptr;
|
WidgetCollection *wdgDbgWin = nullptr;
|
||||||
Window *DbgWin = nullptr;
|
Window *DbgWin = nullptr;
|
||||||
|
|
||||||
char *AudioFile = (char *)"/home/default/Music/Ludwig van Beethoven - Fur Elise.mp3";
|
char *AudioFile = (char *)"/home/default/Music/Ludwig van Beethoven - Fur Elise.mp3";
|
||||||
|
|
||||||
void PlayAudio()
|
void PlayAudio()
|
||||||
{
|
{
|
||||||
TaskManager->GetCurrentThread()->Rename("PlayAudio Test");
|
TaskManager->GetCurrentThread()->Rename("PlayAudio Test");
|
||||||
SmartLock(PlayAudioLock);
|
SmartLock(PlayAudioLock);
|
||||||
Driver::DriverFile AudioDrv;
|
Driver::DriverFile AudioDrv;
|
||||||
|
|
||||||
foreach (auto Driver in DriverManager->GetDrivers())
|
foreach (auto Driver in DriverManager->GetDrivers())
|
||||||
{
|
{
|
||||||
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Audio)
|
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Audio)
|
||||||
{
|
{
|
||||||
AudioDrv = Driver;
|
AudioDrv = Driver;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AudioDrv.Enabled)
|
if (!AudioDrv.Enabled)
|
||||||
{
|
{
|
||||||
error("No audio drivers found! Cannot play audio!");
|
error("No audio drivers found! Cannot play audio!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFileSystem::File pcm = vfs->Open(AudioFile);
|
VirtualFileSystem::File pcm = vfs->Open(AudioFile);
|
||||||
|
|
||||||
if (!pcm.IsOK())
|
if (!pcm.IsOK())
|
||||||
{
|
{
|
||||||
error("Cannot open audio file! Cannot play audio!");
|
error("Cannot open audio file! Cannot play audio!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *PCMRaw = KernelAllocator.RequestPages(TO_PAGES(pcm.node->Length + 1));
|
void *PCMRaw = KernelAllocator.RequestPages(TO_PAGES(pcm.node->Length + 1));
|
||||||
memcpy(PCMRaw, (void *)pcm.node->Address, pcm.node->Length);
|
memcpy(PCMRaw, (void *)pcm.node->Address, pcm.node->Length);
|
||||||
|
|
||||||
KernelCallback callback{};
|
KernelCallback callback{};
|
||||||
callback.Reason = SendReason;
|
callback.Reason = SendReason;
|
||||||
callback.AudioCallback.Send.Data = (uint8_t *)PCMRaw;
|
callback.AudioCallback.Send.Data = (uint8_t *)PCMRaw;
|
||||||
callback.AudioCallback.Send.Length = pcm.node->Length;
|
callback.AudioCallback.Send.Length = pcm.node->Length;
|
||||||
debug("Playing audio...");
|
debug("Playing audio...");
|
||||||
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
|
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
|
||||||
UNUSED(status);
|
UNUSED(status);
|
||||||
debug("Audio played! %d", status);
|
debug("Audio played! %d", status);
|
||||||
KernelAllocator.FreePages((void *)PCMRaw, TO_PAGES(pcm.node->Length + 1));
|
KernelAllocator.FreePages((void *)PCMRaw, TO_PAGES(pcm.node->Length + 1));
|
||||||
vfs->Close(pcm);
|
vfs->Close(pcm);
|
||||||
TEXIT(0);
|
TEXIT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayAudioWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)PlayAudio)->SetPriority(Tasking::TaskPriority::Idle); }
|
void PlayAudioWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)PlayAudio)->SetPriority(Tasking::TaskPriority::Idle); }
|
||||||
|
|
||||||
void ChangeSampleRate(char SR)
|
void ChangeSampleRate(char SR)
|
||||||
{
|
{
|
||||||
Driver::DriverFile AudioDrv;
|
Driver::DriverFile AudioDrv;
|
||||||
|
|
||||||
foreach (auto Driver in DriverManager->GetDrivers())
|
foreach (auto Driver in DriverManager->GetDrivers())
|
||||||
{
|
{
|
||||||
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Audio)
|
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Audio)
|
||||||
{
|
{
|
||||||
AudioDrv = Driver;
|
AudioDrv = Driver;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AudioDrv.Enabled)
|
if (!AudioDrv.Enabled)
|
||||||
{
|
{
|
||||||
error("No audio drivers found! Cannot play audio!");
|
error("No audio drivers found! Cannot play audio!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelCallback callback{};
|
KernelCallback callback{};
|
||||||
callback.Reason = AdjustReason;
|
callback.Reason = AdjustReason;
|
||||||
callback.AudioCallback.Adjust._SampleRate = true;
|
callback.AudioCallback.Adjust._SampleRate = true;
|
||||||
callback.AudioCallback.Adjust.SampleRate = SR;
|
callback.AudioCallback.Adjust.SampleRate = SR;
|
||||||
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
|
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
|
||||||
UNUSED(status);
|
UNUSED(status);
|
||||||
debug("Sample rate changed! %d", status);
|
debug("Sample rate changed! %d", status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSR8000() { ChangeSampleRate(0); }
|
void CSR8000() { ChangeSampleRate(0); }
|
||||||
void CSR11025() { ChangeSampleRate(1); }
|
void CSR11025() { ChangeSampleRate(1); }
|
||||||
void CSR16000() { ChangeSampleRate(2); }
|
void CSR16000() { ChangeSampleRate(2); }
|
||||||
void CSR22050() { ChangeSampleRate(3); }
|
void CSR22050() { ChangeSampleRate(3); }
|
||||||
void CSR32000() { ChangeSampleRate(4); }
|
void CSR32000() { ChangeSampleRate(4); }
|
||||||
void CSR44100() { ChangeSampleRate(5); }
|
void CSR44100() { ChangeSampleRate(5); }
|
||||||
void CSR48000() { ChangeSampleRate(6); }
|
void CSR48000() { ChangeSampleRate(6); }
|
||||||
void CSR88200() { ChangeSampleRate(7); }
|
void CSR88200() { ChangeSampleRate(7); }
|
||||||
void CSR96000() { ChangeSampleRate(8); }
|
void CSR96000() { ChangeSampleRate(8); }
|
||||||
|
|
||||||
void ChangeVolume(char percentage)
|
void ChangeVolume(char percentage)
|
||||||
{
|
{
|
||||||
Driver::DriverFile AudioDrv;
|
Driver::DriverFile AudioDrv;
|
||||||
|
|
||||||
foreach (auto Driver in DriverManager->GetDrivers())
|
foreach (auto Driver in DriverManager->GetDrivers())
|
||||||
{
|
{
|
||||||
if (((FexExtended *)((uintptr_t)Driver.Address + EXTENDED_SECTION_ADDRESS))->Driver.Type == FexDriverType::FexDriverType_Audio)
|
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Audio)
|
||||||
{
|
{
|
||||||
AudioDrv = Driver;
|
AudioDrv = Driver;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AudioDrv.Enabled)
|
if (!AudioDrv.Enabled)
|
||||||
{
|
{
|
||||||
error("No audio drivers found! Cannot play audio!");
|
error("No audio drivers found! Cannot play audio!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelCallback callback{};
|
KernelCallback callback{};
|
||||||
callback.Reason = AdjustReason;
|
callback.Reason = AdjustReason;
|
||||||
callback.AudioCallback.Adjust._Volume = true;
|
callback.AudioCallback.Adjust._Volume = true;
|
||||||
callback.AudioCallback.Adjust.Volume = percentage;
|
callback.AudioCallback.Adjust.Volume = percentage;
|
||||||
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
|
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
|
||||||
UNUSED(status);
|
UNUSED(status);
|
||||||
debug("Volume changed! %d", status);
|
debug("Volume changed! %d", status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CV0() { ChangeVolume(0); }
|
void CV0() { ChangeVolume(0); }
|
||||||
void CV10() { ChangeVolume(10); }
|
void CV10() { ChangeVolume(10); }
|
||||||
void CV20() { ChangeVolume(20); }
|
void CV20() { ChangeVolume(20); }
|
||||||
void CV30() { ChangeVolume(30); }
|
void CV30() { ChangeVolume(30); }
|
||||||
void CV40() { ChangeVolume(40); }
|
void CV40() { ChangeVolume(40); }
|
||||||
void CV50() { ChangeVolume(50); }
|
void CV50() { ChangeVolume(50); }
|
||||||
void CV60() { ChangeVolume(60); }
|
void CV60() { ChangeVolume(60); }
|
||||||
void CV70() { ChangeVolume(70); }
|
void CV70() { ChangeVolume(70); }
|
||||||
void CV80() { ChangeVolume(80); }
|
void CV80() { ChangeVolume(80); }
|
||||||
void CV90() { ChangeVolume(90); }
|
void CV90() { ChangeVolume(90); }
|
||||||
void CV100() { ChangeVolume(100); }
|
void CV100() { ChangeVolume(100); }
|
||||||
|
|
||||||
void BufBight10() { Display->SetBrightness(10, 200); }
|
void BufBight10() { Display->SetBrightness(10, 200); }
|
||||||
void BufBight20() { Display->SetBrightness(20, 200); }
|
void BufBight20() { Display->SetBrightness(20, 200); }
|
||||||
void BufBight30() { Display->SetBrightness(30, 200); }
|
void BufBight30() { Display->SetBrightness(30, 200); }
|
||||||
void BufBight40() { Display->SetBrightness(40, 200); }
|
void BufBight40() { Display->SetBrightness(40, 200); }
|
||||||
void BufBight50() { Display->SetBrightness(50, 200); }
|
void BufBight50() { Display->SetBrightness(50, 200); }
|
||||||
void BufBight60() { Display->SetBrightness(60, 200); }
|
void BufBight60() { Display->SetBrightness(60, 200); }
|
||||||
void BufBight70() { Display->SetBrightness(70, 200); }
|
void BufBight70() { Display->SetBrightness(70, 200); }
|
||||||
void BufBight80() { Display->SetBrightness(80, 200); }
|
void BufBight80() { Display->SetBrightness(80, 200); }
|
||||||
void BufBight90() { Display->SetBrightness(90, 200); }
|
void BufBight90() { Display->SetBrightness(90, 200); }
|
||||||
void BufBight100() { Display->SetBrightness(100, 200); }
|
void BufBight100() { Display->SetBrightness(100, 200); }
|
||||||
|
|
||||||
// void audio_dev_connected() { AudioFile = (char *)"/system/config/audio/media/dev_connected.mp3"; }
|
// void audio_dev_connected() { AudioFile = (char *)"/system/config/audio/media/dev_connected.mp3"; }
|
||||||
// void audio_dev_disconnected() { AudioFile = (char *)"/system/config/audio/media/dev_disconnected.mp3"; }
|
// void audio_dev_disconnected() { AudioFile = (char *)"/system/config/audio/media/dev_disconnected.mp3"; }
|
||||||
// void audio_dev_error() { AudioFile = (char *)"/system/config/audio/media/dev_error.mp3"; }
|
// void audio_dev_error() { AudioFile = (char *)"/system/config/audio/media/dev_error.mp3"; }
|
||||||
// void audio_error() { AudioFile = (char *)"/system/config/audio/media/error.mp3"; }
|
// void audio_error() { AudioFile = (char *)"/system/config/audio/media/error.mp3"; }
|
||||||
// void audio_notification() { AudioFile = (char *)"/system/config/audio/media/notification.mp3"; }
|
// void audio_notification() { AudioFile = (char *)"/system/config/audio/media/notification.mp3"; }
|
||||||
// void audio_warning() { AudioFile = (char *)"/system/config/audio/media/warning.mp3"; }
|
// void audio_warning() { AudioFile = (char *)"/system/config/audio/media/warning.mp3"; }
|
||||||
|
|
||||||
void KernelRecovery::RecoveryThread()
|
void KernelRecovery::RecoveryThread()
|
||||||
{
|
{
|
||||||
while (wdgDbgWin == nullptr || DbgWin == nullptr)
|
while (wdgDbgWin == nullptr || DbgWin == nullptr)
|
||||||
TaskManager->Sleep(100);
|
TaskManager->Sleep(100);
|
||||||
|
|
||||||
wdgDbgWin->CreateLabel({5, 0, 0, 0}, "Scheduler Ticks / Last Task Ticks");
|
wdgDbgWin->CreateLabel({5, 0, 0, 0}, "Scheduler Ticks / Last Task Ticks");
|
||||||
GraphicalUserInterface::Handle SchedLblHnd = wdgDbgWin->CreateLabel({5, 15, 0, 0}, "0000000000000000 / 0000000000000000");
|
GraphicalUserInterface::Handle SchedLblHnd = wdgDbgWin->CreateLabel({5, 15, 0, 0}, "0000000000000000 / 0000000000000000");
|
||||||
|
|
||||||
wdgDbgWin->CreateLabel({5, 40, 0, 0}, "Memory Usage");
|
wdgDbgWin->CreateLabel({5, 40, 0, 0}, "Memory Usage");
|
||||||
GraphicalUserInterface::Handle MemLblHnd = wdgDbgWin->CreateLabel({5, 55, 0, 0}, "0MB / 0GB (0MB reserved) 0% (0000000000000000 bytes allocated)");
|
GraphicalUserInterface::Handle MemLblHnd = wdgDbgWin->CreateLabel({5, 55, 0, 0}, "0MB / 0GB (0MB reserved) 0% (0000000000000000 bytes allocated)");
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
wdgDbgWin->CreateLabel({5, 95, 0, 0}, "GUI Info");
|
wdgDbgWin->CreateLabel({5, 95, 0, 0}, "GUI Info");
|
||||||
wdgDbgWin->CreateLabel({5, 110, 0, 0}, " Fetch Inputs / Paint Desktop / Paint Widgets");
|
wdgDbgWin->CreateLabel({5, 110, 0, 0}, " Fetch Inputs / Paint Desktop / Paint Widgets");
|
||||||
GraphicalUserInterface::Handle GUI1LblHnd = wdgDbgWin->CreateLabel({5, 125, 0, 0}, "0000000000000000 / 0000000000000000 / 0000000000000000");
|
GraphicalUserInterface::Handle GUI1LblHnd = wdgDbgWin->CreateLabel({5, 125, 0, 0}, "0000000000000000 / 0000000000000000 / 0000000000000000");
|
||||||
wdgDbgWin->CreateLabel({5, 140, 0, 0}, " Paint Windows / Paint Cursor / Memset & Update");
|
wdgDbgWin->CreateLabel({5, 140, 0, 0}, " Paint Windows / Paint Cursor / Memset & Update");
|
||||||
GraphicalUserInterface::Handle GUI2LblHnd = wdgDbgWin->CreateLabel({5, 155, 0, 0}, "0000000000000000 / 0000000000000000 / 0000000000000000");
|
GraphicalUserInterface::Handle GUI2LblHnd = wdgDbgWin->CreateLabel({5, 155, 0, 0}, "0000000000000000 / 0000000000000000 / 0000000000000000");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
wdgDbgWin->CreateLabel({5, 195, 0, 0}, "Audio");
|
wdgDbgWin->CreateLabel({5, 195, 0, 0}, "Audio");
|
||||||
wdgDbgWin->CreateButton({5, 210, 85, 15}, "Play Audio", (uintptr_t)PlayAudioWrapper);
|
wdgDbgWin->CreateButton({5, 210, 85, 15}, "Play Audio", (uintptr_t)PlayAudioWrapper);
|
||||||
|
|
||||||
wdgDbgWin->CreateLabel({5, 235, 0, 0}, "Sample Rate");
|
wdgDbgWin->CreateLabel({5, 235, 0, 0}, "Sample Rate");
|
||||||
wdgDbgWin->CreateButton({5, 250, 45, 15}, "8000", (uintptr_t)CSR8000);
|
wdgDbgWin->CreateButton({5, 250, 45, 15}, "8000", (uintptr_t)CSR8000);
|
||||||
wdgDbgWin->CreateButton({55, 250, 45, 15}, "11025", (uintptr_t)CSR11025);
|
wdgDbgWin->CreateButton({55, 250, 45, 15}, "11025", (uintptr_t)CSR11025);
|
||||||
wdgDbgWin->CreateButton({105, 250, 45, 15}, "16000", (uintptr_t)CSR16000);
|
wdgDbgWin->CreateButton({105, 250, 45, 15}, "16000", (uintptr_t)CSR16000);
|
||||||
wdgDbgWin->CreateButton({155, 250, 45, 15}, "22050", (uintptr_t)CSR22050);
|
wdgDbgWin->CreateButton({155, 250, 45, 15}, "22050", (uintptr_t)CSR22050);
|
||||||
wdgDbgWin->CreateButton({205, 250, 45, 15}, "32000", (uintptr_t)CSR32000);
|
wdgDbgWin->CreateButton({205, 250, 45, 15}, "32000", (uintptr_t)CSR32000);
|
||||||
wdgDbgWin->CreateButton({255, 250, 45, 15}, "44100", (uintptr_t)CSR44100);
|
wdgDbgWin->CreateButton({255, 250, 45, 15}, "44100", (uintptr_t)CSR44100);
|
||||||
wdgDbgWin->CreateButton({305, 250, 45, 15}, "48000", (uintptr_t)CSR48000);
|
wdgDbgWin->CreateButton({305, 250, 45, 15}, "48000", (uintptr_t)CSR48000);
|
||||||
wdgDbgWin->CreateButton({355, 250, 45, 15}, "88200", (uintptr_t)CSR88200);
|
wdgDbgWin->CreateButton({355, 250, 45, 15}, "88200", (uintptr_t)CSR88200);
|
||||||
wdgDbgWin->CreateButton({405, 250, 45, 15}, "96000", (uintptr_t)CSR96000);
|
wdgDbgWin->CreateButton({405, 250, 45, 15}, "96000", (uintptr_t)CSR96000);
|
||||||
|
|
||||||
wdgDbgWin->CreateLabel({5, 265, 0, 0}, "Volume");
|
wdgDbgWin->CreateLabel({5, 265, 0, 0}, "Volume");
|
||||||
wdgDbgWin->CreateButton({5, 280, 25, 15}, "0%", (uintptr_t)CV0);
|
wdgDbgWin->CreateButton({5, 280, 25, 15}, "0%", (uintptr_t)CV0);
|
||||||
wdgDbgWin->CreateButton({35, 280, 25, 15}, "10%", (uintptr_t)CV10);
|
wdgDbgWin->CreateButton({35, 280, 25, 15}, "10%", (uintptr_t)CV10);
|
||||||
wdgDbgWin->CreateButton({65, 280, 25, 15}, "20%", (uintptr_t)CV20);
|
wdgDbgWin->CreateButton({65, 280, 25, 15}, "20%", (uintptr_t)CV20);
|
||||||
wdgDbgWin->CreateButton({95, 280, 25, 15}, "30%", (uintptr_t)CV30);
|
wdgDbgWin->CreateButton({95, 280, 25, 15}, "30%", (uintptr_t)CV30);
|
||||||
wdgDbgWin->CreateButton({125, 280, 25, 15}, "40%", (uintptr_t)CV40);
|
wdgDbgWin->CreateButton({125, 280, 25, 15}, "40%", (uintptr_t)CV40);
|
||||||
wdgDbgWin->CreateButton({155, 280, 25, 15}, "50%", (uintptr_t)CV50);
|
wdgDbgWin->CreateButton({155, 280, 25, 15}, "50%", (uintptr_t)CV50);
|
||||||
wdgDbgWin->CreateButton({185, 280, 25, 15}, "60%", (uintptr_t)CV60);
|
wdgDbgWin->CreateButton({185, 280, 25, 15}, "60%", (uintptr_t)CV60);
|
||||||
wdgDbgWin->CreateButton({215, 280, 25, 15}, "70%", (uintptr_t)CV70);
|
wdgDbgWin->CreateButton({215, 280, 25, 15}, "70%", (uintptr_t)CV70);
|
||||||
wdgDbgWin->CreateButton({245, 280, 25, 15}, "80%", (uintptr_t)CV80);
|
wdgDbgWin->CreateButton({245, 280, 25, 15}, "80%", (uintptr_t)CV80);
|
||||||
wdgDbgWin->CreateButton({275, 280, 25, 15}, "90%", (uintptr_t)CV90);
|
wdgDbgWin->CreateButton({275, 280, 25, 15}, "90%", (uintptr_t)CV90);
|
||||||
wdgDbgWin->CreateButton({305, 280, 25, 15}, "100%", (uintptr_t)CV100);
|
wdgDbgWin->CreateButton({305, 280, 25, 15}, "100%", (uintptr_t)CV100);
|
||||||
|
|
||||||
GraphicalUserInterface::Handle wdgDbgCurrentAudioLbl = wdgDbgWin->CreateLabel({5, 295, 0, 0}, "Current Audio: ");
|
GraphicalUserInterface::Handle wdgDbgCurrentAudioLbl = wdgDbgWin->CreateLabel({5, 295, 0, 0}, "Current Audio: ");
|
||||||
// wdgDbgWin->CreateButton({5, 310, 85, 15}, "dev_connected.mp3", (uintptr_t)audio_dev_connected);
|
// wdgDbgWin->CreateButton({5, 310, 85, 15}, "dev_connected.mp3", (uintptr_t)audio_dev_connected);
|
||||||
// wdgDbgWin->CreateButton({95, 310, 85, 15}, "dev_disconnected.mp3", (uintptr_t)audio_dev_disconnected);
|
// wdgDbgWin->CreateButton({95, 310, 85, 15}, "dev_disconnected.mp3", (uintptr_t)audio_dev_disconnected);
|
||||||
// wdgDbgWin->CreateButton({185, 310, 85, 15}, "dev_error.mp3", (uintptr_t)audio_dev_error);
|
// wdgDbgWin->CreateButton({185, 310, 85, 15}, "dev_error.mp3", (uintptr_t)audio_dev_error);
|
||||||
// wdgDbgWin->CreateButton({275, 310, 85, 15}, "error.mp3", (uintptr_t)audio_error);
|
// wdgDbgWin->CreateButton({275, 310, 85, 15}, "error.mp3", (uintptr_t)audio_error);
|
||||||
// wdgDbgWin->CreateButton({365, 310, 85, 15}, "notification.mp3", (uintptr_t)audio_notification);
|
// wdgDbgWin->CreateButton({365, 310, 85, 15}, "notification.mp3", (uintptr_t)audio_notification);
|
||||||
// wdgDbgWin->CreateButton({455, 310, 85, 15}, "warning.mp3", (uintptr_t)audio_warning);
|
// wdgDbgWin->CreateButton({455, 310, 85, 15}, "warning.mp3", (uintptr_t)audio_warning);
|
||||||
|
|
||||||
wdgDbgWin->CreateLabel({5, 325, 0, 0}, "Display Brightness");
|
wdgDbgWin->CreateLabel({5, 325, 0, 0}, "Display Brightness");
|
||||||
wdgDbgWin->CreateButton({5, 340, 25, 15}, "10%", (uintptr_t)BufBight10);
|
wdgDbgWin->CreateButton({5, 340, 25, 15}, "10%", (uintptr_t)BufBight10);
|
||||||
wdgDbgWin->CreateButton({35, 340, 25, 15}, "20%", (uintptr_t)BufBight20);
|
wdgDbgWin->CreateButton({35, 340, 25, 15}, "20%", (uintptr_t)BufBight20);
|
||||||
wdgDbgWin->CreateButton({65, 340, 25, 15}, "30%", (uintptr_t)BufBight30);
|
wdgDbgWin->CreateButton({65, 340, 25, 15}, "30%", (uintptr_t)BufBight30);
|
||||||
wdgDbgWin->CreateButton({95, 340, 25, 15}, "40%", (uintptr_t)BufBight40);
|
wdgDbgWin->CreateButton({95, 340, 25, 15}, "40%", (uintptr_t)BufBight40);
|
||||||
wdgDbgWin->CreateButton({125, 340, 25, 15}, "50%", (uintptr_t)BufBight50);
|
wdgDbgWin->CreateButton({125, 340, 25, 15}, "50%", (uintptr_t)BufBight50);
|
||||||
wdgDbgWin->CreateButton({155, 340, 25, 15}, "60%", (uintptr_t)BufBight60);
|
wdgDbgWin->CreateButton({155, 340, 25, 15}, "60%", (uintptr_t)BufBight60);
|
||||||
wdgDbgWin->CreateButton({185, 340, 25, 15}, "70%", (uintptr_t)BufBight70);
|
wdgDbgWin->CreateButton({185, 340, 25, 15}, "70%", (uintptr_t)BufBight70);
|
||||||
wdgDbgWin->CreateButton({215, 340, 25, 15}, "80%", (uintptr_t)BufBight80);
|
wdgDbgWin->CreateButton({215, 340, 25, 15}, "80%", (uintptr_t)BufBight80);
|
||||||
wdgDbgWin->CreateButton({245, 340, 25, 15}, "90%", (uintptr_t)BufBight90);
|
wdgDbgWin->CreateButton({245, 340, 25, 15}, "90%", (uintptr_t)BufBight90);
|
||||||
wdgDbgWin->CreateButton({275, 340, 25, 15}, "100%", (uintptr_t)BufBight100);
|
wdgDbgWin->CreateButton({275, 340, 25, 15}, "100%", (uintptr_t)BufBight100);
|
||||||
|
|
||||||
GraphicalUserInterface::Handle wdgDbgCurrentCPUSchedCoreLbl = wdgDbgWin->CreateLabel({5, 355, 0, 0}, "CPU Scheduled Core: Unknown");
|
GraphicalUserInterface::Handle wdgDbgCurrentCPUSchedCoreLbl = wdgDbgWin->CreateLabel({5, 355, 0, 0}, "CPU Scheduled Core: Unknown");
|
||||||
|
|
||||||
DbgWin->AddWidget(wdgDbgWin);
|
DbgWin->AddWidget(wdgDbgWin);
|
||||||
|
|
||||||
char TicksText[128];
|
char TicksText[128];
|
||||||
uint64_t MemUsed = 0;
|
uint64_t MemUsed = 0;
|
||||||
uint64_t MemTotal = 0;
|
uint64_t MemTotal = 0;
|
||||||
uint64_t MemReserved = 0;
|
uint64_t MemReserved = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
sprintf(TicksText, "%016lld / %016lld", TaskManager->GetSchedulerTicks(), TaskManager->GetLastTaskTicks());
|
sprintf(TicksText, "%016ld / %016ld", TaskManager->GetSchedulerTicks(), TaskManager->GetLastTaskTicks());
|
||||||
wdgDbgWin->SetText(SchedLblHnd, TicksText);
|
wdgDbgWin->SetText(SchedLblHnd, TicksText);
|
||||||
sprintf(TicksText, "CPU Scheduled Core: %lld", TaskManager->GetLastCore());
|
sprintf(TicksText, "CPU Scheduled Core: %d", TaskManager->GetLastCore());
|
||||||
wdgDbgWin->SetText(wdgDbgCurrentCPUSchedCoreLbl, TicksText);
|
wdgDbgWin->SetText(wdgDbgCurrentCPUSchedCoreLbl, TicksText);
|
||||||
static int RefreshMemCounter = 0;
|
static int RefreshMemCounter = 0;
|
||||||
if (RefreshMemCounter-- == 0)
|
if (RefreshMemCounter-- == 0)
|
||||||
{
|
{
|
||||||
MemUsed = KernelAllocator.GetUsedMemory();
|
MemUsed = KernelAllocator.GetUsedMemory();
|
||||||
MemTotal = KernelAllocator.GetTotalMemory();
|
MemTotal = KernelAllocator.GetTotalMemory();
|
||||||
MemReserved = KernelAllocator.GetReservedMemory();
|
MemReserved = KernelAllocator.GetReservedMemory();
|
||||||
uint64_t MemPercent = (MemUsed * 100) / MemTotal;
|
uint64_t MemPercent = (MemUsed * 100) / MemTotal;
|
||||||
sprintf(TicksText, "%lldMB / %lldGB (%lldMB reserved) %lld%% (%lld bytes allocated)", TO_MB(MemUsed), TO_GB(MemTotal), TO_MB(MemReserved), MemPercent, MemUsed);
|
sprintf(TicksText, "%ldMB / %ldGB (%ldMB reserved) %ld%% (%ld bytes allocated)", TO_MB(MemUsed), TO_GB(MemTotal), TO_MB(MemReserved), MemPercent, MemUsed);
|
||||||
wdgDbgWin->SetText(MemLblHnd, TicksText);
|
wdgDbgWin->SetText(MemLblHnd, TicksText);
|
||||||
RefreshMemCounter = 25;
|
RefreshMemCounter = 25;
|
||||||
}
|
}
|
||||||
sprintf(TicksText, "Debug - %ldx%ld", DbgWin->GetPosition().Width, DbgWin->GetPosition().Height);
|
sprintf(TicksText, "Debug - %ldx%ld", DbgWin->GetPosition().Width, DbgWin->GetPosition().Height);
|
||||||
DbgWin->SetTitle(TicksText);
|
DbgWin->SetTitle(TicksText);
|
||||||
sprintf(TicksText, "Current Audio: %s", AudioFile);
|
sprintf(TicksText, "Current Audio: %s", AudioFile);
|
||||||
wdgDbgWin->SetText(wdgDbgCurrentAudioLbl, TicksText);
|
wdgDbgWin->SetText(wdgDbgCurrentAudioLbl, TicksText);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static int RefreshGUIDbgCounter = 0;
|
static int RefreshGUIDbgCounter = 0;
|
||||||
if (RefreshGUIDbgCounter-- == 0)
|
if (RefreshGUIDbgCounter-- == 0)
|
||||||
{
|
{
|
||||||
sprintf(TicksText, "%016lld / %016lld / %016lld", FIi, PDi, PWi);
|
sprintf(TicksText, "%016ld / %016ld / %016ld", FIi, PDi, PWi);
|
||||||
wdgDbgWin->SetText(GUI1LblHnd, TicksText);
|
wdgDbgWin->SetText(GUI1LblHnd, TicksText);
|
||||||
sprintf(TicksText, "%016lld / %016lld / %016lld", PWWi, PCi, mmi);
|
sprintf(TicksText, "%016ld / %016ld / %016ld", PWWi, PCi, mmi);
|
||||||
wdgDbgWin->SetText(GUI2LblHnd, TicksText);
|
wdgDbgWin->SetText(GUI2LblHnd, TicksText);
|
||||||
RefreshGUIDbgCounter = 5;
|
RefreshGUIDbgCounter = 5;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
TaskManager->Sleep(100);
|
TaskManager->Sleep(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecoveryThreadWrapper()
|
void RecoveryThreadWrapper()
|
||||||
{
|
{
|
||||||
while (!RecoveryScreen)
|
while (!RecoveryScreen)
|
||||||
CPU::Pause();
|
CPU::Pause();
|
||||||
RecoveryScreen->RecoveryThread();
|
RecoveryScreen->RecoveryThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RebootCommandThread() { KST_Reboot(); }
|
void RebootCommandThread() { KST_Reboot(); }
|
||||||
void ShutdownCommandThread() { KST_Shutdown(); }
|
void ShutdownCommandThread() { KST_Shutdown(); }
|
||||||
|
|
||||||
void RebootCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RebootCommandThread); }
|
void RebootCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RebootCommandThread); }
|
||||||
void ShutdownCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)ShutdownCommandThread); }
|
void ShutdownCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)ShutdownCommandThread); }
|
||||||
|
|
||||||
GraphicalUserInterface::GUI *gui = nullptr;
|
GraphicalUserInterface::GUI *gui = nullptr;
|
||||||
void GUIWrapper() { gui->Loop(); }
|
void GUIWrapper() { gui->Loop(); }
|
||||||
|
|
||||||
KernelRecovery::KernelRecovery()
|
KernelRecovery::KernelRecovery()
|
||||||
{
|
{
|
||||||
// PCB *proc = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), "Recovery", TaskTrustLevel::Kernel, nullptr);
|
// PCB *proc = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), "Recovery", TaskTrustLevel::Kernel, nullptr);
|
||||||
|
|
||||||
gui = new GraphicalUserInterface::GUI;
|
gui = new GraphicalUserInterface::GUI;
|
||||||
|
|
||||||
guiThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)GUIWrapper);
|
guiThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)GUIWrapper);
|
||||||
guiThread->Rename("GUI Thread");
|
guiThread->Rename("GUI Thread");
|
||||||
guiThread->SetPriority(Tasking::TaskPriority::Critical);
|
guiThread->SetPriority(Tasking::TaskPriority::Critical);
|
||||||
|
|
||||||
Rect RecoveryModeWindow;
|
Rect RecoveryModeWindow;
|
||||||
RecoveryModeWindow.Width = 460;
|
RecoveryModeWindow.Width = 460;
|
||||||
RecoveryModeWindow.Height = 100;
|
RecoveryModeWindow.Height = 100;
|
||||||
RecoveryModeWindow.Left = Display->GetBuffer(200)->Width / 2 - RecoveryModeWindow.Width / 2;
|
RecoveryModeWindow.Left = Display->GetBuffer(200)->Width / 2 - RecoveryModeWindow.Width / 2;
|
||||||
RecoveryModeWindow.Top = Display->GetBuffer(200)->Height / 2 - RecoveryModeWindow.Height / 2;
|
RecoveryModeWindow.Top = Display->GetBuffer(200)->Height / 2 - RecoveryModeWindow.Height / 2;
|
||||||
Window *RecWin = new Window(gui, RecoveryModeWindow, "Recovery Mode");
|
Window *RecWin = new Window(gui, RecoveryModeWindow, "Recovery Mode");
|
||||||
gui->AddWindow(RecWin);
|
gui->AddWindow(RecWin);
|
||||||
|
|
||||||
WidgetCollection *wdgRecWin = new WidgetCollection(RecWin);
|
WidgetCollection *wdgRecWin = new WidgetCollection(RecWin);
|
||||||
wdgRecWin->CreateLabel({80, 10, 0, 0}, "This is not fully implemented.");
|
wdgRecWin->CreateLabel({80, 10, 0, 0}, "This is not fully implemented.");
|
||||||
wdgRecWin->CreateLabel({10, 40, 0, 0}, "All you can do is shutdown/reboot the system.");
|
wdgRecWin->CreateLabel({10, 40, 0, 0}, "All you can do is shutdown/reboot the system.");
|
||||||
wdgRecWin->CreateButton({10, 70, 90, 20}, "Reboot", (uintptr_t)RebootCommandWrapper);
|
wdgRecWin->CreateButton({10, 70, 90, 20}, "Reboot", (uintptr_t)RebootCommandWrapper);
|
||||||
wdgRecWin->CreateButton({110, 70, 90, 20}, "Shutdown", (uintptr_t)ShutdownCommandWrapper);
|
wdgRecWin->CreateButton({110, 70, 90, 20}, "Shutdown", (uintptr_t)ShutdownCommandWrapper);
|
||||||
RecWin->AddWidget(wdgRecWin);
|
RecWin->AddWidget(wdgRecWin);
|
||||||
|
|
||||||
Rect DebugWindow;
|
Rect DebugWindow;
|
||||||
DebugWindow.Width = 460;
|
DebugWindow.Width = 460;
|
||||||
DebugWindow.Height = 380;
|
DebugWindow.Height = 380;
|
||||||
DebugWindow.Left = 5;
|
DebugWindow.Left = 5;
|
||||||
DebugWindow.Top = 25;
|
DebugWindow.Top = 25;
|
||||||
DbgWin = new Window(gui, DebugWindow, "Debug");
|
DbgWin = new Window(gui, DebugWindow, "Debug");
|
||||||
gui->AddWindow(DbgWin);
|
gui->AddWindow(DbgWin);
|
||||||
|
|
||||||
wdgDbgWin = new WidgetCollection(DbgWin);
|
wdgDbgWin = new WidgetCollection(DbgWin);
|
||||||
Video::Font *NewFont = new Video::Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, Video::FontType::PCScreenFont2);
|
Video::Font *NewFont = new Video::Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, Video::FontType::PCScreenFont2);
|
||||||
wdgDbgWin->ReplaceFont(NewFont);
|
wdgDbgWin->ReplaceFont(NewFont);
|
||||||
recoveryThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RecoveryThreadWrapper);
|
recoveryThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RecoveryThreadWrapper);
|
||||||
recoveryThread->Rename("Recovery Thread");
|
recoveryThread->Rename("Recovery Thread");
|
||||||
recoveryThread->SetPriority(Tasking::TaskPriority::Idle);
|
recoveryThread->SetPriority(Tasking::TaskPriority::Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelRecovery::~KernelRecovery()
|
KernelRecovery::~KernelRecovery()
|
||||||
{
|
{
|
||||||
debug("Destructor called");
|
debug("Destructor called");
|
||||||
TaskManager->KillThread(guiThread, 0);
|
TaskManager->KillThread(guiThread, 0);
|
||||||
TaskManager->KillThread(recoveryThread, 0);
|
TaskManager->KillThread(recoveryThread, 0);
|
||||||
delete gui, gui = nullptr;
|
delete gui, gui = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -22,24 +22,24 @@
|
|||||||
|
|
||||||
enum DebugLevel
|
enum DebugLevel
|
||||||
{
|
{
|
||||||
DebugLevelNone = 0,
|
DebugLevelNone = 0,
|
||||||
DebugLevelError = 1,
|
DebugLevelError = 1,
|
||||||
DebugLevelWarning = 2,
|
DebugLevelWarning = 2,
|
||||||
DebugLevelInfo = 3,
|
DebugLevelInfo = 3,
|
||||||
DebugLevelDebug = 4,
|
DebugLevelDebug = 4,
|
||||||
DebugLevelTrace = 5,
|
DebugLevelTrace = 5,
|
||||||
DebugLevelFixme = 6,
|
DebugLevelFixme = 6,
|
||||||
DebugLevelUbsan = 7
|
DebugLevelUbsan = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
namespace SysDbg
|
namespace SysDbg
|
||||||
{
|
{
|
||||||
void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||||
void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||||
void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||||
void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define error(Format, ...) SysDbg::WriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define error(Format, ...) SysDbg::WriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
@ -103,4 +103,6 @@ void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, co
|
|||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#define stub fixme("stub")
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_DEBUGGER_H__
|
#endif // !__FENNIX_KERNEL_DEBUGGER_H__
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
#include <ints.hpp>
|
#include <ints.hpp>
|
||||||
|
#include <lock.hpp>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
#include <pci.hpp>
|
#include <pci.hpp>
|
||||||
@ -29,114 +30,207 @@
|
|||||||
|
|
||||||
namespace Driver
|
namespace Driver
|
||||||
{
|
{
|
||||||
enum DriverCode
|
enum DriverCode
|
||||||
{
|
{
|
||||||
ERROR,
|
/* This must be the same as in DAPI.hpp DriverReturnCode */
|
||||||
OK,
|
ERROR,
|
||||||
NOT_AVAILABLE,
|
OK,
|
||||||
INVALID_FEX_HEADER,
|
NOT_IMPLEMENTED,
|
||||||
INVALID_DRIVER_DATA,
|
NOT_FOUND,
|
||||||
NOT_DRIVER,
|
NOT_READY,
|
||||||
NOT_IMPLEMENTED,
|
NOT_AVAILABLE,
|
||||||
DRIVER_RETURNED_ERROR,
|
NOT_AUTHORIZED,
|
||||||
UNKNOWN_DRIVER_TYPE,
|
NOT_VALID,
|
||||||
PCI_DEVICE_NOT_FOUND,
|
NOT_ACCEPTED,
|
||||||
DRIVER_CONFLICT
|
INVALID_PCI_BAR,
|
||||||
};
|
INVALID_KERNEL_API,
|
||||||
|
INVALID_MEMORY_ALLOCATION,
|
||||||
|
INVALID_DATA,
|
||||||
|
DEVICE_NOT_SUPPORTED,
|
||||||
|
SYSTEM_NOT_SUPPORTED,
|
||||||
|
KERNEL_API_VERSION_NOT_SUPPORTED,
|
||||||
|
|
||||||
class DriverInterruptHook;
|
/* End of driver-only errors */
|
||||||
struct DriverFile
|
|
||||||
{
|
|
||||||
bool Enabled = false;
|
|
||||||
size_t DriverUID = 0;
|
|
||||||
void *Address = nullptr;
|
|
||||||
void *InterruptCallback = nullptr;
|
|
||||||
Memory::MemMgr *MemTrk = nullptr;
|
|
||||||
DriverInterruptHook *InterruptHook[16]{};
|
|
||||||
|
|
||||||
bool operator==(const DriverFile &Other) const
|
INVALID_FEX_HEADER,
|
||||||
{
|
INVALID_DRIVER_DATA,
|
||||||
return DriverUID == Other.DriverUID;
|
NOT_DRIVER,
|
||||||
}
|
DRIVER_RETURNED_ERROR,
|
||||||
};
|
UNKNOWN_DRIVER_TYPE,
|
||||||
|
UNKNOWN_DRIVER_BIND_TYPE,
|
||||||
|
PCI_DEVICE_NOT_FOUND,
|
||||||
|
DRIVER_CONFLICT
|
||||||
|
};
|
||||||
|
|
||||||
class DriverInterruptHook : public Interrupts::Handler
|
class DriverInterruptHook;
|
||||||
{
|
struct DriverFile
|
||||||
private:
|
{
|
||||||
DriverFile Handle;
|
bool Enabled = false;
|
||||||
bool Enabled = true;
|
bool BuiltIn = false;
|
||||||
|
unsigned int DriverUID = 0;
|
||||||
|
void *Address = nullptr;
|
||||||
|
void *ExtendedHeaderAddress = nullptr;
|
||||||
|
void *InterruptCallback = nullptr;
|
||||||
|
Memory::MemMgr *MemTrk = nullptr;
|
||||||
|
DriverInterruptHook *InterruptHook[16]{};
|
||||||
|
|
||||||
|
bool operator==(const DriverFile &Other) const
|
||||||
|
{
|
||||||
|
return DriverUID == Other.DriverUID;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BuiltInDriverInfo
|
||||||
|
{
|
||||||
|
int (*EntryPoint)(void *);
|
||||||
|
void *ExtendedHeader;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DriverInterruptHook : public Interrupts::Handler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
NewLock(DriverInterruptLock);
|
||||||
|
|
||||||
|
DriverFile Handle;
|
||||||
|
bool Enabled = true;
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
|
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame);
|
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Enable() { Enabled = true; }
|
void Enable() { Enabled = true; }
|
||||||
void Disable() { Enabled = false; }
|
void Disable() { Enabled = false; }
|
||||||
bool IsEnabled() { return Enabled; }
|
bool IsEnabled() { return Enabled; }
|
||||||
DriverInterruptHook(int Interrupt, DriverFile Handle);
|
DriverInterruptHook(int Interrupt, DriverFile Handle);
|
||||||
virtual ~DriverInterruptHook() = default;
|
virtual ~DriverInterruptHook() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Driver
|
class Driver
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<DriverFile> Drivers;
|
NewLock(DriverInitLock);
|
||||||
unsigned long DriverUIDs = 0;
|
|
||||||
DriverCode CallDriverEntryPoint(void *fex, void *KAPIAddress);
|
|
||||||
|
|
||||||
void MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice);
|
std::vector<DriverFile> Drivers;
|
||||||
DriverCode BindPCIGeneric(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
unsigned int DriverUIDs = 0;
|
||||||
DriverCode BindPCIDisplay(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
/* If BuiltIn is true, the "fex" is the entry point. */
|
||||||
DriverCode BindPCINetwork(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
DriverCode CallDriverEntryPoint(void *fex, bool BuiltIn = false);
|
||||||
DriverCode BindPCIStorage(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
|
||||||
DriverCode BindPCIFileSystem(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
|
||||||
DriverCode BindPCIInput(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
|
||||||
DriverCode BindPCIAudio(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice);
|
|
||||||
DriverCode DriverLoadBindPCI(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
|
|
||||||
|
|
||||||
DriverCode BindInterruptGeneric(Memory::MemMgr *mem, void *fex);
|
public:
|
||||||
DriverCode BindInterruptDisplay(Memory::MemMgr *mem, void *fex);
|
/**
|
||||||
DriverCode BindInterruptNetwork(Memory::MemMgr *mem, void *fex);
|
* @brief Load and bind a driver to a PCI device.
|
||||||
DriverCode BindInterruptStorage(Memory::MemMgr *mem, void *fex);
|
*
|
||||||
DriverCode BindInterruptFileSystem(Memory::MemMgr *mem, void *fex);
|
* This function will search for a PCI device with the given VendorID and DeviceID.
|
||||||
DriverCode BindInterruptInput(Memory::MemMgr *mem, void *fex);
|
* If the device is found, the driver will be loaded and bound to the device.
|
||||||
DriverCode BindInterruptAudio(Memory::MemMgr *mem, void *fex);
|
*
|
||||||
DriverCode DriverLoadBindInterrupt(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
|
* @param DriverAddress The address of the driver. The file will be copied to a new location.
|
||||||
|
* @param Size The size of the driver.
|
||||||
|
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
|
||||||
|
* @return DriverCode The result of the operation.
|
||||||
|
*/
|
||||||
|
DriverCode DriverLoadBindPCI(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
|
||||||
|
|
||||||
DriverCode BindInputGeneric(Memory::MemMgr *mem, void *fex);
|
/**
|
||||||
DriverCode BindInputDisplay(Memory::MemMgr *mem, void *fex);
|
* @brief Load and bind a driver to an interrupt.
|
||||||
DriverCode BindInputNetwork(Memory::MemMgr *mem, void *fex);
|
*
|
||||||
DriverCode BindInputStorage(Memory::MemMgr *mem, void *fex);
|
* This function will search for an interrupt with the given IRQ.
|
||||||
DriverCode BindInputFileSystem(Memory::MemMgr *mem, void *fex);
|
* If the interrupt is found, the driver will be loaded and bound to the interrupt.
|
||||||
DriverCode BindInputInput(Memory::MemMgr *mem, void *fex);
|
*
|
||||||
DriverCode BindInputAudio(Memory::MemMgr *mem, void *fex);
|
* @param DriverAddress The address of the driver. The file will be copied to a new location.
|
||||||
DriverCode DriverLoadBindInput(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
|
* @param Size The size of the driver.
|
||||||
|
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
|
||||||
|
* @return DriverCode The result of the operation.
|
||||||
|
*/
|
||||||
|
DriverCode DriverLoadBindInterrupt(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
|
||||||
|
|
||||||
DriverCode BindProcessGeneric(Memory::MemMgr *mem, void *fex);
|
/**
|
||||||
DriverCode BindProcessDisplay(Memory::MemMgr *mem, void *fex);
|
* @brief Load and bind a driver to an input device.
|
||||||
DriverCode BindProcessNetwork(Memory::MemMgr *mem, void *fex);
|
*
|
||||||
DriverCode BindProcessStorage(Memory::MemMgr *mem, void *fex);
|
* This function will attach the driver to the input device.
|
||||||
DriverCode BindProcessFileSystem(Memory::MemMgr *mem, void *fex);
|
*
|
||||||
DriverCode BindProcessInput(Memory::MemMgr *mem, void *fex);
|
* @param DriverAddress The address of the driver. The file will be copied to a new location.
|
||||||
DriverCode BindProcessAudio(Memory::MemMgr *mem, void *fex);
|
* @param Size The size of the driver.
|
||||||
DriverCode DriverLoadBindProcess(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf = false);
|
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
|
||||||
|
* @return DriverCode The result of the operation.
|
||||||
|
*/
|
||||||
|
DriverCode DriverLoadBindInput(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
|
||||||
|
|
||||||
public:
|
/**
|
||||||
std::vector<DriverFile> GetDrivers() { return Drivers; }
|
* @brief Load and bind a driver to a process.
|
||||||
void Panic();
|
*
|
||||||
void UnloadAllDrivers();
|
* This function will attach the driver to the process.
|
||||||
bool UnloadDriver(unsigned long DUID);
|
*
|
||||||
int IOCB(unsigned long DUID, /* KernelCallback */ void *KCB);
|
* @param DriverAddress The address of the driver. The file will be copied to a new location.
|
||||||
DriverCode LoadDriver(uintptr_t DriverAddress, size_t Size);
|
* @param Size The size of the driver.
|
||||||
DriverCode StartDrivers();
|
* @param IsBuiltIn If the driver is built-in, the @param DriverAddress will be @see BuiltInDriverInfo and the @param Size will be ignored.
|
||||||
Driver();
|
* @return DriverCode The result of the operation.
|
||||||
~Driver();
|
*/
|
||||||
};
|
DriverCode DriverLoadBindProcess(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the currently loaded drivers.
|
||||||
|
*
|
||||||
|
* This function returns a clone of the drivers vector.
|
||||||
|
* This means that the vector can be modified without affecting the drivers.
|
||||||
|
*
|
||||||
|
* @return std::vector<DriverFile> A clone of the drivers vector.
|
||||||
|
*/
|
||||||
|
std::vector<DriverFile> GetDrivers() { return Drivers; }
|
||||||
|
|
||||||
|
/* Reserved by the kernel */
|
||||||
|
void Panic();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unload all drivers.
|
||||||
|
*
|
||||||
|
* This function will unload all drivers.
|
||||||
|
*/
|
||||||
|
void UnloadAllDrivers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unload a driver.
|
||||||
|
*
|
||||||
|
* This function will unload a driver with the given driver unique ID.
|
||||||
|
* It will free the memory and remove the driver from the drivers vector.
|
||||||
|
*
|
||||||
|
* @param DUID The driver unique ID.
|
||||||
|
* @return true If the driver was found and unloaded successfully, false otherwise.
|
||||||
|
*/
|
||||||
|
bool UnloadDriver(unsigned long DUID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send a callback to a driver.
|
||||||
|
*
|
||||||
|
* This function will send a callback to a driver with the given driver unique ID.
|
||||||
|
* This is used to communicate with drivers.
|
||||||
|
*
|
||||||
|
* @param DUID The driver unique ID.
|
||||||
|
* @param KCB The @see KernelCallback structure.
|
||||||
|
* @return int The result of the operation.
|
||||||
|
*/
|
||||||
|
int IOCB(unsigned long DUID, /* KernelCallback */ void *KCB);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Load a driver.
|
||||||
|
* @param DriverAddress The address of the driver file.
|
||||||
|
* @param Size The size of the driver file.
|
||||||
|
* @return DriverCode The result of the operation.
|
||||||
|
*/
|
||||||
|
DriverCode LoadDriver(uintptr_t DriverAddress, size_t Size);
|
||||||
|
|
||||||
|
/* Reserved by the kernel */
|
||||||
|
void LoadDrivers();
|
||||||
|
|
||||||
|
/* Reserved by the kernel */
|
||||||
|
Driver();
|
||||||
|
|
||||||
|
/* Reserved by the kernel */
|
||||||
|
~Driver();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_DRIVER_H__
|
#endif // !__FENNIX_KERNEL_DRIVER_H__
|
||||||
|
668
include/gui.hpp
668
include/gui.hpp
@ -26,383 +26,383 @@
|
|||||||
|
|
||||||
namespace GraphicalUserInterface
|
namespace GraphicalUserInterface
|
||||||
{
|
{
|
||||||
typedef uintptr_t Handle;
|
typedef uintptr_t Handle;
|
||||||
|
|
||||||
struct MouseData
|
struct MouseData
|
||||||
{
|
{
|
||||||
int64_t X;
|
int64_t X;
|
||||||
int64_t Y;
|
int64_t Y;
|
||||||
int64_t Z;
|
int64_t Z;
|
||||||
bool Left;
|
bool Left;
|
||||||
bool Right;
|
bool Right;
|
||||||
bool Middle;
|
bool Middle;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScreenBitmap
|
struct ScreenBitmap
|
||||||
{
|
{
|
||||||
int64_t Width;
|
int64_t Width;
|
||||||
int64_t Height;
|
int64_t Height;
|
||||||
size_t Size;
|
size_t Size;
|
||||||
size_t Pitch;
|
size_t Pitch;
|
||||||
uint64_t BitsPerPixel;
|
uint64_t BitsPerPixel;
|
||||||
uint8_t *Data;
|
uint8_t *Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Rect
|
struct Rect
|
||||||
{
|
{
|
||||||
int64_t Left;
|
size_t Left;
|
||||||
int64_t Top;
|
size_t Top;
|
||||||
size_t Width;
|
size_t Width;
|
||||||
size_t Height;
|
size_t Height;
|
||||||
|
|
||||||
bool Contains(int64_t X, int64_t Y)
|
bool Contains(size_t X, size_t Y)
|
||||||
{
|
{
|
||||||
return (X >= Left && X <= Left + Width && Y >= Top && Y <= Top + Height);
|
return (X >= Left && X <= Left + Width && Y >= Top && Y <= Top + Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Contains(Rect rect)
|
bool Contains(Rect rect)
|
||||||
{
|
{
|
||||||
return (rect.Left >= Left && rect.Left + rect.Width <= Left + Width && rect.Top >= Top && rect.Top + rect.Height <= Top + Height);
|
return (rect.Left >= Left && rect.Left + rect.Width <= Left + Width && rect.Top >= Top && rect.Top + rect.Height <= Top + Height);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CursorType
|
enum CursorType
|
||||||
{
|
{
|
||||||
Visible = 0,
|
Visible = 0,
|
||||||
Hidden,
|
Hidden,
|
||||||
Arrow,
|
Arrow,
|
||||||
Hand,
|
Hand,
|
||||||
Wait,
|
Wait,
|
||||||
IBeam,
|
IBeam,
|
||||||
ResizeHorizontal,
|
ResizeHorizontal,
|
||||||
ResizeVertical,
|
ResizeVertical,
|
||||||
ResizeDiagonalLeft,
|
ResizeDiagonalLeft,
|
||||||
ResizeDiagonalRight,
|
ResizeDiagonalRight,
|
||||||
ResizeAll,
|
ResizeAll,
|
||||||
Cross,
|
Cross,
|
||||||
Help,
|
Help,
|
||||||
No,
|
No,
|
||||||
AppStarting,
|
AppStarting,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Event
|
struct Event
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
size_t Width;
|
size_t Width;
|
||||||
size_t Height;
|
size_t Height;
|
||||||
} Resize;
|
} Resize;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int64_t X;
|
int64_t X;
|
||||||
int64_t Y;
|
int64_t Y;
|
||||||
bool Left;
|
bool Left;
|
||||||
bool Right;
|
bool Right;
|
||||||
bool Middle;
|
bool Middle;
|
||||||
} MouseDown;
|
} MouseDown;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int64_t X;
|
int64_t X;
|
||||||
int64_t Y;
|
int64_t Y;
|
||||||
bool Left;
|
bool Left;
|
||||||
bool Right;
|
bool Right;
|
||||||
bool Middle;
|
bool Middle;
|
||||||
} MouseUp;
|
} MouseUp;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int64_t X;
|
int64_t X;
|
||||||
int64_t Y;
|
int64_t Y;
|
||||||
bool Left;
|
bool Left;
|
||||||
bool Right;
|
bool Right;
|
||||||
bool Middle;
|
bool Middle;
|
||||||
} MouseMove;
|
} MouseMove;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
virtual void OnMouseMove(Event *e) {}
|
virtual void OnMouseMove(Event *e) {}
|
||||||
virtual void OnMouseClick(Event *e) {}
|
virtual void OnMouseClick(Event *e) {}
|
||||||
virtual void OnMouseDoubleClick(Event *e) {}
|
virtual void OnMouseDoubleClick(Event *e) {}
|
||||||
virtual void OnMouseDown(Event *e) {}
|
virtual void OnMouseDown(Event *e) {}
|
||||||
virtual void OnMouseUp(Event *e) {}
|
virtual void OnMouseUp(Event *e) {}
|
||||||
virtual void OnMouseWheel(Event *e) {}
|
virtual void OnMouseWheel(Event *e) {}
|
||||||
virtual void OnMouseEnter(Event *e) {}
|
virtual void OnMouseEnter(Event *e) {}
|
||||||
virtual void OnMouseLeave(Event *e) {}
|
virtual void OnMouseLeave(Event *e) {}
|
||||||
virtual void OnMouseHover(Event *e) {}
|
virtual void OnMouseHover(Event *e) {}
|
||||||
virtual void OnMouseDrag(Event *e) {}
|
virtual void OnMouseDrag(Event *e) {}
|
||||||
virtual void OnMouseDragStart(Event *e) {}
|
virtual void OnMouseDragStart(Event *e) {}
|
||||||
virtual void OnMouseDragEnd(Event *e) {}
|
virtual void OnMouseDragEnd(Event *e) {}
|
||||||
virtual void OnMouseDragEnter(Event *e) {}
|
virtual void OnMouseDragEnter(Event *e) {}
|
||||||
virtual void OnMouseDragLeave(Event *e) {}
|
virtual void OnMouseDragLeave(Event *e) {}
|
||||||
virtual void OnMouseDragHover(Event *e) {}
|
virtual void OnMouseDragHover(Event *e) {}
|
||||||
virtual void OnMouseDragDrop(Event *e) {}
|
virtual void OnMouseDragDrop(Event *e) {}
|
||||||
virtual void OnMouseDragDropEnter(Event *e) {}
|
virtual void OnMouseDragDropEnter(Event *e) {}
|
||||||
virtual void OnMouseDragDropLeave(Event *e) {}
|
virtual void OnMouseDragDropLeave(Event *e) {}
|
||||||
virtual void OnMouseDragDropHover(Event *e) {}
|
virtual void OnMouseDragDropHover(Event *e) {}
|
||||||
virtual void OnMouseDragDropEnd(Event *e) {}
|
virtual void OnMouseDragDropEnd(Event *e) {}
|
||||||
virtual void OnMouseDragDropStart(Event *e) {}
|
virtual void OnMouseDragDropStart(Event *e) {}
|
||||||
virtual void OnMouseDragDropCancel(Event *e) {}
|
virtual void OnMouseDragDropCancel(Event *e) {}
|
||||||
virtual void OnMouseDragDropComplete(Event *e) {}
|
virtual void OnMouseDragDropComplete(Event *e) {}
|
||||||
virtual void OnMouseDragDropAbort(Event *e) {}
|
virtual void OnMouseDragDropAbort(Event *e) {}
|
||||||
|
|
||||||
virtual void OnKeyDown(Event *e) {}
|
virtual void OnKeyDown(Event *e) {}
|
||||||
virtual void OnKeyUp(Event *e) {}
|
virtual void OnKeyUp(Event *e) {}
|
||||||
virtual void OnKeyPress(Event *e) {}
|
virtual void OnKeyPress(Event *e) {}
|
||||||
|
|
||||||
virtual void OnFocusEnter(Event *e) {}
|
virtual void OnFocusEnter(Event *e) {}
|
||||||
virtual void OnFocusLeave(Event *e) {}
|
virtual void OnFocusLeave(Event *e) {}
|
||||||
virtual void OnFocusHover(Event *e) {}
|
virtual void OnFocusHover(Event *e) {}
|
||||||
|
|
||||||
virtual void OnResize(Event *e) {}
|
virtual void OnResize(Event *e) {}
|
||||||
virtual void OnMinimize(Event *e) {}
|
virtual void OnMinimize(Event *e) {}
|
||||||
virtual void OnMaximize(Event *e) {}
|
virtual void OnMaximize(Event *e) {}
|
||||||
virtual void OnMove(Event *e) {}
|
virtual void OnMove(Event *e) {}
|
||||||
virtual void OnShow(Event *e) {}
|
virtual void OnShow(Event *e) {}
|
||||||
virtual void OnHide(Event *e) {}
|
virtual void OnHide(Event *e) {}
|
||||||
virtual void OnClose(Event *e) {}
|
virtual void OnClose(Event *e) {}
|
||||||
virtual void OnDestroy(Event *e) {}
|
virtual void OnDestroy(Event *e) {}
|
||||||
|
|
||||||
virtual void OnPaint(Event *e) {}
|
virtual void OnPaint(Event *e) {}
|
||||||
virtual void OnPaintBackground(Event *e) {}
|
virtual void OnPaintBackground(Event *e) {}
|
||||||
virtual void OnPaintForeground(Event *e) {}
|
virtual void OnPaintForeground(Event *e) {}
|
||||||
virtual void OnPaintOverlay(Event *e) {}
|
virtual void OnPaintOverlay(Event *e) {}
|
||||||
virtual void OnPaintAll(Event *e) {}
|
virtual void OnPaintAll(Event *e) {}
|
||||||
virtual void OnPaintChildren(Event *e) {}
|
virtual void OnPaintChildren(Event *e) {}
|
||||||
virtual void OnPaintChildrenBackground(Event *e) {}
|
virtual void OnPaintChildrenBackground(Event *e) {}
|
||||||
virtual void OnPaintChildrenForeground(Event *e) {}
|
virtual void OnPaintChildrenForeground(Event *e) {}
|
||||||
virtual void OnPaintChildrenBorder(Event *e) {}
|
virtual void OnPaintChildrenBorder(Event *e) {}
|
||||||
virtual void OnPaintChildrenShadow(Event *e) {}
|
virtual void OnPaintChildrenShadow(Event *e) {}
|
||||||
virtual void OnPaintChildrenOverlay(Event *e) {}
|
virtual void OnPaintChildrenOverlay(Event *e) {}
|
||||||
virtual void OnPaintChildrenAll(Event *e) {}
|
virtual void OnPaintChildrenAll(Event *e) {}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void SetPixel(ScreenBitmap *Bitmap, int64_t X, int64_t Y, uint32_t Color);
|
void SetPixel(ScreenBitmap *Bitmap, int64_t X, int64_t Y, uint32_t Color);
|
||||||
void DrawOverBitmap(ScreenBitmap *DestinationBitmap,
|
void DrawOverBitmap(ScreenBitmap *DestinationBitmap,
|
||||||
ScreenBitmap *SourceBitmap,
|
ScreenBitmap *SourceBitmap,
|
||||||
int64_t Top,
|
int64_t Top,
|
||||||
int64_t Left,
|
int64_t Left,
|
||||||
bool IgnoreZero = true);
|
bool IgnoreZero = true);
|
||||||
void PutRect(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
|
void PutRect(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
|
||||||
void PutBorder(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
|
void PutBorder(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
|
||||||
uint32_t BlendColors(uint32_t c1, uint32_t c2, float t);
|
uint32_t BlendColors(uint32_t c1, uint32_t c2, float t);
|
||||||
void PutBorderWithShadow(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
|
void PutBorderWithShadow(ScreenBitmap *Bitmap, Rect rect, uint32_t Color);
|
||||||
void DrawShadow(ScreenBitmap *Bitmap, Rect rect);
|
void DrawShadow(ScreenBitmap *Bitmap, Rect rect);
|
||||||
void PaintChar(Video::Font *font, ScreenBitmap *Bitmap, char c, uint32_t Color, int64_t *CharCursorX, int64_t *CharCursorY);
|
void PaintChar(Video::Font *font, ScreenBitmap *Bitmap, char c, uint32_t Color, int64_t *CharCursorX, int64_t *CharCursorY);
|
||||||
void DrawString(ScreenBitmap *Bitmap, Rect rect, const char *Text, uint32_t Color);
|
void DrawString(ScreenBitmap *Bitmap, Rect rect, const char *Text, uint32_t Color);
|
||||||
|
|
||||||
class WidgetCollection
|
class WidgetCollection
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Memory::MemMgr *mem;
|
Memory::MemMgr *mem;
|
||||||
ScreenBitmap *Buffer;
|
ScreenBitmap *Buffer;
|
||||||
Video::Font *CurrentFont;
|
Video::Font *CurrentFont;
|
||||||
void *ParentWindow;
|
void *ParentWindow;
|
||||||
bool NeedRedraw;
|
bool NeedRedraw;
|
||||||
|
|
||||||
struct HandleMeta
|
struct HandleMeta
|
||||||
{
|
{
|
||||||
char Type[4];
|
char Type[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LabelObject
|
struct LabelObject
|
||||||
{
|
{
|
||||||
HandleMeta Handle;
|
HandleMeta Handle;
|
||||||
Rect rect;
|
Rect rect;
|
||||||
char Text[512];
|
char Text[512];
|
||||||
uint32_t Color;
|
uint32_t Color;
|
||||||
int64_t CharCursorX, CharCursorY;
|
int64_t CharCursorX, CharCursorY;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PanelObject
|
struct PanelObject
|
||||||
{
|
{
|
||||||
HandleMeta Handle;
|
HandleMeta Handle;
|
||||||
Rect rect;
|
Rect rect;
|
||||||
uint32_t Color;
|
uint32_t Color;
|
||||||
uint32_t BorderColor;
|
uint32_t BorderColor;
|
||||||
uint32_t ShadowColor;
|
uint32_t ShadowColor;
|
||||||
bool Shadow;
|
bool Shadow;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ButtonObject
|
struct ButtonObject
|
||||||
{
|
{
|
||||||
HandleMeta Handle;
|
HandleMeta Handle;
|
||||||
Rect rect;
|
Rect rect;
|
||||||
char Text[512];
|
char Text[512];
|
||||||
uint32_t Color;
|
uint32_t Color;
|
||||||
uint32_t HoverColor;
|
uint32_t HoverColor;
|
||||||
uint32_t PressedColor;
|
uint32_t PressedColor;
|
||||||
uint32_t BorderColor;
|
uint32_t BorderColor;
|
||||||
uint32_t ShadowColor;
|
uint32_t ShadowColor;
|
||||||
int64_t CharCursorX, CharCursorY;
|
int64_t CharCursorX, CharCursorY;
|
||||||
bool Shadow;
|
bool Shadow;
|
||||||
bool Hover;
|
bool Hover;
|
||||||
bool Pressed;
|
bool Pressed;
|
||||||
uintptr_t OnClick;
|
uintptr_t OnClick;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<LabelObject *> Labels;
|
std::vector<LabelObject *> Labels;
|
||||||
std::vector<PanelObject *> Panels;
|
std::vector<PanelObject *> Panels;
|
||||||
std::vector<ButtonObject *> Buttons;
|
std::vector<ButtonObject *> Buttons;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void ReplaceFont(Video::Font *NewFont)
|
void ReplaceFont(Video::Font *NewFont)
|
||||||
{
|
{
|
||||||
delete this->CurrentFont;
|
delete this->CurrentFont;
|
||||||
this->CurrentFont = NewFont;
|
this->CurrentFont = NewFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle CreatePanel(Rect rect, uint32_t Color);
|
Handle CreatePanel(Rect rect, uint32_t Color);
|
||||||
Handle CreateButton(Rect rect, const char *Text, uintptr_t OnClick = (uintptr_t) nullptr);
|
Handle CreateButton(Rect rect, const char *Text, uintptr_t OnClick = (uintptr_t) nullptr);
|
||||||
Handle CreateLabel(Rect rect, const char *Text);
|
Handle CreateLabel(Rect rect, const char *Text);
|
||||||
Handle CreateTextBox(Rect rect, const char *Text);
|
Handle CreateTextBox(Rect rect, const char *Text);
|
||||||
Handle CreateCheckBox(Rect rect, const char *Text);
|
Handle CreateCheckBox(Rect rect, const char *Text);
|
||||||
Handle CreateRadioButton(Rect rect, const char *Text);
|
Handle CreateRadioButton(Rect rect, const char *Text);
|
||||||
Handle CreateComboBox(Rect rect, const char *Text);
|
Handle CreateComboBox(Rect rect, const char *Text);
|
||||||
Handle CreateListBox(Rect rect, const char *Text);
|
Handle CreateListBox(Rect rect, const char *Text);
|
||||||
Handle CreateProgressBar(Rect rect, const char *Text);
|
Handle CreateProgressBar(Rect rect, const char *Text);
|
||||||
Handle CreateContextMenu(Rect rect, const char *Text);
|
Handle CreateContextMenu(Rect rect, const char *Text);
|
||||||
|
|
||||||
void SetText(Handle handle, const char *Text);
|
void SetText(Handle handle, const char *Text);
|
||||||
|
|
||||||
WidgetCollection(void /* Window */ *ParentWindow);
|
WidgetCollection(void /* Window */ *ParentWindow);
|
||||||
~WidgetCollection();
|
~WidgetCollection();
|
||||||
|
|
||||||
void OnMouseMove(Event *e);
|
void OnMouseMove(Event *e);
|
||||||
void OnMouseClick(Event *e);
|
void OnMouseClick(Event *e);
|
||||||
void OnMouseDoubleClick(Event *e);
|
void OnMouseDoubleClick(Event *e);
|
||||||
void OnMouseDown(Event *e);
|
void OnMouseDown(Event *e);
|
||||||
void OnMouseUp(Event *e);
|
void OnMouseUp(Event *e);
|
||||||
void OnMouseWheel(Event *e);
|
void OnMouseWheel(Event *e);
|
||||||
void OnMouseEnter(Event *e);
|
void OnMouseEnter(Event *e);
|
||||||
void OnMouseLeave(Event *e);
|
void OnMouseLeave(Event *e);
|
||||||
void OnMouseHover(Event *e);
|
void OnMouseHover(Event *e);
|
||||||
void OnMouseDrag(Event *e);
|
void OnMouseDrag(Event *e);
|
||||||
void OnMouseDragStart(Event *e);
|
void OnMouseDragStart(Event *e);
|
||||||
void OnMouseDragEnd(Event *e);
|
void OnMouseDragEnd(Event *e);
|
||||||
|
|
||||||
void OnKeyDown(Event *e);
|
void OnKeyDown(Event *e);
|
||||||
void OnKeyUp(Event *e);
|
void OnKeyUp(Event *e);
|
||||||
void OnKeyPress(Event *e);
|
void OnKeyPress(Event *e);
|
||||||
|
|
||||||
void OnShow(Event *e);
|
void OnShow(Event *e);
|
||||||
void OnHide(Event *e);
|
void OnHide(Event *e);
|
||||||
void OnDestroy(Event *e);
|
void OnDestroy(Event *e);
|
||||||
|
|
||||||
void OnPaint(Event *e);
|
void OnPaint(Event *e);
|
||||||
void OnPaintBackground(Event *e);
|
void OnPaintBackground(Event *e);
|
||||||
void OnPaintForeground(Event *e);
|
void OnPaintForeground(Event *e);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Window
|
class Window
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Memory::MemMgr *mem;
|
Memory::MemMgr *mem;
|
||||||
ScreenBitmap *Buffer;
|
ScreenBitmap *Buffer;
|
||||||
Rect Position;
|
Rect Position;
|
||||||
Rect LastPosition;
|
Rect LastPosition;
|
||||||
char Title[256];
|
char Title[256];
|
||||||
std::vector<WidgetCollection *> Widgets;
|
std::vector<WidgetCollection *> Widgets;
|
||||||
void *ParentGUI;
|
void *ParentGUI;
|
||||||
|
|
||||||
bool Maximized;
|
bool Maximized;
|
||||||
bool Minimized;
|
bool Minimized;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool IsMaximized() { return Maximized; }
|
bool IsMaximized() { return Maximized; }
|
||||||
bool IsMinimized() { return Minimized; }
|
bool IsMinimized() { return Minimized; }
|
||||||
ScreenBitmap *GetBuffer() { return Buffer; }
|
ScreenBitmap *GetBuffer() { return Buffer; }
|
||||||
Rect GetPosition() { return Position; }
|
Rect GetPosition() { return Position; }
|
||||||
Rect *GetPositionPtr() { return &Position; }
|
Rect *GetPositionPtr() { return &Position; }
|
||||||
const char *GetTitle() { return (const char *)Title; }
|
const char *GetTitle() { return (const char *)Title; }
|
||||||
void SetTitle(const char *Title) { strcpy(this->Title, Title); }
|
void SetTitle(const char *Title) { strcpy(this->Title, Title); }
|
||||||
void AddWidget(WidgetCollection *widget);
|
void AddWidget(WidgetCollection *widget);
|
||||||
|
|
||||||
Window(void *ParentGUI, Rect rect, const char *Title);
|
Window(void *ParentGUI, Rect rect, const char *Title);
|
||||||
~Window();
|
~Window();
|
||||||
|
|
||||||
void OnMouseMove(Event *e);
|
void OnMouseMove(Event *e);
|
||||||
void OnMouseClick(Event *e);
|
void OnMouseClick(Event *e);
|
||||||
void OnMouseDoubleClick(Event *e);
|
void OnMouseDoubleClick(Event *e);
|
||||||
void OnMouseDown(Event *e);
|
void OnMouseDown(Event *e);
|
||||||
void OnMouseUp(Event *e);
|
void OnMouseUp(Event *e);
|
||||||
void OnMouseWheel(Event *e);
|
void OnMouseWheel(Event *e);
|
||||||
void OnMouseEnter(Event *e);
|
void OnMouseEnter(Event *e);
|
||||||
void OnMouseLeave(Event *e);
|
void OnMouseLeave(Event *e);
|
||||||
void OnMouseHover(Event *e);
|
void OnMouseHover(Event *e);
|
||||||
void OnMouseDrag(Event *e);
|
void OnMouseDrag(Event *e);
|
||||||
void OnMouseDragStart(Event *e);
|
void OnMouseDragStart(Event *e);
|
||||||
void OnMouseDragEnd(Event *e);
|
void OnMouseDragEnd(Event *e);
|
||||||
|
|
||||||
void OnKeyDown(Event *e);
|
void OnKeyDown(Event *e);
|
||||||
void OnKeyUp(Event *e);
|
void OnKeyUp(Event *e);
|
||||||
void OnKeyPress(Event *e);
|
void OnKeyPress(Event *e);
|
||||||
|
|
||||||
void OnFocusEnter(Event *e);
|
void OnFocusEnter(Event *e);
|
||||||
void OnFocusLeave(Event *e);
|
void OnFocusLeave(Event *e);
|
||||||
void OnFocusHover(Event *e);
|
void OnFocusHover(Event *e);
|
||||||
|
|
||||||
void OnResize(Event *e);
|
void OnResize(Event *e);
|
||||||
void OnMinimize(Event *e);
|
void OnMinimize(Event *e);
|
||||||
void OnMaximize(Event *e);
|
void OnMaximize(Event *e);
|
||||||
void OnMove(Event *e);
|
void OnMove(Event *e);
|
||||||
void OnShow(Event *e);
|
void OnShow(Event *e);
|
||||||
void OnHide(Event *e);
|
void OnHide(Event *e);
|
||||||
void OnClose(Event *e);
|
void OnClose(Event *e);
|
||||||
void OnDestroy(Event *e);
|
void OnDestroy(Event *e);
|
||||||
|
|
||||||
void OnPaint(Event *e);
|
void OnPaint(Event *e);
|
||||||
void OnPaintBackground(Event *e);
|
void OnPaintBackground(Event *e);
|
||||||
void OnPaintForeground(Event *e);
|
void OnPaintForeground(Event *e);
|
||||||
void OnPaintOverlay(Event *e);
|
void OnPaintOverlay(Event *e);
|
||||||
void OnPaintAll(Event *e);
|
void OnPaintAll(Event *e);
|
||||||
void OnPaintChildren(Event *e);
|
void OnPaintChildren(Event *e);
|
||||||
void OnPaintChildrenBackground(Event *e);
|
void OnPaintChildrenBackground(Event *e);
|
||||||
void OnPaintChildrenForeground(Event *e);
|
void OnPaintChildrenForeground(Event *e);
|
||||||
void OnPaintChildrenBorder(Event *e);
|
void OnPaintChildrenBorder(Event *e);
|
||||||
void OnPaintChildrenShadow(Event *e);
|
void OnPaintChildrenShadow(Event *e);
|
||||||
void OnPaintChildrenOverlay(Event *e);
|
void OnPaintChildrenOverlay(Event *e);
|
||||||
void OnPaintChildrenAll(Event *e);
|
void OnPaintChildrenAll(Event *e);
|
||||||
};
|
};
|
||||||
|
|
||||||
class GUI
|
class GUI
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
MouseData MouseArray[256];
|
MouseData MouseArray[256];
|
||||||
Memory::MemMgr *mem;
|
Memory::MemMgr *mem;
|
||||||
Video::Font *CurrentFont;
|
Video::Font *CurrentFont;
|
||||||
Rect Desktop;
|
Rect Desktop;
|
||||||
ScreenBitmap *BackBuffer;
|
ScreenBitmap *BackBuffer;
|
||||||
ScreenBitmap *DesktopBuffer;
|
ScreenBitmap *DesktopBuffer;
|
||||||
ScreenBitmap *OverlayBuffer;
|
ScreenBitmap *OverlayBuffer;
|
||||||
ScreenBitmap *CursorBuffer;
|
ScreenBitmap *CursorBuffer;
|
||||||
std::vector<WidgetCollection *> Widgets;
|
std::vector<WidgetCollection *> Widgets;
|
||||||
std::vector<Window *> Windows;
|
std::vector<Window *> Windows;
|
||||||
CursorType Cursor = CursorType::Arrow;
|
CursorType Cursor = CursorType::Arrow;
|
||||||
CursorType LastCursor = CursorType::Arrow;
|
CursorType LastCursor = CursorType::Arrow;
|
||||||
bool CursorVisible = true;
|
bool CursorVisible = true;
|
||||||
bool IsRunning = false;
|
bool IsRunning = false;
|
||||||
|
|
||||||
bool DesktopBufferRepaint = true;
|
bool DesktopBufferRepaint = true;
|
||||||
bool OverlayBufferRepaint = true;
|
bool OverlayBufferRepaint = true;
|
||||||
bool OverlayFullRepaint = true;
|
bool OverlayFullRepaint = true;
|
||||||
bool CursorBufferRepaint = true;
|
bool CursorBufferRepaint = true;
|
||||||
|
|
||||||
void FetchInputs();
|
void FetchInputs();
|
||||||
void PaintDesktop();
|
void PaintDesktop();
|
||||||
void PaintWidgets();
|
void PaintWidgets();
|
||||||
void PaintWindows();
|
void PaintWindows();
|
||||||
void PaintCursor();
|
void PaintCursor();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void SetCursorType(CursorType Type = CursorType::Visible) { this->Cursor = Type; }
|
void SetCursorType(CursorType Type = CursorType::Visible) { this->Cursor = Type; }
|
||||||
void Loop();
|
void Loop();
|
||||||
void AddWindow(Window *window);
|
void AddWindow(Window *window);
|
||||||
void AddWidget(WidgetCollection *widget);
|
void AddWidget(WidgetCollection *widget);
|
||||||
GUI();
|
GUI();
|
||||||
~GUI();
|
~GUI();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_GUI_H__
|
#endif // !__FENNIX_KERNEL_GUI_H__
|
||||||
|
400
include/pci.hpp
400
include/pci.hpp
@ -20,221 +20,223 @@
|
|||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
|
#include <memory.hpp>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace PCI
|
namespace PCI
|
||||||
{
|
{
|
||||||
namespace Descriptors
|
namespace Descriptors
|
||||||
{
|
{
|
||||||
enum PCIVendors
|
enum PCIVendors
|
||||||
{
|
{
|
||||||
SymbiosLogic = 0x1000,
|
SymbiosLogic = 0x1000,
|
||||||
RedHat = 0x1AF4,
|
RedHat = 0x1AF4,
|
||||||
REDHat2 = 0x1B36,
|
REDHat2 = 0x1B36,
|
||||||
Realtek = 0x10EC,
|
Realtek = 0x10EC,
|
||||||
VirtualBox = 0x80EE,
|
VirtualBox = 0x80EE,
|
||||||
Ensoniq = 0x1274,
|
Ensoniq = 0x1274,
|
||||||
QEMU = 0x1234,
|
QEMU = 0x1234,
|
||||||
VMware = 0x15AD,
|
VMware = 0x15AD,
|
||||||
IntelCorporation = 0x8086,
|
IntelCorporation = 0x8086,
|
||||||
AdvancedMicroDevices = 0x1022,
|
AdvancedMicroDevices = 0x1022,
|
||||||
NVIDIACorporation = 0x10DE
|
NVIDIACorporation = 0x10DE
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *const DeviceClasses[]{
|
const char *const DeviceClasses[]{
|
||||||
"Unclassified",
|
"Unclassified",
|
||||||
"Mass Storage Controller",
|
"Mass Storage Controller",
|
||||||
"Network Controller",
|
"Network Controller",
|
||||||
"Display Controller",
|
"Display Controller",
|
||||||
"Multimedia Controller",
|
"Multimedia Controller",
|
||||||
"Memory Controller",
|
"Memory Controller",
|
||||||
"Bridge Device",
|
"Bridge Device",
|
||||||
"Simple Communication Controller",
|
"Simple Communication Controller",
|
||||||
"Base System Peripheral",
|
"Base System Peripheral",
|
||||||
"Input Device Controller",
|
"Input Device Controller",
|
||||||
"Docking Station",
|
"Docking Station",
|
||||||
"Processor",
|
"Processor",
|
||||||
"Serial Bus Controller",
|
"Serial Bus Controller",
|
||||||
"Wireless Controller",
|
"Wireless Controller",
|
||||||
"Intelligent Controller",
|
"Intelligent Controller",
|
||||||
"Satellite Communication Controller",
|
"Satellite Communication Controller",
|
||||||
"Encryption Controller",
|
"Encryption Controller",
|
||||||
"Signal Processing Controller",
|
"Signal Processing Controller",
|
||||||
"Processing Accelerator",
|
"Processing Accelerator",
|
||||||
"Non Essential Instrumentation"};
|
"Non Essential Instrumentation"};
|
||||||
|
|
||||||
const char *MassStorageControllerSubclassName(uint8_t SubclassCode);
|
const char *MassStorageControllerSubclassName(uint8_t SubclassCode);
|
||||||
const char *NetworkControllerSubclassName(uint8_t SubclassCode);
|
const char *NetworkControllerSubclassName(uint8_t SubclassCode);
|
||||||
const char *DisplayControllerSubclassName(uint8_t SubclassCode);
|
const char *DisplayControllerSubclassName(uint8_t SubclassCode);
|
||||||
const char *CommunicationControllerSubclassName(uint8_t SubclassCode);
|
const char *CommunicationControllerSubclassName(uint8_t SubclassCode);
|
||||||
const char *BaseSystemPeripheralSubclassName(uint8_t SubclassCode);
|
const char *BaseSystemPeripheralSubclassName(uint8_t SubclassCode);
|
||||||
const char *SerialBusControllerSubclassName(uint8_t SubclassCode);
|
const char *SerialBusControllerSubclassName(uint8_t SubclassCode);
|
||||||
const char *BridgeDeviceSubclassName(uint8_t SubclassCode);
|
const char *BridgeDeviceSubclassName(uint8_t SubclassCode);
|
||||||
const char *WirelessControllerSubclassName(uint8_t SubclassCode);
|
const char *WirelessControllerSubclassName(uint8_t SubclassCode);
|
||||||
const char *GetVendorName(uint32_t VendorID);
|
const char *GetVendorName(uint32_t VendorID);
|
||||||
const char *GetDeviceName(uint32_t VendorID, uint32_t DeviceID);
|
const char *GetDeviceName(uint32_t VendorID, uint32_t DeviceID);
|
||||||
const char *GetSubclassName(uint8_t ClassCode, uint8_t SubclassCode);
|
const char *GetSubclassName(uint8_t ClassCode, uint8_t SubclassCode);
|
||||||
const char *GetProgIFName(uint8_t ClassCode, uint8_t SubclassCode, uint8_t ProgIF);
|
const char *GetProgIFName(uint8_t ClassCode, uint8_t SubclassCode, uint8_t ProgIF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */
|
/* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */
|
||||||
enum PCICommands
|
enum PCICommands
|
||||||
{
|
{
|
||||||
/** @brief Enable response in I/O space */
|
/** @brief Enable response in I/O space */
|
||||||
PCI_COMMAND_IO = 0x1,
|
PCI_COMMAND_IO = 0x1,
|
||||||
/** @brief Enable response in Memory space */
|
/** @brief Enable response in Memory space */
|
||||||
PCI_COMMAND_MEMORY = 0x2,
|
PCI_COMMAND_MEMORY = 0x2,
|
||||||
/** @brief Enable bus mastering */
|
/** @brief Enable bus mastering */
|
||||||
PCI_COMMAND_MASTER = 0x4,
|
PCI_COMMAND_MASTER = 0x4,
|
||||||
/** @brief Enable response to special cycles */
|
/** @brief Enable response to special cycles */
|
||||||
PCI_COMMAND_SPECIAL = 0x8,
|
PCI_COMMAND_SPECIAL = 0x8,
|
||||||
/** @brief Use memory write and invalidate */
|
/** @brief Use memory write and invalidate */
|
||||||
PCI_COMMAND_INVALIDATE = 0x10,
|
PCI_COMMAND_INVALIDATE = 0x10,
|
||||||
/** @brief Enable palette snooping */
|
/** @brief Enable palette snooping */
|
||||||
PCI_COMMAND_VGA_PALETTE = 0x20,
|
PCI_COMMAND_VGA_PALETTE = 0x20,
|
||||||
/** @brief Enable parity checking */
|
/** @brief Enable parity checking */
|
||||||
PCI_COMMAND_PARITY = 0x40,
|
PCI_COMMAND_PARITY = 0x40,
|
||||||
/** @brief Enable address/data stepping */
|
/** @brief Enable address/data stepping */
|
||||||
PCI_COMMAND_WAIT = 0x80,
|
PCI_COMMAND_WAIT = 0x80,
|
||||||
/** @brief Enable SERR */
|
/** @brief Enable SERR */
|
||||||
PCI_COMMAND_SERR = 0x100,
|
PCI_COMMAND_SERR = 0x100,
|
||||||
/** @brief Enable back-to-back writes */
|
/** @brief Enable back-to-back writes */
|
||||||
PCI_COMMAND_FAST_BACK = 0x200,
|
PCI_COMMAND_FAST_BACK = 0x200,
|
||||||
/** @brief INTx Emulation Disable */
|
/** @brief INTx Emulation Disable */
|
||||||
PCI_COMMAND_INTX_DISABLE = 0x400
|
PCI_COMMAND_INTX_DISABLE = 0x400
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PCIDeviceHeader
|
struct PCIDeviceHeader
|
||||||
{
|
{
|
||||||
uint16_t VendorID;
|
uint16_t VendorID;
|
||||||
uint16_t DeviceID;
|
uint16_t DeviceID;
|
||||||
uint16_t Command;
|
uint16_t Command;
|
||||||
uint16_t Status;
|
uint16_t Status;
|
||||||
uint8_t RevisionID;
|
uint8_t RevisionID;
|
||||||
uint8_t ProgIF;
|
uint8_t ProgIF;
|
||||||
uint8_t Subclass;
|
uint8_t Subclass;
|
||||||
uint8_t Class;
|
uint8_t Class;
|
||||||
uint8_t CacheLineSize;
|
uint8_t CacheLineSize;
|
||||||
uint8_t LatencyTimer;
|
uint8_t LatencyTimer;
|
||||||
uint8_t HeaderType;
|
uint8_t HeaderType;
|
||||||
uint8_t BIST;
|
uint8_t BIST;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief PCI Header Type 0
|
* @brief PCI Header Type 0
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct PCIHeader0
|
struct PCIHeader0
|
||||||
{
|
{
|
||||||
PCIDeviceHeader Header;
|
PCIDeviceHeader Header;
|
||||||
uint32_t BAR0;
|
uint32_t BAR0;
|
||||||
uint32_t BAR1;
|
uint32_t BAR1;
|
||||||
uint32_t BAR2;
|
uint32_t BAR2;
|
||||||
uint32_t BAR3;
|
uint32_t BAR3;
|
||||||
uint32_t BAR4;
|
uint32_t BAR4;
|
||||||
uint32_t BAR5;
|
uint32_t BAR5;
|
||||||
uint32_t CardbusCISPointer;
|
uint32_t CardbusCISPointer;
|
||||||
uint16_t SubsystemVendorID;
|
uint16_t SubsystemVendorID;
|
||||||
uint16_t SubsystemID;
|
uint16_t SubsystemID;
|
||||||
uint32_t ExpansionROMBaseAddress;
|
uint32_t ExpansionROMBaseAddress;
|
||||||
uint8_t CapabilitiesPointer;
|
uint8_t CapabilitiesPointer;
|
||||||
uint8_t Reserved0;
|
uint8_t Reserved0;
|
||||||
uint16_t Reserved1;
|
uint16_t Reserved1;
|
||||||
uint32_t Reserved2;
|
uint32_t Reserved2;
|
||||||
uint8_t InterruptLine;
|
uint8_t InterruptLine;
|
||||||
uint8_t InterruptPin;
|
uint8_t InterruptPin;
|
||||||
uint8_t MinGrant;
|
uint8_t MinGrant;
|
||||||
uint8_t MaxLatency;
|
uint8_t MaxLatency;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief PCI Header Type 1 (PCI-to-PCI Bridge)
|
* @brief PCI Header Type 1 (PCI-to-PCI Bridge)
|
||||||
*/
|
*/
|
||||||
struct PCIHeader1
|
struct PCIHeader1
|
||||||
{
|
{
|
||||||
PCIDeviceHeader Header;
|
PCIDeviceHeader Header;
|
||||||
uint32_t BAR0;
|
uint32_t BAR0;
|
||||||
uint32_t BAR1;
|
uint32_t BAR1;
|
||||||
uint8_t PrimaryBusNumber;
|
uint8_t PrimaryBusNumber;
|
||||||
uint8_t SecondaryBusNumber;
|
uint8_t SecondaryBusNumber;
|
||||||
uint8_t SubordinateBusNumber;
|
uint8_t SubordinateBusNumber;
|
||||||
uint8_t SecondaryLatencyTimer;
|
uint8_t SecondaryLatencyTimer;
|
||||||
uint8_t IOBase;
|
uint8_t IOBase;
|
||||||
uint8_t IOLimit;
|
uint8_t IOLimit;
|
||||||
uint16_t SecondaryStatus;
|
uint16_t SecondaryStatus;
|
||||||
uint16_t MemoryBase;
|
uint16_t MemoryBase;
|
||||||
uint16_t MemoryLimit;
|
uint16_t MemoryLimit;
|
||||||
uint16_t PrefetchableMemoryBase;
|
uint16_t PrefetchableMemoryBase;
|
||||||
uint16_t PrefetchableMemoryLimit;
|
uint16_t PrefetchableMemoryLimit;
|
||||||
uint32_t PrefetchableMemoryBaseUpper32;
|
uint32_t PrefetchableMemoryBaseUpper32;
|
||||||
uint32_t PrefetchableMemoryLimitUpper32;
|
uint32_t PrefetchableMemoryLimitUpper32;
|
||||||
uint16_t IOBaseUpper16;
|
uint16_t IOBaseUpper16;
|
||||||
uint16_t IOLimitUpper16;
|
uint16_t IOLimitUpper16;
|
||||||
uint8_t CapabilitiesPointer;
|
uint8_t CapabilitiesPointer;
|
||||||
uint8_t Reserved0;
|
uint8_t Reserved0;
|
||||||
uint16_t Reserved1;
|
uint16_t Reserved1;
|
||||||
uint32_t ExpansionROMBaseAddress;
|
uint32_t ExpansionROMBaseAddress;
|
||||||
uint8_t InterruptLine;
|
uint8_t InterruptLine;
|
||||||
uint8_t InterruptPin;
|
uint8_t InterruptPin;
|
||||||
uint16_t BridgeControl;
|
uint16_t BridgeControl;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief PCI Header Type 2 (PCI-to-CardBus Bridge)
|
* @brief PCI Header Type 2 (PCI-to-CardBus Bridge)
|
||||||
*/
|
*/
|
||||||
struct PCIHeader2
|
struct PCIHeader2
|
||||||
{
|
{
|
||||||
PCIDeviceHeader Header;
|
PCIDeviceHeader Header;
|
||||||
uint32_t CardbusSocketRegistersBaseAddress;
|
uint32_t CardbusSocketRegistersBaseAddress;
|
||||||
uint8_t CapabilitiesPointer;
|
uint8_t CapabilitiesPointer;
|
||||||
uint8_t Reserved0;
|
uint8_t Reserved0;
|
||||||
uint16_t SecondaryStatus;
|
uint16_t SecondaryStatus;
|
||||||
uint8_t PCIbusNumber;
|
uint8_t PCIbusNumber;
|
||||||
uint8_t CardbusBusNumber;
|
uint8_t CardbusBusNumber;
|
||||||
uint8_t SubordinateBusNumber;
|
uint8_t SubordinateBusNumber;
|
||||||
uint8_t CardbusLatencyTimer;
|
uint8_t CardbusLatencyTimer;
|
||||||
uint32_t MemoryBase0;
|
uint32_t MemoryBase0;
|
||||||
uint32_t MemoryLimit0;
|
uint32_t MemoryLimit0;
|
||||||
uint32_t MemoryBase1;
|
uint32_t MemoryBase1;
|
||||||
uint32_t MemoryLimit1;
|
uint32_t MemoryLimit1;
|
||||||
uint32_t IOBase0;
|
uint32_t IOBase0;
|
||||||
uint32_t IOLimit0;
|
uint32_t IOLimit0;
|
||||||
uint32_t IOBase1;
|
uint32_t IOBase1;
|
||||||
uint32_t IOLimit1;
|
uint32_t IOLimit1;
|
||||||
uint8_t InterruptLine;
|
uint8_t InterruptLine;
|
||||||
uint8_t InterruptPin;
|
uint8_t InterruptPin;
|
||||||
uint16_t BridgeControl;
|
uint16_t BridgeControl;
|
||||||
uint16_t SubsystemVendorID;
|
uint16_t SubsystemVendorID;
|
||||||
uint16_t SubsystemID;
|
uint16_t SubsystemID;
|
||||||
uint32_t LegacyBaseAddress;
|
uint32_t LegacyBaseAddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DeviceConfig
|
struct DeviceConfig
|
||||||
{
|
{
|
||||||
uintptr_t BaseAddress;
|
uintptr_t BaseAddress;
|
||||||
uint16_t PCISegGroup;
|
uint16_t PCISegGroup;
|
||||||
uint8_t StartBus;
|
uint8_t StartBus;
|
||||||
uint8_t EndBus;
|
uint8_t EndBus;
|
||||||
uint32_t Reserved;
|
uint32_t Reserved;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
class PCI
|
class PCI
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<PCIDeviceHeader *> Devices;
|
std::vector<PCIDeviceHeader *> Devices;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<PCIDeviceHeader *> &GetDevices() { return Devices; }
|
std::vector<PCIDeviceHeader *> &GetDevices() { return Devices; }
|
||||||
void EnumerateFunction(uintptr_t DeviceAddress, uintptr_t Function);
|
void MapPCIAddresses(PCIDeviceHeader *PCIDevice, Memory::PageTable *Table = nullptr);
|
||||||
void EnumerateDevice(uintptr_t BusAddress, uintptr_t Device);
|
void EnumerateFunction(uintptr_t DeviceAddress, uintptr_t Function);
|
||||||
void EnumerateBus(uintptr_t BaseAddress, uintptr_t Bus);
|
void EnumerateDevice(uintptr_t BusAddress, uintptr_t Device);
|
||||||
std::vector<PCIDeviceHeader *> FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF);
|
void EnumerateBus(uintptr_t BaseAddress, uintptr_t Bus);
|
||||||
std::vector<PCIDeviceHeader *> FindPCIDevice(int VendorID, int DeviceID);
|
std::vector<PCIDeviceHeader *> FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF);
|
||||||
|
std::vector<PCIDeviceHeader *> FindPCIDevice(int VendorID, int DeviceID);
|
||||||
|
|
||||||
PCI();
|
PCI();
|
||||||
~PCI();
|
~PCI();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_PCI_H__
|
#endif // !__FENNIX_KERNEL_PCI_H__
|
||||||
|
550
include/task.hpp
550
include/task.hpp
@ -32,331 +32,331 @@
|
|||||||
|
|
||||||
namespace Tasking
|
namespace Tasking
|
||||||
{
|
{
|
||||||
typedef unsigned long IP;
|
typedef unsigned long IP;
|
||||||
typedef __UINTPTR_TYPE__ IPOffset;
|
typedef __UINTPTR_TYPE__ IPOffset;
|
||||||
typedef unsigned long UPID;
|
typedef unsigned long UPID;
|
||||||
typedef unsigned long UTID;
|
typedef unsigned long UTID;
|
||||||
typedef __UINTPTR_TYPE__ Token;
|
typedef __UINTPTR_TYPE__ Token;
|
||||||
|
|
||||||
enum TaskArchitecture
|
enum TaskArchitecture
|
||||||
{
|
{
|
||||||
UnknownArchitecture,
|
UnknownArchitecture,
|
||||||
x32,
|
x32,
|
||||||
x64,
|
x64,
|
||||||
ARM32,
|
ARM32,
|
||||||
ARM64
|
ARM64
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TaskCompatibility
|
enum TaskCompatibility
|
||||||
{
|
{
|
||||||
UnknownPlatform,
|
UnknownPlatform,
|
||||||
Native,
|
Native,
|
||||||
Linux,
|
Linux,
|
||||||
Windows
|
Windows
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TaskTrustLevel
|
enum TaskTrustLevel
|
||||||
{
|
{
|
||||||
UnknownElevation,
|
UnknownElevation,
|
||||||
Kernel,
|
Kernel,
|
||||||
System,
|
System,
|
||||||
User
|
User
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TaskStatus
|
enum TaskStatus
|
||||||
{
|
{
|
||||||
UnknownStatus,
|
UnknownStatus,
|
||||||
Ready,
|
Ready,
|
||||||
Running,
|
Running,
|
||||||
Sleeping,
|
Sleeping,
|
||||||
Waiting,
|
Waiting,
|
||||||
Stopped,
|
Stopped,
|
||||||
Terminated
|
Terminated
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TaskPriority
|
enum TaskPriority
|
||||||
{
|
{
|
||||||
UnknownPriority = 0,
|
UnknownPriority = 0,
|
||||||
Idle = 1,
|
Idle = 1,
|
||||||
Low = 2,
|
Low = 2,
|
||||||
Normal = 5,
|
Normal = 5,
|
||||||
High = 8,
|
High = 8,
|
||||||
Critical = 10
|
Critical = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TaskSecurity
|
struct TaskSecurity
|
||||||
{
|
{
|
||||||
TaskTrustLevel TrustLevel;
|
TaskTrustLevel TrustLevel;
|
||||||
Token UniqueToken;
|
Token UniqueToken;
|
||||||
bool IsCritical;
|
bool IsCritical;
|
||||||
bool IsDebugEnabled;
|
bool IsDebugEnabled;
|
||||||
bool IsKernelDebugEnabled;
|
bool IsKernelDebugEnabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TaskInfo
|
struct TaskInfo
|
||||||
{
|
{
|
||||||
uint64_t OldUserTime = 0;
|
size_t OldUserTime = 0;
|
||||||
uint64_t OldKernelTime = 0;
|
size_t OldKernelTime = 0;
|
||||||
|
|
||||||
uint64_t SleepUntil = 0;
|
size_t SleepUntil = 0;
|
||||||
uint64_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0;
|
size_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0;
|
||||||
uint64_t Year, Month, Day, Hour, Minute, Second;
|
uint64_t Year, Month, Day, Hour, Minute, Second;
|
||||||
bool Affinity[256]; // MAX_CPU
|
bool Affinity[256]; // MAX_CPU
|
||||||
TaskPriority Priority;
|
TaskPriority Priority;
|
||||||
TaskArchitecture Architecture;
|
TaskArchitecture Architecture;
|
||||||
TaskCompatibility Compatibility;
|
TaskCompatibility Compatibility;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TCB
|
struct TCB
|
||||||
{
|
{
|
||||||
UTID ID;
|
UTID ID;
|
||||||
char Name[256];
|
char Name[256];
|
||||||
struct PCB *Parent;
|
struct PCB *Parent;
|
||||||
IP EntryPoint;
|
IP EntryPoint;
|
||||||
IPOffset Offset;
|
IPOffset Offset;
|
||||||
int ExitCode;
|
int ExitCode;
|
||||||
Memory::StackGuard *Stack;
|
Memory::StackGuard *Stack;
|
||||||
Memory::MemMgr *Memory;
|
Memory::MemMgr *Memory;
|
||||||
TaskStatus Status;
|
TaskStatus Status;
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
CPU::x64::TrapFrame Registers;
|
CPU::x64::TrapFrame Registers;
|
||||||
uint64_t ShadowGSBase, GSBase, FSBase;
|
uint64_t ShadowGSBase, GSBase, FSBase;
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
CPU::x32::TrapFrame Registers; // TODO
|
CPU::x32::TrapFrame Registers; // TODO
|
||||||
uint64_t ShadowGSBase, GSBase, FSBase;
|
uint64_t ShadowGSBase, GSBase, FSBase;
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
uint64_t Registers; // TODO
|
uint64_t Registers; // TODO
|
||||||
#endif
|
#endif
|
||||||
uintptr_t IPHistory[128];
|
uintptr_t IPHistory[128];
|
||||||
TaskSecurity Security;
|
TaskSecurity Security;
|
||||||
TaskInfo Info;
|
TaskInfo Info;
|
||||||
CPU::x64::FXState *FPU;
|
CPU::x64::FXState *FPU;
|
||||||
|
|
||||||
void Rename(const char *name)
|
void Rename(const char *name)
|
||||||
{
|
{
|
||||||
CriticalSection cs;
|
CriticalSection cs;
|
||||||
if (strlen(name) > 256 || strlen(name) == 0)
|
if (strlen(name) > 256 || strlen(name) == 0)
|
||||||
{
|
{
|
||||||
debug("Invalid thread name");
|
debug("Invalid thread name");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace("Renaming thread %s to %s", Name, name);
|
trace("Renaming thread %s to %s", Name, name);
|
||||||
strncpy(Name, name, 256);
|
strncpy(Name, name, 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPriority(TaskPriority priority)
|
void SetPriority(TaskPriority priority)
|
||||||
{
|
{
|
||||||
CriticalSection cs;
|
CriticalSection cs;
|
||||||
trace("Setting priority of thread %s to %d", Name, priority);
|
trace("Setting priority of thread %s to %d", Name, priority);
|
||||||
Info.Priority = priority;
|
Info.Priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetExitCode() { return ExitCode; }
|
int GetExitCode() { return ExitCode; }
|
||||||
|
|
||||||
void SetCritical(bool Critical)
|
void SetCritical(bool Critical)
|
||||||
{
|
{
|
||||||
CriticalSection cs;
|
CriticalSection cs;
|
||||||
trace("Setting criticality of thread %s to %s", Name, Critical ? "true" : "false");
|
trace("Setting criticality of thread %s to %s", Name, Critical ? "true" : "false");
|
||||||
Security.IsCritical = Critical;
|
Security.IsCritical = Critical;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetDebugMode(bool Enable)
|
void SetDebugMode(bool Enable)
|
||||||
{
|
{
|
||||||
CriticalSection cs;
|
CriticalSection cs;
|
||||||
trace("Setting debug mode of thread %s to %s", Name, Enable ? "true" : "false");
|
trace("Setting debug mode of thread %s to %s", Name, Enable ? "true" : "false");
|
||||||
Security.IsDebugEnabled = Enable;
|
Security.IsDebugEnabled = Enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetKernelDebugMode(bool Enable)
|
void SetKernelDebugMode(bool Enable)
|
||||||
{
|
{
|
||||||
CriticalSection cs;
|
CriticalSection cs;
|
||||||
trace("Setting kernel debug mode of thread %s to %s", Name, Enable ? "true" : "false");
|
trace("Setting kernel debug mode of thread %s to %s", Name, Enable ? "true" : "false");
|
||||||
Security.IsKernelDebugEnabled = Enable;
|
Security.IsKernelDebugEnabled = Enable;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PCB
|
struct PCB
|
||||||
{
|
{
|
||||||
UPID ID;
|
UPID ID;
|
||||||
char Name[256];
|
char Name[256];
|
||||||
PCB *Parent;
|
PCB *Parent;
|
||||||
int ExitCode;
|
int ExitCode;
|
||||||
TaskStatus Status;
|
TaskStatus Status;
|
||||||
TaskSecurity Security;
|
TaskSecurity Security;
|
||||||
TaskInfo Info;
|
TaskInfo Info;
|
||||||
std::vector<TCB *> Threads;
|
std::vector<TCB *> Threads;
|
||||||
std::vector<PCB *> Children;
|
std::vector<PCB *> Children;
|
||||||
InterProcessCommunication::IPC *IPC;
|
InterProcessCommunication::IPC *IPC;
|
||||||
Memory::PageTable *PageTable;
|
Memory::PageTable *PageTable;
|
||||||
SymbolResolver::Symbols *ELFSymbolTable;
|
SymbolResolver::Symbols *ELFSymbolTable;
|
||||||
VirtualFileSystem::Node *CurrentWorkingDirectory;
|
VirtualFileSystem::Node *CurrentWorkingDirectory;
|
||||||
VirtualFileSystem::Node *ProcessDirectory;
|
VirtualFileSystem::Node *ProcessDirectory;
|
||||||
VirtualFileSystem::Node *memDirectory;
|
VirtualFileSystem::Node *memDirectory;
|
||||||
|
|
||||||
void SetWorkingDirectory(VirtualFileSystem::Node *node)
|
void SetWorkingDirectory(VirtualFileSystem::Node *node)
|
||||||
{
|
{
|
||||||
CriticalSection cs;
|
CriticalSection cs;
|
||||||
trace("Setting working directory of process %s to %#lx (%s)", Name, node, node->Name);
|
trace("Setting working directory of process %s to %#lx (%s)", Name, node, node->Name);
|
||||||
CurrentWorkingDirectory = node;
|
CurrentWorkingDirectory = node;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief Token Trust Level */
|
/** @brief Token Trust Level */
|
||||||
enum TTL
|
enum TTL
|
||||||
{
|
{
|
||||||
UnknownTrustLevel = 0b0001,
|
UnknownTrustLevel = 0b0001,
|
||||||
Untrusted = 0b0010,
|
Untrusted = 0b0010,
|
||||||
Trusted = 0b0100,
|
Trusted = 0b0100,
|
||||||
TrustedByKernel = 0b1000,
|
TrustedByKernel = 0b1000,
|
||||||
FullTrust = Trusted | TrustedByKernel
|
FullTrust = Trusted | TrustedByKernel
|
||||||
};
|
};
|
||||||
|
|
||||||
class Security
|
class Security
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct TokenData
|
struct TokenData
|
||||||
{
|
{
|
||||||
Token token;
|
Token token;
|
||||||
int TrustLevel;
|
int TrustLevel;
|
||||||
uint64_t OwnerID;
|
uint64_t OwnerID;
|
||||||
bool Process;
|
bool Process;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<TokenData> Tokens;
|
std::vector<TokenData> Tokens;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Token CreateToken();
|
Token CreateToken();
|
||||||
bool TrustToken(Token token, TTL TrustLevel);
|
bool TrustToken(Token token, TTL TrustLevel);
|
||||||
bool AddTrustLevel(Token token, TTL TrustLevel);
|
bool AddTrustLevel(Token token, TTL TrustLevel);
|
||||||
bool RemoveTrustLevel(Token token, TTL TrustLevel);
|
bool RemoveTrustLevel(Token token, TTL TrustLevel);
|
||||||
bool UntrustToken(Token token);
|
bool UntrustToken(Token token);
|
||||||
bool DestroyToken(Token token);
|
bool DestroyToken(Token token);
|
||||||
bool IsTokenTrusted(Token token, TTL TrustLevel);
|
bool IsTokenTrusted(Token token, TTL TrustLevel);
|
||||||
bool IsTokenTrusted(Token token, int TrustLevel);
|
bool IsTokenTrusted(Token token, int TrustLevel);
|
||||||
int GetTokenTrustLevel(Token token);
|
int GetTokenTrustLevel(Token token);
|
||||||
Security();
|
Security();
|
||||||
~Security();
|
~Security();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Task : public Interrupts::Handler
|
class Task : public Interrupts::Handler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Security SecurityManager;
|
Security SecurityManager;
|
||||||
UPID NextPID = 0;
|
UPID NextPID = 0;
|
||||||
UTID NextTID = 0;
|
UTID NextTID = 0;
|
||||||
|
|
||||||
std::vector<PCB *> ProcessList;
|
std::vector<PCB *> ProcessList;
|
||||||
PCB *IdleProcess = nullptr;
|
PCB *IdleProcess = nullptr;
|
||||||
TCB *IdleThread = nullptr;
|
TCB *IdleThread = nullptr;
|
||||||
TCB *CleanupThread = nullptr;
|
TCB *CleanupThread = nullptr;
|
||||||
std::atomic_uint64_t SchedulerTicks = 0;
|
std::atomic_size_t SchedulerTicks = 0;
|
||||||
std::atomic_uint64_t LastTaskTicks = 0;
|
std::atomic_size_t LastTaskTicks = 0;
|
||||||
std::atomic_int LastCore = 0;
|
std::atomic_int LastCore = 0;
|
||||||
bool StopScheduler = false;
|
bool StopScheduler = false;
|
||||||
bool InvalidPCB(PCB *pcb);
|
bool InvalidPCB(PCB *pcb);
|
||||||
bool InvalidTCB(TCB *tcb);
|
bool InvalidTCB(TCB *tcb);
|
||||||
|
|
||||||
void RemoveThread(TCB *tcb);
|
void RemoveThread(TCB *tcb);
|
||||||
void RemoveProcess(PCB *pcb);
|
void RemoveProcess(PCB *pcb);
|
||||||
|
|
||||||
void UpdateUsage(TaskInfo *Info, TaskSecurity *Security, int Core);
|
void UpdateUsage(TaskInfo *Info, TaskSecurity *Security, int Core);
|
||||||
|
|
||||||
bool FindNewProcess(void *CPUDataPointer);
|
bool FindNewProcess(void *CPUDataPointer);
|
||||||
bool GetNextAvailableThread(void *CPUDataPointer);
|
bool GetNextAvailableThread(void *CPUDataPointer);
|
||||||
bool GetNextAvailableProcess(void *CPUDataPointer);
|
bool GetNextAvailableProcess(void *CPUDataPointer);
|
||||||
bool SchedulerSearchProcessThread(void *CPUDataPointer);
|
bool SchedulerSearchProcessThread(void *CPUDataPointer);
|
||||||
void UpdateProcessStatus();
|
void UpdateProcessStatus();
|
||||||
void WakeUpThreads();
|
void WakeUpThreads();
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
void Schedule(CPU::x64::TrapFrame *Frame);
|
void Schedule(CPU::x64::TrapFrame *Frame);
|
||||||
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
void Schedule(void *Frame);
|
void Schedule(void *Frame);
|
||||||
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
|
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
void Schedule(CPU::aarch64::TrapFrame *Frame);
|
void Schedule(CPU::aarch64::TrapFrame *Frame);
|
||||||
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame);
|
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void SetCleanupThread(TCB *Thread) { CleanupThread = Thread; }
|
void SetCleanupThread(TCB *Thread) { CleanupThread = Thread; }
|
||||||
uint64_t GetSchedulerTicks() { return SchedulerTicks.load(); }
|
size_t GetSchedulerTicks() { return SchedulerTicks.load(); }
|
||||||
uint64_t GetLastTaskTicks() { return LastTaskTicks.load(); }
|
size_t GetLastTaskTicks() { return LastTaskTicks.load(); }
|
||||||
uint64_t GetLastCore() { return LastCore.load(); }
|
int GetLastCore() { return LastCore.load(); }
|
||||||
std::vector<PCB *> GetProcessList() { return ProcessList; }
|
std::vector<PCB *> GetProcessList() { return ProcessList; }
|
||||||
Security *GetSecurityManager() { return &SecurityManager; }
|
Security *GetSecurityManager() { return &SecurityManager; }
|
||||||
void CleanupProcessesThread();
|
void CleanupProcessesThread();
|
||||||
void Panic() { StopScheduler = true; }
|
void Panic() { StopScheduler = true; }
|
||||||
void Schedule();
|
void Schedule();
|
||||||
void SignalShutdown();
|
void SignalShutdown();
|
||||||
void RevertProcessCreation(PCB *Process);
|
void RevertProcessCreation(PCB *Process);
|
||||||
void RevertThreadCreation(TCB *Thread);
|
void RevertThreadCreation(TCB *Thread);
|
||||||
|
|
||||||
void KillThread(TCB *tcb, int Code)
|
void KillThread(TCB *tcb, int Code)
|
||||||
{
|
{
|
||||||
tcb->Status = TaskStatus::Terminated;
|
tcb->Status = TaskStatus::Terminated;
|
||||||
tcb->ExitCode = Code;
|
tcb->ExitCode = Code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KillProcess(PCB *pcb, int Code)
|
void KillProcess(PCB *pcb, int Code)
|
||||||
{
|
{
|
||||||
pcb->Status = TaskStatus::Terminated;
|
pcb->Status = TaskStatus::Terminated;
|
||||||
pcb->ExitCode = Code;
|
pcb->ExitCode = Code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the Current Process object
|
* @brief Get the Current Process object
|
||||||
* @return PCB*
|
* @return PCB*
|
||||||
*/
|
*/
|
||||||
PCB *GetCurrentProcess();
|
PCB *GetCurrentProcess();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the Current Thread object
|
* @brief Get the Current Thread object
|
||||||
* @return TCB*
|
* @return TCB*
|
||||||
*/
|
*/
|
||||||
TCB *GetCurrentThread();
|
TCB *GetCurrentThread();
|
||||||
|
|
||||||
PCB *GetProcessByID(UPID ID);
|
PCB *GetProcessByID(UPID ID);
|
||||||
|
|
||||||
TCB *GetThreadByID(UTID ID);
|
TCB *GetThreadByID(UTID ID);
|
||||||
|
|
||||||
/** @brief Wait for process to terminate */
|
/** @brief Wait for process to terminate */
|
||||||
void WaitForProcess(PCB *pcb);
|
void WaitForProcess(PCB *pcb);
|
||||||
|
|
||||||
/** @brief Wait for thread to terminate */
|
/** @brief Wait for thread to terminate */
|
||||||
void WaitForThread(TCB *tcb);
|
void WaitForThread(TCB *tcb);
|
||||||
|
|
||||||
void WaitForProcessStatus(PCB *pcb, TaskStatus Status);
|
void WaitForProcessStatus(PCB *pcb, TaskStatus Status);
|
||||||
void WaitForThreadStatus(TCB *tcb, TaskStatus Status);
|
void WaitForThreadStatus(TCB *tcb, TaskStatus Status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sleep for a given amount of milliseconds
|
* @brief Sleep for a given amount of milliseconds
|
||||||
*
|
*
|
||||||
* @param Milliseconds Amount of milliseconds to sleep
|
* @param Milliseconds Amount of milliseconds to sleep
|
||||||
*/
|
*/
|
||||||
void Sleep(uint64_t Milliseconds);
|
void Sleep(uint64_t Milliseconds);
|
||||||
|
|
||||||
PCB *CreateProcess(PCB *Parent,
|
PCB *CreateProcess(PCB *Parent,
|
||||||
const char *Name,
|
const char *Name,
|
||||||
TaskTrustLevel TrustLevel,
|
TaskTrustLevel TrustLevel,
|
||||||
void *Image = nullptr,
|
void *Image = nullptr,
|
||||||
bool DoNotCreatePageTable = false);
|
bool DoNotCreatePageTable = false);
|
||||||
|
|
||||||
TCB *CreateThread(PCB *Parent,
|
TCB *CreateThread(PCB *Parent,
|
||||||
IP EntryPoint,
|
IP EntryPoint,
|
||||||
const char **argv = nullptr,
|
const char **argv = nullptr,
|
||||||
const char **envp = nullptr,
|
const char **envp = nullptr,
|
||||||
const std::vector<AuxiliaryVector> &auxv = std::vector<AuxiliaryVector>(),
|
const std::vector<AuxiliaryVector> &auxv = std::vector<AuxiliaryVector>(),
|
||||||
IPOffset Offset = 0,
|
IPOffset Offset = 0,
|
||||||
TaskArchitecture Architecture = TaskArchitecture::x64,
|
TaskArchitecture Architecture = TaskArchitecture::x64,
|
||||||
TaskCompatibility Compatibility = TaskCompatibility::Native,
|
TaskCompatibility Compatibility = TaskCompatibility::Native,
|
||||||
bool ThreadNotReady = false);
|
bool ThreadNotReady = false);
|
||||||
|
|
||||||
Task(const IP EntryPoint);
|
Task(const IP EntryPoint);
|
||||||
~Task();
|
~Task();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PEXIT(Code) TaskManager->GetCurrentProcess()->ExitCode = Code
|
#define PEXIT(Code) TaskManager->GetCurrentProcess()->ExitCode = Code
|
||||||
|
316
include/time.hpp
316
include/time.hpp
@ -23,180 +23,180 @@
|
|||||||
|
|
||||||
namespace Time
|
namespace Time
|
||||||
{
|
{
|
||||||
struct Clock
|
struct Clock
|
||||||
{
|
{
|
||||||
int Year, Month, Day, Hour, Minute, Second;
|
int Year, Month, Day, Hour, Minute, Second;
|
||||||
uint64_t Counter;
|
size_t Counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
Clock ReadClock();
|
Clock ReadClock();
|
||||||
Clock ConvertFromUnix(int Timestamp);
|
Clock ConvertFromUnix(int Timestamp);
|
||||||
|
|
||||||
enum Units
|
enum Units
|
||||||
{
|
{
|
||||||
Femtoseconds,
|
Femtoseconds,
|
||||||
Picoseconds,
|
Picoseconds,
|
||||||
Nanoseconds,
|
Nanoseconds,
|
||||||
Microseconds,
|
Microseconds,
|
||||||
Milliseconds,
|
Milliseconds,
|
||||||
Seconds,
|
Seconds,
|
||||||
Minutes,
|
Minutes,
|
||||||
Hours,
|
Hours,
|
||||||
Days,
|
Days,
|
||||||
Months,
|
Months,
|
||||||
Years
|
Years
|
||||||
};
|
};
|
||||||
|
|
||||||
class HighPrecisionEventTimer
|
class HighPrecisionEventTimer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct HPET
|
struct HPET
|
||||||
{
|
{
|
||||||
uintptr_t GeneralCapabilities;
|
uintptr_t GeneralCapabilities;
|
||||||
uintptr_t Reserved0;
|
uintptr_t Reserved0;
|
||||||
uintptr_t GeneralConfiguration;
|
uintptr_t GeneralConfiguration;
|
||||||
uintptr_t Reserved1;
|
uintptr_t Reserved1;
|
||||||
uintptr_t GeneralIntStatus;
|
uintptr_t GeneralIntStatus;
|
||||||
uintptr_t Reserved2;
|
uintptr_t Reserved2;
|
||||||
uintptr_t Reserved3[24];
|
uintptr_t Reserved3[24];
|
||||||
uintptr_t MainCounterValue;
|
uintptr_t MainCounterValue;
|
||||||
uintptr_t Reserved4;
|
uintptr_t Reserved4;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t clk = 0;
|
uint32_t clk = 0;
|
||||||
HPET *hpet = nullptr;
|
HPET *hpet = nullptr;
|
||||||
uint64_t ClassCreationTime = 0;
|
size_t ClassCreationTime = 0;
|
||||||
|
|
||||||
inline uint64_t ConvertUnit(Units Unit)
|
inline size_t ConvertUnit(Units Unit)
|
||||||
{
|
{
|
||||||
switch (Unit)
|
switch (Unit)
|
||||||
{
|
{
|
||||||
case Femtoseconds:
|
case Femtoseconds:
|
||||||
return 1;
|
return 1;
|
||||||
case Picoseconds:
|
case Picoseconds:
|
||||||
return 1000;
|
return 1000;
|
||||||
case Nanoseconds:
|
case Nanoseconds:
|
||||||
return 1000000;
|
return 1000000;
|
||||||
case Microseconds:
|
case Microseconds:
|
||||||
return 1000000000;
|
return 1000000000;
|
||||||
case Milliseconds:
|
case Milliseconds:
|
||||||
return 1000000000000;
|
return 1000000000000;
|
||||||
case Seconds:
|
case Seconds:
|
||||||
return 1000000000000000;
|
return 1000000000000000;
|
||||||
case Minutes:
|
case Minutes:
|
||||||
return 1000000000000000000;
|
return 1000000000000000000;
|
||||||
// case Hours:
|
// case Hours:
|
||||||
// return 1000000000000000000000;
|
// return 1000000000000000000000;
|
||||||
// case Days:
|
// case Days:
|
||||||
// return 1000000000000000000000000;
|
// return 1000000000000000000000000;
|
||||||
// case Months:
|
// case Months:
|
||||||
// return 1000000000000000000000000000;
|
// return 1000000000000000000000000000;
|
||||||
// case Years:
|
// case Years:
|
||||||
// return 1000000000000000000000000000000;
|
// return 1000000000000000000000000000000;
|
||||||
default:
|
default:
|
||||||
error("Invalid time unit %d", Unit);
|
error("Invalid time unit %d", Unit);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Sleep(uint64_t Duration, Units Unit);
|
bool Sleep(size_t Duration, Units Unit);
|
||||||
uint64_t GetCounter();
|
size_t GetCounter();
|
||||||
uint64_t CalculateTarget(uint64_t Target, Units Unit);
|
size_t CalculateTarget(size_t Target, Units Unit);
|
||||||
uint64_t GetNanosecondsSinceClassCreation();
|
size_t GetNanosecondsSinceClassCreation();
|
||||||
|
|
||||||
HighPrecisionEventTimer(void *hpet);
|
HighPrecisionEventTimer(void *hpet);
|
||||||
~HighPrecisionEventTimer();
|
~HighPrecisionEventTimer();
|
||||||
};
|
};
|
||||||
|
|
||||||
class TimeStampCounter
|
class TimeStampCounter
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
uint64_t clk = 0;
|
size_t clk = 0;
|
||||||
uint64_t ClassCreationTime = 0;
|
size_t ClassCreationTime = 0;
|
||||||
|
|
||||||
inline uint64_t ConvertUnit(Units Unit)
|
inline size_t ConvertUnit(Units Unit)
|
||||||
{
|
{
|
||||||
switch (Unit)
|
switch (Unit)
|
||||||
{
|
{
|
||||||
case Femtoseconds:
|
case Femtoseconds:
|
||||||
return 1;
|
return 1;
|
||||||
case Picoseconds:
|
case Picoseconds:
|
||||||
return 1000;
|
return 1000;
|
||||||
case Nanoseconds:
|
case Nanoseconds:
|
||||||
return 1000000;
|
return 1000000;
|
||||||
case Microseconds:
|
case Microseconds:
|
||||||
return 1000000000;
|
return 1000000000;
|
||||||
case Milliseconds:
|
case Milliseconds:
|
||||||
return 1000000000000;
|
return 1000000000000;
|
||||||
case Seconds:
|
case Seconds:
|
||||||
return 1000000000000000;
|
return 1000000000000000;
|
||||||
case Minutes:
|
case Minutes:
|
||||||
return 1000000000000000000;
|
return 1000000000000000000;
|
||||||
// case Hours:
|
// case Hours:
|
||||||
// return 1000000000000000000000;
|
// return 1000000000000000000000;
|
||||||
// case Days:
|
// case Days:
|
||||||
// return 1000000000000000000000000;
|
// return 1000000000000000000000000;
|
||||||
// case Months:
|
// case Months:
|
||||||
// return 1000000000000000000000000000;
|
// return 1000000000000000000000000000;
|
||||||
// case Years:
|
// case Years:
|
||||||
// return 1000000000000000000000000000000;
|
// return 1000000000000000000000000000000;
|
||||||
default:
|
default:
|
||||||
error("Invalid time unit %d", Unit);
|
error("Invalid time unit %d", Unit);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Sleep(uint64_t Duration, Units Unit);
|
bool Sleep(size_t Duration, Units Unit);
|
||||||
uint64_t GetCounter();
|
size_t GetCounter();
|
||||||
uint64_t CalculateTarget(uint64_t Target, Units Unit);
|
size_t CalculateTarget(size_t Target, Units Unit);
|
||||||
uint64_t GetNanosecondsSinceClassCreation();
|
size_t GetNanosecondsSinceClassCreation();
|
||||||
|
|
||||||
TimeStampCounter();
|
TimeStampCounter();
|
||||||
~TimeStampCounter();
|
~TimeStampCounter();
|
||||||
};
|
};
|
||||||
|
|
||||||
class time
|
class time
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum TimeActiveTimer
|
enum TimeActiveTimer
|
||||||
{
|
{
|
||||||
NONE = 0b0,
|
NONE = 0b0,
|
||||||
RTC = 0b1,
|
RTC = 0b1,
|
||||||
PIT = 0b10,
|
PIT = 0b10,
|
||||||
HPET = 0b100,
|
HPET = 0b100,
|
||||||
ACPI = 0b1000,
|
ACPI = 0b1000,
|
||||||
APIC = 0b10000,
|
APIC = 0b10000,
|
||||||
TSC = 0b100000
|
TSC = 0b100000
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int SupportedTimers = 0;
|
int SupportedTimers = 0;
|
||||||
TimeActiveTimer ActiveTimer = NONE;
|
TimeActiveTimer ActiveTimer = NONE;
|
||||||
|
|
||||||
HighPrecisionEventTimer *hpet;
|
HighPrecisionEventTimer *hpet;
|
||||||
TimeStampCounter *tsc;
|
TimeStampCounter *tsc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int GetSupportedTimers() { return SupportedTimers; }
|
int GetSupportedTimers() { return SupportedTimers; }
|
||||||
TimeActiveTimer GetActiveTimer() { return ActiveTimer; }
|
TimeActiveTimer GetActiveTimer() { return ActiveTimer; }
|
||||||
bool ChangeActiveTimer(TimeActiveTimer Timer)
|
bool ChangeActiveTimer(TimeActiveTimer Timer)
|
||||||
{
|
{
|
||||||
if (!(SupportedTimers & Timer))
|
if (!(SupportedTimers & Timer))
|
||||||
return false;
|
return false;
|
||||||
ActiveTimer = Timer;
|
ActiveTimer = Timer;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sleep(uint64_t Duration, Units Unit);
|
bool Sleep(size_t Duration, Units Unit);
|
||||||
uint64_t GetCounter();
|
size_t GetCounter();
|
||||||
uint64_t CalculateTarget(uint64_t Target, Units Unit);
|
size_t CalculateTarget(size_t Target, Units Unit);
|
||||||
uint64_t GetNanosecondsSinceClassCreation();
|
size_t GetNanosecondsSinceClassCreation();
|
||||||
void FindTimers(void *acpi);
|
void FindTimers(void *acpi);
|
||||||
time();
|
time();
|
||||||
~time();
|
~time();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_TIME_H__
|
#endif // !__FENNIX_KERNEL_TIME_H__
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user