mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-25 22:14:34 +00:00
feat(kernel/driver): implement built-in driver support
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
parent
426499090e
commit
f824df9aad
@ -77,6 +77,14 @@ SECTIONS
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
||||
.builtin_drivers ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.builtin_drivers) - KERNEL_VMA)
|
||||
{
|
||||
__kernel_builtin_drivers_start = .;
|
||||
KEEP(*(SORT(.builtin_drivers.*)))
|
||||
KEEP(*(.builtin_drivers))
|
||||
__kernel_builtin_drivers_end = .;
|
||||
} :rodata
|
||||
|
||||
.init_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.init_array) - KERNEL_VMA)
|
||||
{
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
|
@ -80,6 +80,14 @@ SECTIONS
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
||||
.builtin_drivers ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.builtin_drivers) - KERNEL_VMA)
|
||||
{
|
||||
__kernel_builtin_drivers_start = .;
|
||||
KEEP(*(SORT(.builtin_drivers.*)))
|
||||
KEEP(*(.builtin_drivers))
|
||||
__kernel_builtin_drivers_end = .;
|
||||
} :rodata
|
||||
|
||||
.init_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.init_array) - KERNEL_VMA)
|
||||
{
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
|
@ -58,6 +58,14 @@ SECTIONS
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
|
||||
.builtin_drivers :
|
||||
{
|
||||
__kernel_builtin_drivers_start = .;
|
||||
KEEP(*(SORT(.builtin_drivers.*)))
|
||||
KEEP(*(.builtin_drivers))
|
||||
__kernel_builtin_drivers_end = .;
|
||||
}
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
|
@ -80,6 +80,14 @@ SECTIONS
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
||||
.builtin_drivers ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.builtin_drivers) - KERNEL_VMA)
|
||||
{
|
||||
__kernel_builtin_drivers_start = .;
|
||||
KEEP(*(SORT(.builtin_drivers.*)))
|
||||
KEEP(*(.builtin_drivers))
|
||||
__kernel_builtin_drivers_end = .;
|
||||
} :rodata
|
||||
|
||||
.init_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.init_array) - KERNEL_VMA)
|
||||
{
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
|
@ -15,6 +15,7 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define NO_API_IN_HEADER 1
|
||||
#include <driver.hpp>
|
||||
#include <interface/driver.h>
|
||||
#include <interface/fs.h>
|
||||
|
@ -37,6 +37,36 @@ namespace Driver
|
||||
void Manager::PreloadDrivers()
|
||||
{
|
||||
debug("Initializing driver manager");
|
||||
|
||||
auto &bs = __kernel_builtin_drivers_start;
|
||||
auto &be = __kernel_builtin_drivers_end;
|
||||
for (const BuiltInDriver *drv = bs; drv < be; ++drv)
|
||||
{
|
||||
debug("Loading built-in driver %s", drv->Name);
|
||||
|
||||
DriverObject drvObj = {};
|
||||
strncpy(drvObj.Name, drv->Name, sizeof(drvObj.Name));
|
||||
strncpy(drvObj.Description, drv->Description, sizeof(drvObj.Description));
|
||||
strncpy(drvObj.Author, drv->Author, sizeof(drvObj.Author));
|
||||
drvObj.Version.Major = drv->Version.Major;
|
||||
drvObj.Version.Minor = drv->Version.Minor;
|
||||
drvObj.Version.Patch = drv->Version.Patch;
|
||||
drvObj.Entry = drv->Entry;
|
||||
drvObj.Final = drv->Final;
|
||||
drvObj.Panic = drv->Panic;
|
||||
drvObj.Probe = drv->Probe;
|
||||
|
||||
drvObj.IsBuiltIn = true;
|
||||
drvObj.BaseAddress = 0;
|
||||
drvObj.EntryPoint = drv->EntryPoint;
|
||||
drvObj.vma = new Memory::VirtualMemoryArea(thisProcess->PageTable);
|
||||
drvObj.Path = "<builtin>";
|
||||
drvObj.InterruptHandlers = new std::unordered_map<uint8_t, void *>();
|
||||
drvObj.DeviceOperations = new std::unordered_map<dev_t, DriverHandlers>();
|
||||
drvObj.ID = DriverIDCounter;
|
||||
Drivers.insert({DriverIDCounter++, drvObj});
|
||||
}
|
||||
|
||||
const char *DriverDirectory = Config.DriverDirectory;
|
||||
FileNode *drvDirNode = fs->GetByPath(DriverDirectory, nullptr);
|
||||
if (!drvDirNode)
|
||||
@ -58,13 +88,15 @@ namespace Driver
|
||||
continue;
|
||||
}
|
||||
|
||||
DriverObject drvObj = {.BaseAddress = 0,
|
||||
.EntryPoint = 0,
|
||||
.vma = new Memory::VirtualMemoryArea(thisProcess->PageTable),
|
||||
.Path = drvNode->Path,
|
||||
.InterruptHandlers = new std::unordered_map<uint8_t, void *>(),
|
||||
.DeviceOperations = new std::unordered_map<dev_t, DriverHandlers>(),
|
||||
.ID = DriverIDCounter};
|
||||
DriverObject drvObj = {};
|
||||
drvObj.IsBuiltIn = false;
|
||||
drvObj.BaseAddress = 0;
|
||||
drvObj.EntryPoint = 0;
|
||||
drvObj.vma = new Memory::VirtualMemoryArea(thisProcess->PageTable);
|
||||
drvObj.Path = drvNode->Path;
|
||||
drvObj.InterruptHandlers = new std::unordered_map<uint8_t, void *>();
|
||||
drvObj.DeviceOperations = new std::unordered_map<dev_t, DriverHandlers>();
|
||||
drvObj.ID = DriverIDCounter;
|
||||
|
||||
int err = this->LoadDriverFile(drvObj, drvNode);
|
||||
debug("err = %d (%s)", err, strerror(err));
|
||||
@ -111,7 +143,7 @@ namespace Driver
|
||||
continue;
|
||||
}
|
||||
|
||||
KPrint("Loading driver %s", Drv.Name);
|
||||
KPrint("Loading driver %s (%d)", Drv.Name, Drv.ID);
|
||||
|
||||
debug("Calling Probe()=%#lx on driver %s",
|
||||
Drv.Probe, Drv.Path.c_str());
|
||||
|
@ -38,6 +38,51 @@
|
||||
#include <io.h>
|
||||
#include <list>
|
||||
|
||||
struct BuiltInDriver
|
||||
{
|
||||
char Name[32] = {'\0'};
|
||||
char Description[64] = {'\0'};
|
||||
char Author[32] = {'\0'};
|
||||
struct
|
||||
{
|
||||
int Major, Minor, Patch;
|
||||
} Version = {0, 0, 0};
|
||||
char License[32] = {'\0'};
|
||||
bool Initialized = false;
|
||||
int ErrorCode = 0;
|
||||
|
||||
int (*Entry)() = nullptr;
|
||||
int (*Final)() = nullptr;
|
||||
int (*Panic)() = nullptr;
|
||||
int (*Probe)() = nullptr;
|
||||
uintptr_t EntryPoint = 0;
|
||||
};
|
||||
|
||||
extern const BuiltInDriver __kernel_builtin_drivers_start[];
|
||||
extern const BuiltInDriver __kernel_builtin_drivers_end[];
|
||||
|
||||
#define REGISTER_BUILTIN_DRIVER(driverName, desc, auth, maj, min, patch, \
|
||||
entryFunc, finalFunc, panicFunc, initFunc) \
|
||||
int __builtin_driver_start_##driverName(dev_t id) \
|
||||
{ \
|
||||
DriverID = id; \
|
||||
return 0; \
|
||||
} \
|
||||
static const BuiltInDriver __builtin_driver_##driverName \
|
||||
__attribute__((section(".builtin_drivers"), used)) = { \
|
||||
#driverName, \
|
||||
desc, \
|
||||
auth, \
|
||||
{maj, min, patch}, \
|
||||
"", \
|
||||
false, \
|
||||
0, \
|
||||
entryFunc, \
|
||||
finalFunc, \
|
||||
panicFunc, \
|
||||
initFunc, \
|
||||
(uintptr_t)__builtin_driver_start_##driverName}
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
char GetScanCode(uint8_t ScanCode, bool Upper);
|
||||
@ -50,10 +95,10 @@ namespace Driver
|
||||
RingBuffer<InputReport> *InputReports;
|
||||
};
|
||||
|
||||
struct DriverObject
|
||||
struct DriverObject : BuiltInDriver
|
||||
{
|
||||
bool IsBuiltIn = false;
|
||||
uintptr_t BaseAddress = 0;
|
||||
uintptr_t EntryPoint = 0;
|
||||
Memory::VirtualMemoryArea *vma;
|
||||
|
||||
/* Path has the same pointer as in the Node */
|
||||
@ -61,22 +106,6 @@ namespace Driver
|
||||
std::unordered_map<uint8_t, void *> *InterruptHandlers;
|
||||
std::unordered_map<dev_t, DriverHandlers> *DeviceOperations;
|
||||
dev_t ID = 0;
|
||||
|
||||
char Name[32] = {'\0'};
|
||||
char Description[64] = {'\0'};
|
||||
char Author[32] = {'\0'};
|
||||
struct
|
||||
{
|
||||
int Major, Minor, Patch;
|
||||
} Version = {0, 0, 0};
|
||||
char License[32] = {'\0'};
|
||||
bool Initialized = false;
|
||||
int ErrorCode = 0;
|
||||
|
||||
int (*Entry)() = nullptr;
|
||||
int (*Final)() = nullptr;
|
||||
int (*Panic)() = nullptr;
|
||||
int (*Probe)() = nullptr;
|
||||
};
|
||||
|
||||
class Manager
|
||||
@ -93,7 +122,6 @@ namespace Driver
|
||||
FileNode *devNode = nullptr;
|
||||
FileNode *devInputNode = nullptr;
|
||||
|
||||
|
||||
int LoadDriverFile(DriverObject &Drv, FileNode *File);
|
||||
void ReloadDriver(dev_t driverID);
|
||||
|
||||
@ -153,7 +181,6 @@ namespace Driver
|
||||
|
||||
dev_t RegisterDevice(dev_t DriverID, DeviceType Type, const InodeOperations *Operations);
|
||||
int ReportInputEvent(dev_t DriverID, InputReport *Report);
|
||||
|
||||
int UnregisterDevice(dev_t DriverID, dev_t Device);
|
||||
|
||||
void *AllocateMemory(dev_t DriverID, size_t Pages);
|
||||
@ -168,4 +195,73 @@ namespace Driver
|
||||
|
||||
void *GetSymbolByName(const char *Name, int Version);
|
||||
|
||||
#ifndef NO_API_IN_HEADER
|
||||
namespace v0
|
||||
{
|
||||
typedef int CriticalState;
|
||||
|
||||
void KernelPrint(dev_t DriverID, const char *Format, va_list args);
|
||||
void KernelLog(dev_t DriverID, const char *Format, va_list args);
|
||||
|
||||
CriticalState EnterCriticalSection(dev_t DriverID);
|
||||
void LeaveCriticalSection(dev_t DriverID, CriticalState PreviousState);
|
||||
|
||||
int RegisterInterruptHandler(dev_t DriverID, uint8_t IRQ, void *Handler);
|
||||
int OverrideInterruptHandler(dev_t DriverID, uint8_t IRQ, void *Handler);
|
||||
int UnregisterInterruptHandler(dev_t DriverID, uint8_t IRQ, void *Handler);
|
||||
int UnregisterAllInterruptHandlers(dev_t DriverID, void *Handler);
|
||||
|
||||
dev_t RegisterFileSystem(dev_t DriverID, FileSystemInfo *Info, struct Inode *Root);
|
||||
int UnregisterFileSystem(dev_t DriverID, dev_t Device);
|
||||
|
||||
pid_t CreateKernelProcess(dev_t DriverID, const char *Name);
|
||||
pid_t CreateKernelThread(dev_t DriverID, pid_t pId, const char *Name, void *EntryPoint, void *Argument);
|
||||
pid_t GetCurrentProcess(dev_t DriverID);
|
||||
int KillProcess(dev_t DriverID, pid_t pId, int ExitCode);
|
||||
int KillThread(dev_t DriverID, pid_t tId, pid_t pId, int ExitCode);
|
||||
void Yield(dev_t DriverID);
|
||||
void Sleep(dev_t DriverID, uint64_t Milliseconds);
|
||||
|
||||
void PIC_EOI(dev_t DriverID, uint8_t IRQ);
|
||||
void IRQ_MASK(dev_t DriverID, uint8_t IRQ);
|
||||
void IRQ_UNMASK(dev_t DriverID, uint8_t IRQ);
|
||||
|
||||
void PS2Wait(dev_t DriverID, const bool Output);
|
||||
void PS2WriteCommand(dev_t DriverID, uint8_t Command);
|
||||
void PS2WriteData(dev_t DriverID, uint8_t Data);
|
||||
uint8_t PS2ReadData(dev_t DriverID);
|
||||
uint8_t PS2ReadStatus(dev_t DriverID);
|
||||
uint8_t PS2ReadAfterACK(dev_t DriverID);
|
||||
void PS2ClearOutputBuffer(dev_t DriverID);
|
||||
int PS2ACKTimeout(dev_t DriverID);
|
||||
|
||||
void *AllocateMemory(dev_t DriverID, size_t Pages);
|
||||
void FreeMemory(dev_t DriverID, void *Pointer, size_t Pages);
|
||||
void *MemoryCopy(dev_t DriverID, void *Destination, const void *Source, size_t Length);
|
||||
void *MemorySet(dev_t DriverID, void *Destination, int Value, size_t Length);
|
||||
void *MemoryMove(dev_t DriverID, void *Destination, const void *Source, size_t Length);
|
||||
size_t StringLength(dev_t DriverID, const char String[]);
|
||||
char *_strstr(dev_t DriverID, const char *Haystack, const char *Needle);
|
||||
|
||||
void MapPages(dev_t MajorID, void *PhysicalAddress, void *VirtualAddress, size_t Pages, uint32_t Flags);
|
||||
void UnmapPages(dev_t MajorID, void *VirtualAddress, size_t Pages);
|
||||
void AppendMapFlag(dev_t MajorID, void *Address, PageMapFlags Flag);
|
||||
void RemoveMapFlag(dev_t MajorID, void *Address, PageMapFlags Flag);
|
||||
|
||||
void *Znwm(size_t Size);
|
||||
void ZdlPvm(void *Pointer, size_t Size);
|
||||
|
||||
__PCIArray *GetPCIDevices(dev_t DriverID, uint16_t _Vendors[], uint16_t _Devices[]);
|
||||
void InitializePCI(dev_t DriverID, void *_Header);
|
||||
uint32_t GetBAR(dev_t DriverID, uint8_t i, void *_Header);
|
||||
uint8_t iLine(dev_t DriverID, PCI::PCIDevice *Device);
|
||||
uint8_t iPin(dev_t DriverID, PCI::PCIDevice *Device);
|
||||
|
||||
dev_t CreateDeviceFile(dev_t DriverID, const char *name, mode_t mode, const InodeOperations *Operations);
|
||||
dev_t RegisterDevice(dev_t DriverID, DeviceType Type, const InodeOperations *Operations);
|
||||
int UnregisterDevice(dev_t DriverID, dev_t Device);
|
||||
int ReportInputEvent(dev_t DriverID, InputReport *Report);
|
||||
}
|
||||
#endif // !NO_API_IN_HEADER
|
||||
|
||||
#endif // !__FENNIX_KERNEL_DRIVER_H__
|
||||
|
@ -103,6 +103,7 @@ typedef union
|
||||
uint8_t Raw;
|
||||
} PS2_OUTPUT_PORT;
|
||||
|
||||
#ifndef __kernel__
|
||||
void PIC_EOI(uint8_t IRQ);
|
||||
void IRQ_MASK(uint8_t IRQ);
|
||||
void IRQ_UNMASK(uint8_t IRQ);
|
||||
@ -114,11 +115,11 @@ uint8_t PS2ReadStatus();
|
||||
uint8_t PS2ReadAfterACK();
|
||||
void PS2ClearOutputBuffer();
|
||||
int PS2ACKTimeout();
|
||||
#endif // !__kernel__
|
||||
|
||||
#define WaitOutput PS2Wait(DriverID, true)
|
||||
#define WaitInput PS2Wait(DriverID, false)
|
||||
|
||||
|
||||
#define PS2_KBD_CMD_SET_LEDS 0xED
|
||||
#define PS2_KBD_CMD_ECHO 0xEE
|
||||
#define PS2_KBD_CMD_SCAN_CODE_SET 0xF0
|
||||
@ -189,7 +190,6 @@ typedef union
|
||||
uint8_t Raw;
|
||||
} PS2_KBD_TYPEMATIC;
|
||||
|
||||
|
||||
#define PS2_MOUSE_CMD_SET_SCALING_1_1 0xE6
|
||||
#define PS2_MOUSE_CMD_SET_SCALING_2_1 0xE7
|
||||
#define PS2_MOUSE_CMD_SET_RESOLUTION 0xE8
|
||||
|
@ -69,7 +69,10 @@ typedef enum
|
||||
BLOCK_TYPE_FLOPPY = DEVICE_TYPE_BLOCK + 128,
|
||||
} DeviceType;
|
||||
|
||||
#ifndef __kernel__
|
||||
EXTERNC dev_t CreateDeviceFile(const char *name, mode_t mode, const struct InodeOperations *Operations);
|
||||
EXTERNC dev_t RegisterDevice(DeviceType Type, const struct InodeOperations *Operations);
|
||||
EXTERNC int UnregisterDevice(dev_t Device);
|
||||
#endif // !__kernel__
|
||||
|
||||
#endif // !__FENNIX_API_DEVICE_H__
|
||||
|
@ -377,7 +377,9 @@ struct FileSystemInfo
|
||||
void *PrivateData;
|
||||
} __attribute__((packed));
|
||||
|
||||
#ifndef __kernel__
|
||||
dev_t RegisterFileSystem(struct FileSystemInfo *Info, struct Inode *Root);
|
||||
int UnregisterFileSystem(dev_t Device);
|
||||
#endif // !__kernel__
|
||||
|
||||
#endif // !__FENNIX_API_FILESYSTEM_H__
|
||||
|
@ -239,6 +239,8 @@ typedef struct
|
||||
};
|
||||
} InputReport;
|
||||
|
||||
#ifndef __kernel__
|
||||
EXTERNC int ReportInputEvent(InputReport *Report);
|
||||
#endif // !__kernel__
|
||||
|
||||
#endif // !__FENNIX_API_INPUT_H__
|
||||
|
@ -171,11 +171,13 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifndef __kernel__
|
||||
PCIArray *GetPCIDevices(uint16_t Vendors[], uint16_t Devices[]);
|
||||
void InitializePCI(PCIDevice *Device);
|
||||
uint32_t GetBAR(uint8_t Index, PCIDevice *Device);
|
||||
uint8_t iLine(PCIDevice *Device);
|
||||
uint8_t iPin(PCIDevice *Device);
|
||||
#endif // !__kernel__
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user