Fix driver implementation

This commit is contained in:
EnderIce2 2024-07-07 03:15:17 +03:00
parent f85935f8f3
commit 4ecf37c44e
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
64 changed files with 2893 additions and 2863 deletions

View File

@ -4,14 +4,14 @@
"head",
],
"body": [
"#ifndef __FENNIX_API_${2:header}_H__",
"#define __FENNIX_API_${2:header}_H__",
"#ifndef __FENNIX_DRIVER_${2:header}_H__",
"#define __FENNIX_DRIVER_${2:header}_H__",
"",
"#include <types.h>",
"",
"$0",
"",
"#endif // !__FENNIX_API_${2:header}_H__",
"#endif // !__FENNIX_DRIVER_${2:header}_H__",
""
],
"description": "Create header."

View File

@ -1,5 +1,5 @@
build:
cp -f ../Kernel/driver.h include/driver.h
cp -rf ../Kernel/include/interface/* include/
mkdir -p out
make -C library build
make -C audio build
@ -7,6 +7,7 @@ build:
make -C misc build
make -C network build
make -C storage build
make -C filesystem build
prepare:
$(info Nothing to prepare)
@ -19,3 +20,4 @@ clean:
make -C misc clean
make -C network clean
make -C storage clean
make -C filesystem clean

View File

@ -1,83 +1,22 @@
# Config file
# Config files
include ../../../Makefile.conf
FILENAME = ac97.drv
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver
LDFLAGS := \
-fPIC -fPIE -pie \
-Wl,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared -fvisibility=hidden
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
FILENAME = ac97.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -21,6 +21,7 @@
#include <base.h>
#include <pci.h>
#include <io.h>
#include <fs.h>
#define DescriptorListLength 0x20
@ -370,13 +371,13 @@ public:
{
if (Buffer == nullptr)
{
Log("Invalid buffer.");
KernelLog("Invalid buffer.");
return -EINVAL;
}
if ((Size == 0) || (Size % (SampleSize * Channels)))
{
Log("Invalid buffer length.");
KernelLog("Invalid buffer length.");
return -EINVAL;
}
@ -431,7 +432,7 @@ public:
if (Wrote == 0)
{
Log("Wrote 0 bytes.");
KernelLog("Wrote 0 bytes.");
break;
}
@ -563,7 +564,7 @@ public:
uint16_t CurrentBDL = inb(BusMasterAddress + PCMOUT_BufferDescriptorEntry);
uint16_t LastBDL = (CurrentBDL + 2) & (DescriptorListLength - 1);
outb(BusMasterAddress + PCMOUT_DescriptorEntries, LastBDL);
Log("FIXME: CurrentBDL: %d, LastBDL: %d", CurrentBDL, LastBDL);
KernelLog("FIXME: CurrentBDL: %d, LastBDL: %d", CurrentBDL, LastBDL);
}
else if (Status & TC_LastBufferEntryInterruptEnable)
{
@ -577,7 +578,7 @@ public:
}
else if (Status & TC_FifoERRORInterruptEnable)
{
Log("FIFO error");
KernelLog("FIFO error");
outw(MixerAddress + PCMOUT_Status, TC_FifoERRORInterruptEnable);
}
else
@ -689,7 +690,7 @@ public:
};
AC97Device *Drivers[4] = {nullptr};
dev_t AudioID[4] = {0};
dev_t AudioID[4] = {(dev_t)-1};
#define OIR(x) OIR_##x
#define CREATE_OIR(x) \
@ -700,20 +701,40 @@ CREATE_OIR(1);
CREATE_OIR(2);
CREATE_OIR(3);
int drvOpen(dev_t, dev_t, int, mode_t) { return 0; }
int drvClose(dev_t, dev_t) { return 0; }
size_t drvRead(dev_t, dev_t, uint8_t *, size_t, off_t) { return 0; }
int __fs_Open(struct Inode *, int, mode_t) { return 0; }
int __fs_Close(struct Inode *) { return 0; }
ssize_t __fs_Read(struct Inode *, void *, size_t, off_t) { return 0; }
size_t drvWrite(dev_t, dev_t min, uint8_t *Buffer, size_t Size, off_t)
ssize_t __fs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t)
{
return Drivers[AudioID[min]]->write(Buffer, Size);
return Drivers[AudioID[Node->GetMinor()]]->write((uint8_t *)Buffer, Size);
}
int drvIoctl(dev_t, dev_t min, unsigned long Request, void *Argp)
int __fs_Ioctl(struct Inode *Node, unsigned long Request, void *Argp)
{
return Drivers[AudioID[min]]->ioctl((AudioIoctl)Request, Argp);
return Drivers[AudioID[Node->GetMinor()]]->ioctl((AudioIoctl)Request, Argp);
}
const struct InodeOperations AudioOps = {
.Lookup = nullptr,
.Create = nullptr,
.Remove = nullptr,
.Rename = nullptr,
.Read = __fs_Read,
.Write = __fs_Write,
.Truncate = nullptr,
.Open = __fs_Open,
.Close = __fs_Close,
.Ioctl = __fs_Ioctl,
.ReadDir = nullptr,
.MkDir = nullptr,
.RmDir = nullptr,
.SymLink = nullptr,
.ReadLink = nullptr,
.Seek = nullptr,
.Stat = nullptr,
};
PCIArray *Devices;
EXTERNC int cxx_Panic()
{
@ -734,10 +755,10 @@ EXTERNC int cxx_Probe()
{
uint16_t VendorIDs[] = {0x8086, PCI_END};
uint16_t DeviceIDs[] = {0x2415, PCI_END};
Devices = FindPCIDevices(VendorIDs, DeviceIDs);
Devices = GetPCIDevices(VendorIDs, DeviceIDs);
if (Devices == nullptr)
{
Log("No AC'97 device found.");
KernelLog("No AC'97 device found.");
return -ENODEV;
}
@ -754,10 +775,10 @@ EXTERNC int cxx_Probe()
uint8_t Type = PCIBAR0 & 1;
if (Type != 1)
{
Log("Device %x:%x.%d BAR0 is not I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
KernelLog("Device %x:%x.%d BAR0 is not I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
continue;
}
@ -767,7 +788,7 @@ EXTERNC int cxx_Probe()
if (!Found)
{
Log("No valid AC'97 device found.");
KernelLog("No valid AC'97 device found.");
return -EINVAL;
}
return 0;
@ -787,10 +808,10 @@ EXTERNC int cxx_Initialize()
uint8_t Type = PCIBAR0 & 1;
if (Type != 1)
{
Log("Device %x:%x.%d BAR0 is not I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
KernelLog("Device %x:%x.%d BAR0 is not I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
continue;
}
@ -815,10 +836,7 @@ EXTERNC int cxx_Initialize()
default:
break;
}
dev_t ret = RegisterAudioDevice(ddt_Audio,
drvOpen, drvClose,
drvRead, drvWrite,
drvIoctl);
dev_t ret = RegisterDevice(AUDIO_TYPE_PCM, &AudioOps);
AudioID[Count] = ret;
Count++;
ctx = (PCIArray *)ctx->Next;
@ -841,10 +859,10 @@ EXTERNC int cxx_Finalize()
uint8_t Type = PCIBAR0 & 1;
if (Type != 1)
{
Log("Device %x:%x.%d BAR0 is not I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
KernelLog("Device %x:%x.%d BAR0 is not I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
continue;
}
@ -853,5 +871,11 @@ EXTERNC int cxx_Finalize()
ctx = (PCIArray *)ctx->Next;
}
for (size_t i = 0; i < sizeof(AudioID) / sizeof(dev_t); i++)
{
if (AudioID[i] != (dev_t)-1)
UnregisterDevice(AudioID[i]);
}
return 0;
}

View File

@ -27,5 +27,5 @@ int DriverProbe() { return cxx_Probe(); }
DriverInfo("ac97",
"Audio Codec '97 Driver",
"EnderIce2",
"0.1",
0, 0, 1,
"GPLv3");

View File

@ -1,83 +1,22 @@
# Config file
# Config files
include ../../../Makefile.conf
FILENAME = hda.drv
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver
LDFLAGS := \
-fPIC -fPIE -pie \
-Wl,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared -fvisibility=hidden
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
FILENAME = hda.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -21,6 +21,7 @@
#include <base.h>
#include <pci.h>
#include <io.h>
#include <fs.h>
#include "hda.hpp"
@ -62,7 +63,7 @@ public:
RIRB((uint64_t *)AllocateMemory(1))
{
CTL = (ControllerRegisters *)(uintptr_t)Header->BAR0;
Log("Unimplemented HDA driver");
KernelLog("Unimplemented HDA driver");
return;
Initialized = true;
}
@ -75,7 +76,7 @@ public:
};
HDADevice *Drivers[4] = {nullptr};
dev_t AudioID[4] = {0};
dev_t AudioID[4] = {(dev_t)-1};
#define OIR(x) OIR_##x
#define CREATE_OIR(x) \
@ -86,20 +87,40 @@ CREATE_OIR(1);
CREATE_OIR(2);
CREATE_OIR(3);
int drvOpen(dev_t, dev_t, int, mode_t) { return 0; }
int drvClose(dev_t, dev_t) { return 0; }
size_t drvRead(dev_t, dev_t, uint8_t *, size_t, off_t) { return 0; }
int __fs_Open(struct Inode *, int, mode_t) { return 0; }
int __fs_Close(struct Inode *) { return 0; }
ssize_t __fs_Read(struct Inode *, void *, size_t, off_t) { return 0; }
size_t drvWrite(dev_t, dev_t min, uint8_t *Buffer, size_t Size, off_t)
ssize_t __fs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t)
{
return Drivers[AudioID[min]]->write(Buffer, Size);
return Drivers[AudioID[Node->GetMinor()]]->write((uint8_t *)Buffer, Size);
}
int drvIoctl(dev_t, dev_t min, unsigned long Request, void *Argp)
int __fs_Ioctl(struct Inode *Node, unsigned long Request, void *Argp)
{
return Drivers[AudioID[min]]->ioctl((AudioIoctl)Request, Argp);
return Drivers[AudioID[Node->GetMinor()]]->ioctl((AudioIoctl)Request, Argp);
}
const struct InodeOperations AudioOps = {
.Lookup = nullptr,
.Create = nullptr,
.Remove = nullptr,
.Rename = nullptr,
.Read = __fs_Read,
.Write = __fs_Write,
.Truncate = nullptr,
.Open = __fs_Open,
.Close = __fs_Close,
.Ioctl = __fs_Ioctl,
.ReadDir = nullptr,
.MkDir = nullptr,
.RmDir = nullptr,
.SymLink = nullptr,
.ReadLink = nullptr,
.Seek = nullptr,
.Stat = nullptr,
};
PCIArray *Devices;
EXTERNC int cxx_Panic()
{
@ -125,10 +146,10 @@ EXTERNC int cxx_Probe()
0x2668 /* ICH6 */,
0x293E /* ICH9 */,
PCI_END};
Devices = FindPCIDevices(VendorIDs, DeviceIDs);
Devices = GetPCIDevices(VendorIDs, DeviceIDs);
if (Devices == nullptr)
{
Log("No HDA device found.");
KernelLog("No HDA device found.");
return -ENODEV;
}
@ -145,10 +166,10 @@ EXTERNC int cxx_Probe()
uint8_t Type = PCIBAR0 & 1;
if (Type == 1)
{
Log("Device %x:%x.%d BAR0 is I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
KernelLog("Device %x:%x.%d BAR0 is I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
continue;
}
@ -158,7 +179,7 @@ EXTERNC int cxx_Probe()
if (!Found)
{
Log("No valid HDA device found.");
KernelLog("No valid HDA device found.");
return -EINVAL;
}
return 0;
@ -178,10 +199,10 @@ EXTERNC int cxx_Initialize()
uint8_t Type = PCIBAR0 & 1;
if (Type == 1)
{
Log("Device %x:%x.%d BAR0 is I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
KernelLog("Device %x:%x.%d BAR0 is I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
continue;
}
@ -191,10 +212,7 @@ EXTERNC int cxx_Initialize()
if (Drivers[Count]->IsInitialized())
{
dev_t ret = RegisterAudioDevice(ddt_Audio,
drvOpen, drvClose,
drvRead, drvWrite,
drvIoctl);
dev_t ret = RegisterDevice(AUDIO_TYPE_PCM, &AudioOps);
AudioID[Count] = ret;
Count++;
}
@ -203,7 +221,7 @@ EXTERNC int cxx_Initialize()
if (Count == 0)
{
Log("No valid HDA device found.");
KernelLog("No valid HDA device found.");
return -EINVAL;
}
@ -224,10 +242,10 @@ EXTERNC int cxx_Finalize()
uint8_t Type = PCIBAR0 & 1;
if (Type == 1)
{
Log("Device %x:%x.%d BAR0 is I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
KernelLog("Device %x:%x.%d BAR0 is I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
continue;
}
@ -235,5 +253,11 @@ EXTERNC int cxx_Finalize()
ctx = (PCIArray *)ctx->Next;
}
for (size_t i = 0; i < sizeof(AudioID) / sizeof(dev_t); i++)
{
if (AudioID[i] != (dev_t)-1)
UnregisterDevice(AudioID[i]);
}
return 0;
}

View File

@ -27,5 +27,5 @@ int DriverProbe() { return cxx_Probe(); }
DriverInfo("hda",
"Intel High Definition Audio Driver",
"EnderIce2",
"0.1",
0, 0, 1,
"GPLv3");

54
config.mk Normal file
View File

@ -0,0 +1,54 @@
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
DRIVER_LDFLAGS := -nostdlib -nodefaultlibs -nolibc -zmax-page-size=0x1000 \
-Wl,-Map file.map -fvisibility=hidden -Wl,--dynamic-linker=/boot/fennix.elf
ifeq ($(OSARCH), amd64)
DRIVER_CFLAGS := -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
DRIVER_CFLAGS := -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
DRIVER_CFLAGS += -pipe -fno-builtin -fPIC
endif
DRIVER_CFLAGS += -I../../include
ifeq ($(DEBUG), 1)
DRIVER_CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
DRIVER_CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
DRIVER_CFLAGS += -fstack-check
endif
DRIVER_LDFLAGS += -ggdb3 -O0
endif
WARNCFLAG = -Wall -Wextra
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(DRIVER_CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<

View File

@ -46,5 +46,5 @@ int DriverProbe()
DriverInfo("name",
"description",
"author",
"version",
0, 0, 0,
"license");

5
filesystem/Makefile Normal file
View File

@ -0,0 +1,5 @@
build:
make -C fat build
clean:
make -C fat clean

22
filesystem/fat/Makefile Normal file
View File

@ -0,0 +1,22 @@
# Config files
include ../../../Makefile.conf
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
FILENAME = fat.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

290
filesystem/fat/fat.h Normal file
View File

@ -0,0 +1,290 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_DRIVER_FAT_H__
#define __FENNIX_DRIVER_FAT_H__
#include <types.h>
/* Source: https://wiki.osdev.org/FAT */
struct BIOSParameterBlock
{
/** The first three bytes EB 3C 90 disassemble to JMP SHORT 3C NOP.
* (The 3C value may be different.) The reason for this is to jump
* over the disk format information (the BPB and EBPB). Since the
* first sector of the disk is loaded into ram at location
* 0x0000:0x7c00 and executed, without this jump, the processor
* would attempt to execute data that isn't code. Even for
* non-bootable volumes, code matching this pattern (or using the
* E9 jump opcode) is required to be present by both Windows and
* OS X. To fulfil this requirement, an infinite loop can be placed
* here with the bytes EB FE 90. */
uint8_t JumpBoot[3];
/** OEM identifier. The first 8 Bytes (3 - 10) is the version of DOS
* being used. The next eight Bytes 29 3A 63 7E 2D 49 48 and 43 read
* out the name of the version. The official FAT Specification from
* Microsoft says that this field is really meaningless and is ignored
* by MS FAT Modules, however it does recommend the value "MSWIN4.1"
* as some 3rd party drivers supposedly check it and expect it to
* have that value. Older versions of dos also report MSDOS5.1,
* linux-formatted floppy will likely to carry "mkdosfs" here, and
* FreeDOS formatted disks have been observed to have "FRDOS5.1" here.
* If the string is less than 8 bytes, it is padded with spaces. */
uint8_t OEM[8];
/** The number of Bytes per sector (remember, all numbers are in the
* little-endian format). */
uint16_t BytesPerSector;
/** Number of sectors per cluster. */
uint8_t SectorsPerCluster;
/** Number of reserved sectors. The boot record sectors are included
* in this value. */
uint16_t ReservedSectors;
/** Number of File Allocation Tables (FAT's) on the storage media.
* Often this value is 2. */
uint8_t NumberOfFATs;
/** Number of root directory entries (must be set so that the root
* directory occupies entire sectors). */
uint16_t RootDirectoryEntries;
/** The total sectors in the logical volume. If this value is 0, it
* means there are more than 65535 sectors in the volume, and the
* actual count is stored in the Large Sector Count entry at 0x20. */
uint16_t Sectors16;
/** This Byte indicates the media descriptor type. */
uint8_t Media;
/** Number of sectors per FAT. FAT12/FAT16 only. */
uint16_t SectorsPerFAT;
/** Number of sectors per track. */
uint16_t SectorsPerTrack;
/** Number of heads or sides on the storage media. */
uint16_t NumberOfHeads;
/** Number of hidden sectors. (i.e. the LBA of the beginning of
* the partition). */
uint32_t HiddenSectors;
/** Large sector count. This field is set if there are more than
* 65535 sectors in the volume, resulting in a value which does not
* fit in the Number of Sectors entry at 0x13. */
uint32_t Sectors32;
} __packed;
struct ExtendedBootRecord_FAT12_16
{
/** Drive number. The value here should be identical to the value
* returned by BIOS interrupt 0x13, or passed in the DL register;
* i.e. 0x00 for a floppy disk and 0x80 for hard disks. This number
* is useless because the media is likely to be moved to another
* machine and inserted in a drive with a different drive number. */
uint8_t DriveNumber;
/** Flags in Windows NT. Reserved otherwise. */
uint8_t Flags;
/** Signature (must be 0x28 or 0x29). */
uint8_t Signature;
/** VolumeID 'Serial' number. Used for tracking volumes between
* computers. You can ignore this if you want. */
uint32_t VolumeID;
/** Volume label string. This field is padded with spaces. */
uint8_t VolumeLabel[11];
/** System identifier string. This field is a string representation
* of the FAT file system type. It is padded with spaces. The spec
* says never to trust the contents of this string for any use. */
uint8_t SystemIdentifier[8];
/** Boot code. */
uint8_t BootCode[448];
/** Bootable partition signature 0xAA55. */
uint16_t BootSignature;
} __packed;
struct ExtendedBootRecord_FAT32
{
/** Sectors per FAT. The size of the FAT in sectors. */
uint32_t SectorsPerFAT;
/** Flags. */
uint16_t Flags;
/** FAT version number. The high byte is the major version and the
* low byte is the minor version. FAT drivers should respect this
* field. */
uint16_t FATVersion;
/** The cluster number of the root directory. Often this field is
* set to 2. */
uint32_t RootDirectoryCluster;
/** The sector number of the FSInfo structure. */
uint16_t FSInfoSector;
/** The sector number of the backup boot sector. */
uint16_t BackupBootSector;
/** Reserved. When the volume is formated these bytes should be zero. */
uint8_t Reserved[12];
/** Drive number. The values here are identical to the values returned
* by the BIOS interrupt 0x13. 0x00 for a floppy disk and 0x80 for
* hard disks. */
uint8_t DriveNumber;
/** Flags in Windows NT. Reserved otherwise. */
uint8_t Flags2;
/** Signature (must be 0x28 or 0x29). */
uint8_t Signature;
/** Volume ID 'Serial' number. Used for tracking volumes between
* computers. You can ignore this if you want. */
uint32_t VolumeID;
/** Volume label string. This field is padded with spaces. */
uint8_t VolumeLabel[11];
/** System identifier string. Always "FAT32 ". The spec says never
* to trust the contents of this string for any use. */
uint8_t SystemIdentifier[8];
/** Boot code. */
uint8_t BootCode[420];
/** Bootable partition signature 0xAA55. */
uint16_t BootSignature;
} __packed;
struct FSInfo
{
/** Lead signature (must be 0x41615252 to indicate a valid FSInfo
* structure). */
uint32_t LeadSignature;
/** Reserved, these bytes should never be used. */
uint8_t Reserved1[480];
/** Another signature (must be 0x61417272). */
uint32_t AnotherSignature;
/** Contains the last known free cluster count on the volume. If the
* value is 0xFFFFFFFF, then the free count is unknown and must be
* computed. However, this value might be incorrect and should at
* least be range checked (<= volume cluster count). */
uint32_t FreeClusterCount;
/** Indicates the cluster number at which the filesystem driver should
* start looking for available clusters. If the value is 0xFFFFFFFF,
* then there is no hint and the driver should start searching at 2.
* Typically this value is set to the last allocated cluster number.
* As the previous field, this value should be range checked. */
uint32_t NextFreeCluster;
/** Reserved. */
uint8_t Reserved2[12];
/** Trail signature (0xAA550000). */
uint32_t TrailSignature;
} __packed;
struct exFATBootRecord
{
/** The first three bytes EB 3C 90 disassemble to JMP SHORT 3C NOP.
* (The 3C value may be different.) The reason for this is to jump
* over the disk format information (the BPB and EBPB). Since the
* first sector of the disk is loaded into ram at location
* 0x0000:0x7c00 and executed, without this jump, the processor
* would attempt to execute data that isn't code. Even for
* non-bootable volumes, code matching this pattern (or using the
* E9 jump opcode) is required to be present by both Windows and
* OS X. To fulfil this requirement, an infinite loop can be placed
* here with the bytes EB FE 90. */
uint8_t JumpBoot[3];
/** OEM identifier. This contains the string "EXFAT ". Not to be
* used for filesystem determination, but it's a nice hint. */
uint8_t OEM[8];
/** Set to zero. This makes sure any FAT driver will not be able to
* load it. */
uint8_t Reserved1[53];
/** Partition offset. No idea why the partition itself would have
* this, but it's here. Might be wrong. Probably best to just ignore. */
uint64_t PartitionOffset;
/** Volume length. */
uint64_t VolumeLength;
/** FAT offset (in sectors) from start of partition. */
uint32_t FATOffset;
/** FAT length (in sectors). */
uint32_t FATLength;
/** Cluster heap offset (in sectors). */
uint32_t ClusterHeapOffset;
/** Cluster count. */
uint32_t ClusterCount;
/** Root directory cluster. Typically 4 (but just read this value). */
uint32_t RootDirectoryCluster;
/** Serial number of partition. */
uint32_t SerialNumber;
/** Filesystem revision. */
uint16_t FilesystemRevision;
/** Flags. */
uint16_t Flags;
/** Sector shift. */
uint8_t SectorShift;
/** Cluster shift. */
uint8_t ClusterShift;
/** Number of FATs. */
uint8_t NumberOfFATs;
/** Drive select. */
uint8_t DriveSelect;
/** Percentage in use. */
uint8_t PercentageInUse;
/** Reserved (set to 0). */
uint8_t Reserved2[7];
} __packed;
#endif // !__FENNIX_DRIVER_FAT_H__

View File

@ -15,11 +15,31 @@
along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_VM_H__
#define __FENNIX_API_VM_H__
#include <base.h>
#include <types.h>
int DriverEntry()
{
return 0;
}
bool IsVMwareBackdoorAvailable();
int DriverFinal()
{
return 0;
}
#endif // !__FENNIX_API_VM_H__
int DriverPanic()
{
return 0;
}
int DriverProbe()
{
/* Nothing to do */
return 0;
}
DriverInfo("fat",
"File Allocation Table Driver",
"EnderIce2",
0, 0, 1,
"GPLv3");

View File

@ -19,8 +19,6 @@
#define __FENNIX_API_AIP_H__
#include <types.h>
#include <aip/kbd.h>
#include <aip/mouse.h>
#define PIC1_CMD 0x20
#define PIC1_DATA (PIC1_CMD + 1)
@ -117,7 +115,145 @@ uint8_t PS2ReadAfterACK();
void PS2ClearOutputBuffer();
int PS2ACKTimeout();
#define WaitOutput PS2Wait(true)
#define WaitInput PS2Wait(false)
#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
#define PS2_KBD_CMD_IDENTIFY 0xF2
#define PS2_KBD_CMD_TYPEMATIC 0xF3
#define PS2_KBD_CMD_ENABLE_SCANNING 0xF4
#define PS2_KBD_CMD_DISABLE_SCANNING 0xF5
#define PS2_KBD_CMD_DEFAULTS 0xF6
#define PS2_KBD_CMD_ALL_TYPEMATIC 0xF7
#define PS2_KBD_CMD_ALL_MAKE_RELEASE 0xF8
#define PS2_KBD_CMD_ALL_MAKE 0xF9
#define PS2_KBD_CMD_ALL_TYPEMATIC_MAKE_RELEASE 0xFA
#define PS2_KBD_CMD_SPECIFIC_TYPEMATIC 0xFB
#define PS2_KBD_CMD_SPECIFIC_MAKE_RELEASE 0xFC
#define PS2_KBD_CMD_SPECIFIC_MAKE 0xFD
#define PS2_KBD_CMD_RESEND 0xFE
#define PS2_KBD_CMD_RESET 0xFF
#define PS2_KBD_RESP_ACK 0xFA
#define PS2_KBD_RESP_ECHO 0xEE
#define PS2_KBD_RESP_RESEND 0xFE
#define PS2_KBD_RESP_TEST_PASSED 0xAA
#define PS2_KBD_RESP_TEST_FAILED 0xFC
#define PS2_KBD_RESP_TEST_FAILED_2 0xFD
typedef enum
{
PS2_KBD_LED_SCROLL_LOCK = 1,
PS2_KBD_LED_NUM_LOCK = 2,
PS2_KBD_LED_CAPS_LOCK = 4
} PS2_KBD_LEDS;
typedef enum
{
PS2_KBD_SCAN_CODE_GET_CURRENT = 0,
PS2_KBD_SCAN_CODE_SET_1 = 1,
PS2_KBD_SCAN_CODE_SET_2 = 2,
PS2_KBD_SCAN_CODE_SET_3 = 3,
PS2_KBD_SC_SET_1 = 0x43,
PS2_KBD_SC_SET_2 = 0x41,
PS2_KBD_SC_SET_3 = 0x3F
} PS2_KBD_SCAN_CODE_SET;
typedef union
{
struct
{
/**
* 00000b - 30Hz
* 11111b - 2Hz
*/
uint8_t RepeatRate : 5;
/**
* 00b - 250ms
* 01b - 500ms
* 10b - 750ms
* 11b - 1000ms
*/
uint8_t Delay : 2;
/**
* Must be zero
*/
uint8_t Zero : 1;
};
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
#define PS2_MOUSE_CMD_GET_STATUS 0xE9
#define PS2_MOUSE_CMD_SET_STREAM_MODE 0xEA
#define PS2_MOUSE_CMD_READ_DATA 0xEB
#define PS2_MOUSE_CMD_RESET_WRAP_MODE 0xEC
#define PS2_MOUSE_CMD_SET_WRAP_MODE 0xEE
#define PS2_MOUSE_CMD_SET_REMOTE_MODE 0xF0
#define PS2_MOUSE_CMD_READ_ID 0xF2
/** Values: 10, 20, 40, 60, 80, 100, 200 */
#define PS2_MOUSE_CMD_SET_SAMPLE_RATE 0xF3
#define PS2_MOUSE_CMD_ENABLE_DATA_REPORTING 0xF4
#define PS2_MOUSE_CMD_DISABLE_DATA_REPORTING 0xF5
#define PS2_MOUSE_CMD_SET_DEFAULTS 0xF6
#define PS2_MOUSE_CMD_RESEND 0xFE
#define PS2_MOUSE_CMD_RESET 0xFF
#define PS2_MOUSE_RESP_ACK 0xFA
#define PS2_MOUSE_RESP_RESEND 0xFE
#define PS2_MOUSE_RESP_TEST_PASSED 0xAA
#define PS2_MOUSE_RESP_TEST_FAILED 0xFC
typedef enum
{
PS2_MOUSE_RES_1 = 0,
PS2_MOUSE_RES_2 = 1,
PS2_MOUSE_RES_4 = 2,
PS2_MOUSE_RES_8 = 3
} PS2_MOUSE_RESOLUTION;
typedef struct
{
union
{
struct
{
uint8_t LeftButton : 1;
uint8_t RightButton : 1;
uint8_t MiddleButton : 1;
uint8_t Always1 : 1;
uint8_t XSign : 1;
uint8_t YSign : 1;
uint8_t XOverflow : 1;
uint8_t YOverflow : 1;
} __attribute__((packed));
uint8_t Raw;
} Base;
uint8_t XMovement;
uint8_t YMovement;
union
{
struct
{
uint8_t Z : 4;
uint8_t Button4 : 1;
uint8_t Button5 : 1;
uint8_t Always0 : 1;
uint8_t Always0_2 : 1;
} __attribute__((packed));
uint8_t Raw;
} ZMovement;
} PS2_MOUSE_PACKET;
#endif // !__FENNIX_API_AIP_H__

View File

@ -1,45 +1,29 @@
/*
This file is part of Fennix Drivers.
This file is part of Fennix Kernel.
Fennix Drivers is free software: you can redistribute it and/or
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 Drivers is distributed in the hope that it will be useful,
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 Drivers. If not, see <https://www.gnu.org/licenses/>.
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_AUDIO_H__
#define __FENNIX_API_AUDIO_H__
#include <types.h>
#include <driver.h>
typedef int (*drvOpen_t)(dev_t, dev_t, int, mode_t);
typedef int (*drvClose_t)(dev_t, dev_t);
typedef size_t (*drvRead_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
typedef size_t (*drvWrite_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
typedef int (*drvIoctl_t)(dev_t, dev_t, unsigned long, void *);
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
dev_t RegisterAudioDevice(DeviceDriverType Type,
drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
int UnregisterAudioDevice(dev_t DeviceID, DeviceDriverType Type);
#ifdef __cplusplus
}
#endif // __cplusplus
#if __has_include(<interface/device.h>)
#include <interface/device.h>
#else
#include <device.h>
#endif
#endif // !__FENNIX_API_AUDIO_H__

View File

@ -77,20 +77,20 @@ extern "C"
void UnmapPages(void *VirtualAddress, size_t Pages);
/**
* @brief Print to the screen
* @brief Print to the kernel terminal
* @param Format The format string
* @param ... The arguments to the format string
*
* @note The newline character is automatically appended
*/
void KPrint(const char *Format, ...);
void KernelPrint(const char *Format, ...);
/**
* @brief Print to the kernel logger
* @param Format The format string
* @param ... The arguments to the format string
*/
void Log(const char *Format, ...);
void KernelLog(const char *Format, ...);
/**
* @brief Register an interrupt handler
@ -241,17 +241,20 @@ extern "C"
/** @copydoc LeaveCriticalSection */
#define LCS LeaveCriticalSection(__ECS)
#define DriverInfo(Name, Description, Author, Version, License) \
void __IdentifyDriver( \
dev_t ID, \
int (*GetDriverInfo)(dev_t, const char *, const char *, \
const char *, const char *, const char *)) \
{ \
GetDriverInfo(ID, Name, Description, Author, Version, License); \
}
#define DriverInfo(_Name, _Description, _Author, _MajorVersion, \
_MinorVersion, _PathVersion, _License) \
__attribute__((section(".driver.info"))) struct __DriverInfo \
__di = {.Name = _Name, \
.Description = _Description, \
.Author = _Author, \
.Version = {.APIVersion = 0, \
.Major = _MajorVersion, \
.Minor = _MinorVersion, \
.Patch = _PathVersion}, \
.License = _License}
#ifdef DEBUG
#define DebugLog(m, ...) Log(m, ##__VA_ARGS__)
#define DebugLog(m, ...) KernelLog(m, ##__VA_ARGS__)
#else
#define DebugLog(m, ...)
#endif // DEBUG

View File

@ -1,45 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_BLOCK_H__
#define __FENNIX_API_BLOCK_H__
#include <types.h>
#include <driver.h>
typedef int (*drvOpen_t)(dev_t, dev_t, int, mode_t);
typedef int (*drvClose_t)(dev_t, dev_t);
typedef size_t (*drvRead_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
typedef size_t (*drvWrite_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
typedef int (*drvIoctl_t)(dev_t, dev_t, unsigned long, void *);
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
dev_t RegisterBlockDevice(DeviceDriverType Type,
drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
int UnregisterBlockDevice(dev_t DeviceID, DeviceDriverType Type);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !__FENNIX_API_BLOCK_H__

74
include/device.h Normal file
View File

@ -0,0 +1,74 @@
/*
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_API_DEVICE_H__
#define __FENNIX_API_DEVICE_H__
#include <types.h>
#ifndef __FENNIX_API_FILESYSTEM_H__
#if __has_include(<interface/fs.h>)
#include <interface/fs.h>
#else
#include <fs.h>
#endif
#endif // !__FENNIX_API_FILESYSTEM_H__
typedef enum
{
DEVICE_TYPE_MASK = 0b1111111100000000000000000000000000000000,
DEVICE_TYPE_NONE = 0b0000000000000000000000000000000000000000,
DEVICE_TYPE_INPUT = 0b0000000100000000000000000000000000000000,
DEVICE_TYPE_AUDIO = 0b0000001000000000000000000000000000000000,
DEVICE_TYPE_NETWORK = 0b0000010000000000000000000000000000000000,
DEVICE_TYPE_BLOCK = 0b0000100000000000000000000000000000000000,
INPUT_TYPE_NONE = DEVICE_TYPE_INPUT + 0,
INPUT_TYPE_KEYBOARD = DEVICE_TYPE_INPUT + 2,
INPUT_TYPE_MOUSE = DEVICE_TYPE_INPUT + 4,
INPUT_TYPE_JOYSTICK = DEVICE_TYPE_INPUT + 8,
INPUT_TYPE_TOUCHSCREEN = DEVICE_TYPE_INPUT + 16,
INPUT_TYPE_GAMEPAD = DEVICE_TYPE_INPUT + 32,
INPUT_TYPE_ACCELEROMETER = DEVICE_TYPE_INPUT + 64,
INPUT_TYPE_GYROSCOPE = DEVICE_TYPE_INPUT + 128,
INPUT_TYPE_MAGNETOMETER = DEVICE_TYPE_INPUT + 256,
AUDIO_TYPE_NONE = DEVICE_TYPE_AUDIO + 0,
AUDIO_TYPE_PWM = DEVICE_TYPE_AUDIO + 2,
AUDIO_TYPE_DSP = DEVICE_TYPE_AUDIO + 4,
AUDIO_TYPE_PCM = DEVICE_TYPE_AUDIO + 8,
AUDIO_TYPE_MIDI = DEVICE_TYPE_AUDIO + 16,
NETWORK_TYPE_NONE = DEVICE_TYPE_NETWORK + 0,
NETWORK_TYPE_ETHERNET = DEVICE_TYPE_NETWORK + 2,
NETWORK_TYPE_WIFI = DEVICE_TYPE_NETWORK + 4,
NETWORK_TYPE_BLUETOOTH = DEVICE_TYPE_NETWORK + 8,
BLOCK_TYPE_NONE = DEVICE_TYPE_BLOCK + 0,
BLOCK_TYPE_SDCARD = DEVICE_TYPE_BLOCK + 2,
BLOCK_TYPE_HDD = DEVICE_TYPE_BLOCK + 4,
BLOCK_TYPE_SSD = DEVICE_TYPE_BLOCK + 8,
BLOCK_TYPE_USB = DEVICE_TYPE_BLOCK + 16,
BLOCK_TYPE_NVME = DEVICE_TYPE_BLOCK + 32,
BLOCK_TYPE_CDROM = DEVICE_TYPE_BLOCK + 64,
BLOCK_TYPE_FLOPPY = DEVICE_TYPE_BLOCK + 128,
} DeviceType;
EXTERNC dev_t RegisterDevice(DeviceType Type, const struct InodeOperations *Operations);
EXTERNC int UnregisterDevice(dev_t Device);
#endif // !__FENNIX_API_DEVICE_H__

View File

@ -20,30 +20,6 @@
#include <types.h>
typedef enum
{
_drf_Entry,
_drf_Final,
_drf_Panic,
_drf_Probe,
} __driverRegFunc;
typedef union
{
struct
{
uint8_t LeftButton : 1;
uint8_t RightButton : 1;
uint8_t MiddleButton : 1;
uint8_t Button4 : 1;
uint8_t Button5 : 1;
uint8_t Button6 : 1;
uint8_t Button7 : 1;
uint8_t Button8 : 1;
};
uint8_t Value;
} __MouseButtons;
typedef struct
{
/* PCIDevice */ void *Device;
@ -57,177 +33,22 @@ typedef struct
typedef enum
{
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_0,
IOCTL_AUDIO_GET_VOLUME = 0,
IOCTL_AUDIO_SET_VOLUME = 1,
KEY_Q,
KEY_W,
KEY_E,
KEY_R,
KEY_T,
KEY_Y,
KEY_U,
KEY_I,
KEY_O,
KEY_P,
KEY_A,
KEY_S,
KEY_D,
KEY_F,
KEY_G,
KEY_H,
KEY_J,
KEY_K,
KEY_L,
KEY_Z,
KEY_X,
KEY_C,
KEY_V,
KEY_B,
KEY_N,
KEY_M,
IOCTL_AUDIO_GET_MUTE = 2,
IOCTL_AUDIO_SET_MUTE = 3,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
IOCTL_AUDIO_GET_SAMPLE_RATE = 4,
IOCTL_AUDIO_SET_SAMPLE_RATE = 5,
KEYPAD_7,
KEYPAD_8,
KEYPAD_9,
KEYPAD_MINUS,
KEYPAD_4,
KEYPAD_5,
KEYPAD_6,
KEYPAD_PLUS,
KEYPAD_1,
KEYPAD_2,
KEYPAD_3,
KEYPAD_0,
KEYPAD_PERIOD,
KEYPAD_RETURN,
KEYPAD_ASTERISK,
KEYPAD_SLASH,
KEY_LEFT_CTRL,
KEY_RIGHT_CTRL,
KEY_LEFT_SHIFT,
KEY_RIGHT_SHIFT,
KEY_LEFT_ALT,
KEY_RIGHT_ALT,
KEY_ESCAPE,
KEY_MINUS,
KEY_EQUAL,
KEY_BACKSPACE,
KEY_TAB,
KEY_LEFT_BRACKET,
KEY_RIGHT_BRACKET,
KEY_RETURN,
KEY_SEMICOLON,
KEY_APOSTROPHE,
KEY_BACK_TICK,
KEY_BACKSLASH,
KEY_COMMA,
KEY_PERIOD,
KEY_SLASH,
KEY_SPACE,
KEY_CAPS_LOCK,
KEY_NUM_LOCK,
KEY_SCROLL_LOCK,
KEY_PRINT_SCREEN,
KEY_HOME,
KEY_UP_ARROW,
KEY_LEFT_ARROW,
KEY_RIGHT_ARROW,
KEY_DOWN_ARROW,
KEY_PAGE_UP,
KEY_PAGE_DOWN,
KEY_END,
KEY_INSERT,
KEY_DELETE,
KEY_LEFT_GUI,
KEY_RIGHT_GUI,
KEY_APPS,
KEY_MULTIMEDIA_PREV_TRACK,
KEY_MULTIMEDIA_NEXT_TRACK,
KEY_MULTIMEDIA_MUTE,
KEY_MULTIMEDIA_CALCULATOR,
KEY_MULTIMEDIA_PLAY,
KEY_MULTIMEDIA_STOP,
KEY_MULTIMEDIA_VOL_DOWN,
KEY_MULTIMEDIA_VOL_UP,
KEY_MULTIMEDIA_WWW_HOME,
KEY_MULTIMEDIA_WWW_SEARCH,
KEY_MULTIMEDIA_WWW_FAVORITES,
KEY_MULTIMEDIA_WWW_REFRESH,
KEY_MULTIMEDIA_WWW_STOP,
KEY_MULTIMEDIA_WWW_FORWARD,
KEY_MULTIMEDIA_WWW_BACK,
KEY_MULTIMEDIA_MY_COMPUTER,
KEY_MULTIMEDIA_EMAIL,
KEY_MULTIMEDIA_MEDIA_SELECT,
KEY_ACPI_POWER,
KEY_ACPI_SLEEP,
KEY_ACPI_WAKE,
KEY_PRESSED = 0x80,
} KeyScanCodes;
typedef enum
{
ddt_Keyboard,
ddt_Mouse,
ddt_Joystick,
ddt_Gamepad,
ddt_Touchpad,
ddt_Touchscreen,
ddt_SATA,
ddt_ATA,
ddt_NVMe,
ddt_Audio,
ddt_Network,
} DeviceDriverType;
typedef enum
{
IOCTL_AUDIO_GET_VOLUME,
IOCTL_AUDIO_SET_VOLUME,
IOCTL_AUDIO_GET_MUTE,
IOCTL_AUDIO_SET_MUTE,
IOCTL_AUDIO_GET_SAMPLE_RATE,
IOCTL_AUDIO_SET_SAMPLE_RATE,
IOCTL_AUDIO_GET_CHANNELS,
IOCTL_AUDIO_SET_CHANNELS,
IOCTL_AUDIO_GET_CHANNELS = 6,
IOCTL_AUDIO_SET_CHANNELS = 7,
} AudioIoctl;
typedef enum
{
IOCTL_NET_GET_MAC,
IOCTL_NET_GET_MAC = 0,
} NetIoctl;
typedef enum
@ -239,89 +60,17 @@ typedef enum
MAP_CACHE_DISABLE = 1 << 4,
} PageMapFlags;
typedef struct
struct __DriverInfo
{
struct
const char *Name;
const char *Description;
const char *Author;
struct __DriverVersion
{
uint8_t Major;
uint8_t Minor;
uint8_t Patch;
} APIVersion;
dev_t MajorID;
uintptr_t Base;
/* Internal */
int (*RegisterFunction)(dev_t MajorID, void *Function, __driverRegFunc Type);
int (*GetDriverInfo)(dev_t MajorID, const char *Name, const char *Description, const char *Author, const char *Version, const char *License);
/* Interrupts */
int (*RegisterInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
int (*OverrideInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
int (*UnregisterInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
int (*UnregisterAllInterruptHandlers)(dev_t MajorID, void *Handler);
/* Input */
dev_t (*RegisterInputDevice)(dev_t MajorID, DeviceDriverType Type);
int (*UnregisterInputDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
int (*ReportKeyboardEvent)(dev_t MajorID, dev_t MinorID, uint8_t ScanCode);
int (*ReportRelativeMouseEvent)(dev_t MajorID, dev_t MinorID, __MouseButtons Button, int X, int Y, int8_t Z);
int (*ReportAbsoluteMouseEvent)(dev_t MajorID, dev_t MinorID, __MouseButtons Button, uintptr_t X, uintptr_t Y, int8_t Z);
/* Storage */
dev_t (*RegisterBlockDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
int (*UnregisterBlockDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
/* Audio */
dev_t (*RegisterAudioDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
int (*UnregisterAudioDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
/* Network */
dev_t (*RegisterNetDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
int (*UnregisterNetDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
int (*ReportNetworkPacket)(dev_t MajorID, dev_t MinorID, void *Buffer, size_t Size);
/* Logging */
void (*KPrint)(dev_t MajorID, const char *Format, va_list args);
void (*KernelLog)(dev_t MajorID, const char *Format, va_list args);
/* Memory */
void *(*RequestPages)(dev_t MajorID, size_t Pages);
void (*FreePages)(dev_t MajorID, void *Pointer, size_t Pages);
/* Mapping */
void (*AppendMapFlag)(dev_t MajorID, void *Address, PageMapFlags Flag);
void (*RemoveMapFlag)(dev_t MajorID, void *Address, PageMapFlags Flag);
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);
/* Scheduling */
pid_t (*CreateKernelProcess)(dev_t MajorID, const char *Name);
pid_t (*CreateKernelThread)(dev_t MajorID, pid_t pId, const char *Name, void *EntryPoint, void *Argument);
pid_t (*GetCurrentProcess)(dev_t MajorID);
int (*KillProcess)(dev_t MajorID, pid_t pId, int ExitCode);
int (*KillThread)(dev_t MajorID, pid_t tId, pid_t pId, int ExitCode);
void (*Yield)(dev_t MajorID);
void (*Sleep)(dev_t MajorID, uint64_t Milliseconds);
/* PCI */
__PCIArray *(*GetPCIDevices)(dev_t MajorID, uint16_t Vendors[], uint16_t Devices[]);
void (*InitializePCI)(dev_t MajorID, void *Header);
uint32_t (*GetBAR)(dev_t MajorID, uint8_t Index, void *Header);
/* Kernel std API */
void *(*memcpy)(dev_t MajorID, void *Destination, const void *Source, size_t Length);
void *(*memset)(dev_t MajorID, void *Destination, int Value, size_t Length);
void *(*memmove)(dev_t MajorID, void *Destination, const void *Source, size_t Length);
int (*memcmp)(dev_t MajorID, const void *Left, const void *Right, size_t Length);
size_t (*strlen)(dev_t MajorID, const char *String);
char *(*strcpy)(dev_t MajorID, char *Destination, const char *Source);
char *(*strcat)(dev_t MajorID, char *Destination, const char *Source);
int (*strcmp)(dev_t MajorID, const char *Left, const char *Right);
int (*strncmp)(dev_t MajorID, const char *Left, const char *Right, size_t Length);
char *(*strchr)(dev_t MajorID, const char *String, int Character);
char *(*strrchr)(dev_t MajorID, const char *String, int Character);
char *(*strstr)(dev_t MajorID, const char *Haystack, const char *Needle);
} __driverAPI;
int APIVersion;
int Major, Minor, Patch;
} Version;
const char *License;
};
#endif // !__FENNIX_API_DRIVER_FUNCTIONS_H__

View File

@ -1,408 +1,604 @@
/*
This file is part of Fennix Drivers.
This file is part of Fennix Kernel.
Fennix Drivers is free software: you can redistribute it and/or
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 Drivers is distributed in the hope that it will be useful,
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 Drivers. If not, see <https://www.gnu.org/licenses/>.
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _ERRNO_H
#define _ERRNO_H
/** Operation not permitted */
#define EPERM 1
/** No such file or directory */
#define ENOENT 2
/** No such process */
#define ESRCH 3
/** Interrupted system call */
#define EINTR 4
/** I/O error */
#define EIO 5
/** No such device or address */
#define ENXIO 6
/** Argument list too long */
#define E2BIG 7
/** Exec format error */
#define ENOEXEC 8
/** Bad file number */
#define EBADF 9
/** No child processes */
#define ECHILD 10
/** Try again */
#define EAGAIN 11
/** Out of memory */
#define ENOMEM 12
/** Permission denied */
#define EACCES 13
/** Bad address */
#define EFAULT 14
/** Block device required */
#define ENOTBLK 15
/** Device or resource busy */
#define EBUSY 16
/** File exists */
#define EEXIST 17
/** Cross-device link */
#define EXDEV 18
/** No such device */
#define ENODEV 19
/** Not a directory */
#define ENOTDIR 20
/** Is a directory */
#define EISDIR 21
/** Invalid argument */
#define EINVAL 22
/** File table overflow */
#define ENFILE 23
/** Too many open files */
#define EMFILE 24
/** Not a typewriter */
#define ENOTTY 25
/** Text file busy */
#define ETXTBSY 26
/** File too large */
#define EFBIG 27
/** No space left on device */
#define ENOSPC 28
/** Illegal seek */
#define ESPIPE 29
/** Read-only file system */
#define EROFS 30
/** Too many links */
#define EMLINK 31
/** Broken pipe */
#define EPIPE 32
/** Math argument out of domain of func */
#define EDOM 33
/** Math result not representable */
#define ERANGE 34
/** Resource deadlock would occur */
#define EDEADLK 35
/** File name too long */
#define ENAMETOOLONG 36
/** No record locks available */
#define ENOLCK 37
/** Function not implemented */
#define ENOSYS 38
/** Directory not empty */
#define ENOTEMPTY 39
/** Too many symbolic links encountered */
#define ELOOP 40
/** No message of desired type */
#define ENOMSG 42
/** Identifier removed */
#define EIDRM 43
/** Channel number out of range */
#define ECHRNG 44
/** Level 2 not synchronized */
#define EL2NSYNC 45
/** Level 3 halted */
#define EL3HLT 46
/** Level 3 reset */
#define EL3RST 47
/** Link number out of range */
#define ELNRNG 48
/** Protocol driver not attached */
#define EUNATCH 49
/** No CSI structure available */
#define ENOCSI 50
/** Level 2 halted */
#define EL2HLT 51
/** Invalid exchange */
#define EBADE 52
/** Invalid request descriptor */
#define EBADR 53
/** Exchange full */
#define EXFULL 54
/** No anode */
#define ENOANO 55
/** Invalid request code */
#define EBADRQC 56
/** Invalid slot */
#define EBADSLT 57
/** Bad font file format */
#define EBFONT 59
/** Device not a stream */
#define ENOSTR 60
/** No data available */
#define ENODATA 61
/** Timer expired */
#define ETIME 62
/** Out of streams resources */
#define ENOSR 63
/** Machine is not on the network */
#define ENONET 64
/** Package not installed */
#define ENOPKG 65
/** Object is remote */
#define EREMOTE 66
/** Link has been severed */
#define ENOLINK 67
/** Advertise error */
#define EADV 68
/** Srmount error */
#define ESRMNT 69
/** Communication error on send */
#define ECOMM 70
/** Protocol error */
#define EPROTO 71
/** Multihop attempted */
#define EMULTIHOP 72
/** RFS specific error */
#define EDOTDOT 73
/** Not a data message */
#define EBADMSG 74
/** Value too large for defined data type */
#define EOVERFLOW 75
/** Name not unique on network */
#define ENOTUNIQ 76
/** File descriptor in bad state */
#define EBADFD 77
/** Remote address changed */
#define EREMCHG 78
/** Can not access a needed shared library */
#define ELIBACC 79
/** Accessing a corrupted shared library */
#define ELIBBAD 80
/** .lib section in a.out corrupted */
#define ELIBSCN 81
/** Attempting to link in too many shared libraries */
#define ELIBMAX 82
/** Cannot exec a shared library directly */
#define ELIBEXEC 83
/** Illegal byte sequence */
#define EILSEQ 84
/** Interrupted system call should be restarted */
#define ERESTART 85
/** Streams pipe error */
#define ESTRPIPE 86
/** Too many users */
#define EUSERS 87
/** Socket operation on non-socket */
#define ENOTSOCK 88
/** Destination address required */
#define EDESTADDRREQ 89
/** Message too long */
#define EMSGSIZE 90
/** Protocol wrong type for socket */
#define EPROTOTYPE 91
/** Protocol not available */
#define ENOPROTOOPT 92
/** Protocol not supported */
#define EPROTONOSUPPORT 93
/** Socket type not supported */
#define ESOCKTNOSUPPORT 94
/** Operation not supported on transport endpoint */
#define EOPNOTSUPP 95
/** Protocol family not supported */
#define EPFNOSUPPORT 96
/** Address family not supported by protocol */
#define EAFNOSUPPORT 97
/** Address already in use */
#define EADDRINUSE 98
/** Cannot assign requested address */
#define EADDRNOTAVAIL 99
/** Network is down */
#define ENETDOWN 100
/** Network is unreachable */
#define ENETUNREACH 101
/** Network dropped connection because of reset */
#define ENETRESET 102
/** Software caused connection abort */
#define ECONNABORTED 103
/** Connection reset by peer */
#define ECONNRESET 104
/** No buffer space available */
#define ENOBUFS 105
/** Transport endpoint is already connected */
#define EISCONN 106
/** Transport endpoint is not connected */
#define ENOTCONN 107
/** Cannot send after transport endpoint shutdown */
#define ESHUTDOWN 108
/** Too many references: cannot splice */
#define ETOOMANYREFS 109
/** Connection timed out */
#define ETIMEDOUT 110
/** Connection refused */
#define ECONNREFUSED 111
/** Host is down */
#define EHOSTDOWN 112
/** No route to host */
#define EHOSTUNREACH 113
/** Operation already in progress */
#define EALREADY 114
/** Operation now in progress */
#define EINPROGRESS 115
/** Stale NFS file handle */
#define ESTALE 116
/** Structure needs cleaning */
#define EUCLEAN 117
/** Not a XENIX named type file */
#define ENOTNAM 118
/** No XENIX semaphores available */
#define ENAVAIL 119
/** Is a named type file */
#define EISNAM 120
/** Remote I/O error */
#define EREMOTEIO 121
/** Quota exceeded */
#define EDQUOT 122
/** No medium found */
#define ENOMEDIUM 123
/** Wrong medium type */
#define EMEDIUMTYPE 124
/** Operation Canceled */
#define ECANCELED 125
/** Required key not available */
#define ENOKEY 126
/** Key has expired */
#define EKEYEXPIRED 127
/** Key has been revoked */
#define EKEYREVOKED 128
/** Key was rejected by service */
#define EKEYREJECTED 129
/** Owner died */
#define EOWNERDEAD 130
/** State not recoverable */
#define ENOTRECOVERABLE 131
#endif // !_ERRNO_H
#ifndef __FENNIX_KERNEL_ERRNO_H__
#define __FENNIX_KERNEL_ERRNO_H__
/**
* The documentation for these error codes are from:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
*
* Full list:
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
*/
typedef enum
{
/**
* No Error
*/
EOK = 0,
/**
* Argument list too long. The sum of the number of bytes used by the
* new process image's argument list and environment list is greater
* than the system-imposed limit of {ARG_MAX} bytes.
* or:
* Lack of space in an output buffer.
* or:
* Argument is greater than the system-imposed maximum.
*/
E2BIG = 1,
/**
* Permission denied. An attempt was made to access a file in a way
* forbidden by its file access permissions.
*/
EACCES = 2,
/**
* Address in use. The specified address is in use.
*/
EADDRINUSE = 3,
/**
* Address not available. The specified address is not available from
* the local system.
*/
EADDRNOTAVAIL = 4,
/**
* Address family not supported. The implementation does not support
* the specified address family, or the specified address is not a
* valid address for the address family of the specified socket.
*/
EAFNOSUPPORT = 5,
/**
* Resource temporarily unavailable. This is a temporary condition
* and later calls to the same routine may complete normally.
*/
EAGAIN = 6,
/**
* Connection already in progress. A connection request is already in
* progress for the specified socket.
*/
EALREADY = 7,
/**
* Bad file descriptor. A file descriptor argument is out of range,
* refers to no open file, or a read (write) request is made to a
* file that is only open for writing (reading).
*/
EBADF = 8,
/**
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
* I_RECVFD request to a STREAMS device, a message arrived at the
* head of the STREAM that is inappropriate for the function
* receiving the message.
* read()
* Message waiting to be read on a STREAM is not a data message.
* getmsg() or getpmsg()
* A file descriptor was received instead of a control message.
* ioctl()
* Control or data information was received instead of a file
* descriptor when I_RECVFD was specified.
*/
EBADMSG = 9,
/**
* Resource busy. An attempt was made to make use of a system
* resource that is not currently available, as it is being
* used by another process in a manner that would have
* conflicted with the request being made by this process.
*/
EBUSY = 10,
/**
* Operation canceled. The associated asynchronous operation was
* canceled before completion.
*/
ECANCELED = 11,
/**
* No child process. A wait(), waitid(), or waitpid() function was
* executed by a process that had no existing or unwaited-for
* child process.
*/
ECHILD = 12,
/**
* Connection aborted. The connection has been aborted.
*/
ECONNABORTED = 13,
/**
* Connection refused. An attempt to connect to a socket was refused
* because there was no process listening or because the queue of
* connection requests was full and the underlying protocol does not
* support retransmissions.
*/
ECONNREFUSED = 14,
/**
* Connection reset. The connection was forcibly closed by the peer.
*/
ECONNRESET = 15,
/**
* Resource deadlock would occur. An attempt was made to lock a system
* resource that would have resulted in a deadlock situation.
*/
EDEADLK = 16,
/**
* Destination address required. No bind address was established.
*/
EDESTADDRREQ = 17,
/**
* Domain error. An input argument is outside the defined domain of the
* mathematical function (defined in the ISO C standard).
*/
EDOM = 18,
/**
* Reserved.
*/
EDQUOT = 19,
/**
* File exists. An existing file was mentioned in an inappropriate
* context; for example, as a new link name in the link() function.
*/
EEXIST = 20,
/**
* Bad address. The system detected an invalid address in attempting
* to use an argument of a call. The reliable detection of this error
* cannot be guaranteed, and when not detected may result in the
* generation of a signal, indicating an address violation, which is
* sent to the process.
*/
EFAULT = 21,
/**
* File too large. The size of a file would exceed the maximum file
* size of an implementation or offset maximum established in the
* corresponding file description.
*/
EFBIG = 22,
/**
* Host is unreachable. The destination host cannot be reached
* (probably because the host is down or a remote router cannot
* reach it).
*/
EHOSTUNREACH = 23,
/**
* Identifier removed. Returned during XSI interprocess communication
* if an identifier has been removed from the system.
*/
EIDRM = 24,
/**
* Illegal byte sequence. A wide-character code has been detected that
* does not correspond to a valid character, or a byte sequence does
* not form a valid wide-character code (defined in the ISO C standard).
*/
EILSEQ = 25,
/**
* Operation in progress. This code is used to indicate that an
* asynchronous operation has not yet completed.
* or:
* O_NONBLOCK is set for the socket file descriptor and the connection
* cannot be immediately established.
*/
EINPROGRESS = 26,
/**
* Interrupted function call. An asynchronous signal was caught by the
* process during the execution of an interruptible function. If the
* signal handler performs a normal return, the interrupted function
* call may return this condition (see the Base Definitions volume
* of POSIX.1-2017, <signal.h>).
*/
EINTR = 27,
/**
* Invalid argument. Some invalid argument was supplied; for example,
* specifying an undefined signal in a signal() function or a
* kill() function.
*/
EINVAL = 28,
/**
* Input/output error. Some physical input or output error has occurred.
* This error may be reported on a subsequent operation on the same
* file descriptor. Any other error-causing operation on the same file
* descriptor may cause the [EIO] error indication to be lost.
*/
EIO = 29,
/**
* Socket is connected. The specified socket is already connected.
*/
EISCONN = 30,
/**
* Is a directory. An attempt was made to open a directory with write
* mode specified.
*/
EISDIR = 31,
/**
* Symbolic link loop. A loop exists in symbolic links encountered
* during pathname resolution. This error may also be returned if
* more than {SYMLOOP_MAX} symbolic links are encountered during
* pathname resolution.
*/
ELOOP = 32,
/**
* File descriptor value too large or too many open streams. An
* attempt was made to open a file descriptor with a value greater
* than or equal to {OPEN_MAX}, or an attempt was made to open more
* than the maximum number of streams allowed in the process.
*/
EMFILE = 33,
/**
* Too many links. An attempt was made to have the link count of a
* single file exceed {LINK_MAX}.
*/
EMLINK = 34,
/**
* Message too large. A message sent on a transport provider was
* larger than an internal message buffer or some other network limit.
* or:
* Inappropriate message buffer length.
*/
EMSGSIZE = 35,
/**
* Reserved.
*/
EMULTIHOP = 36,
/**
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
* the implementation considers this to be an error, or a pathname
* component is longer than {NAME_MAX}. This error may also occur
* when pathname substitution, as a result of encountering a
* symbolic link during pathname resolution, results in a pathname
* string the size of which exceeds {PATH_MAX}.
*/
ENAMETOOLONG = 37,
/**
* Network is down. The local network interface used to reach the
* destination is down.
*/
ENETDOWN = 38,
/**
* The connection was aborted by the network.
*/
ENETRESET = 39,
/**
* Network unreachable. No route to the network is present.
*/
ENETUNREACH = 40,
/**
* Too many files open in system. Too many files are currently open
* in the system. The system has reached its predefined limit for
* simultaneously open files and temporarily cannot accept requests
* to open another one.
*/
ENFILE = 41,
/**
* No buffer space available. Insufficient buffer resources were
* available in the system to perform the socket operation.
*/
ENOBUFS = 42,
/**
* No message available. No message is available on the STREAM head
* read queue.
*/
ENODATA = 43,
/**
* No such device. An attempt was made to apply an inappropriate
* function to a device; for example, trying to read a write-only
* device such as a printer.
*/
ENODEV = 44,
/**
* No such file or directory. A component of a specified pathname
* does not exist, or the pathname is an empty string.
*/
ENOENT = 45,
/**
* Executable file format error. A request is made to execute a file
* that, although it has appropriate privileges, is not in the
* format required by the implementation for executable files.
*/
ENOEXEC = 46,
/**
* No locks available. A system-imposed limit on the number of
* simultaneous file and record locks has been reached and no more
* are currently available.
*/
ENOLCK = 47,
/**
* Reserved.
*/
ENOLINK = 48,
/**
* Not enough space. The new process image requires more memory than
* is allowed by the hardware or system-imposed memory management
* constraints.
*/
ENOMEM = 49,
/**
* No message of the desired type. The message queue does not contain
* a message of the required type during XSI interprocess communication.
*/
ENOMSG = 50,
/**
* Protocol not available. The protocol option specified to
* setsockopt() is not supported by the implementation.
*/
ENOPROTOOPT = 51,
/**
* No space left on a device. During the write() function on a
* regular file or when extending a directory, there is no free
* space left on the device.
*/
ENOSPC = 52,
/**
* No STREAM resources. Insufficient STREAMS memory resources are
* available to perform a STREAMS-related function. This is a
* temporary condition; it may be recovered from if other
* processes release resources.
*/
ENOSR = 53,
/**
* Not a STREAM. A STREAM function was attempted on a file descriptor
* that was not associated with a STREAMS device.
*/
ENOSTR = 54,
/**
* Functionality not supported. An attempt was made to use optional
* functionality that is not supported in this implementation.
*/
ENOSYS = 55,
/**
* Socket not connected. The socket is not connected.
*/
ENOTCONN = 56,
/**
* Not a directory. A component of the specified pathname exists, but
* it is not a directory, when a directory was expected; or an
* attempt was made to create a non-directory file, and the specified
* pathname contains at least one non- <slash> character and ends
* with one or more trailing <slash> characters.
*/
ENOTDIR = 57,
/**
* Directory not empty. A directory other than an empty directory
* was supplied when an empty directory was expected.
*/
ENOTEMPTY = 58,
/**
* State not recoverable. The state protected by a robust mutex
* is not recoverable.
*/
ENOTRECOVERABLE = 59,
/**
* Not a socket. The file descriptor does not refer to a socket.
*/
ENOTSOCK = 60,
/**
* Not supported. The implementation does not support the requested
* feature or value.
*/
ENOTSUP = 61,
/**
* Inappropriate I/O control operation. A control function has been
* attempted for a file or special file for which the operation
* is inappropriate.
*/
ENOTTY = 62,
/**
* No such device or address. Input or output on a special file
* refers to a device that does not exist, or makes a request
* beyond the capabilities of the device. It may also occur when,
* for example, a tape drive is not on-line.
*/
ENXIO = 63,
/**
* Operation not supported on socket. The type of socket (address
* family or protocol) does not support the requested operation.
*/
EOPNOTSUPP = 64,
/**
* Value too large to be stored in data type. An operation was
* attempted which would generate a value that is outside the
* range of values that can be represented in the relevant data
* type or that are allowed for a given data item.
*/
EOVERFLOW = 65,
/**
* Previous owner died. The owner of a robust mutex terminated
* while holding the mutex lock.
*/
EOWNERDEAD = 66,
/**
* Operation not permitted. An attempt was made to perform an
* operation limited to processes with appropriate privileges or
* to the owner of a file or other resource.
*/
EPERM = 67,
/**
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
* for which there is no process to read the data.
*/
EPIPE = 68,
/**
* Protocol error. Some protocol error occurred. This error is
* device-specific, but is generally not related to a
* hardware failure.
*/
EPROTO = 69,
/**
* Protocol not supported. The protocol is not supported by the
* address family, or the protocol is not supported by
* the implementation.
*/
EPROTONOSUPPORT = 70,
/**
* Protocol wrong type for socket. The socket type is not
* supported by the protocol.
*/
EPROTOTYPE = 71,
/**
* Result too large or too small. The result of the function
* is too large (overflow) or too small (underflow) to be
* represented in the available space.
*/
ERANGE = 72,
/**
* Read-only file system. An attempt was made to modify a file
* or directory on a file system that is read-only.
*/
EROFS = 73,
/**
* Invalid seek. An attempt was made to access the file offset
* associated with a pipe or FIFO.
*/
ESPIPE = 74,
/**
* No such process. No process can be found corresponding to that
* specified by the given process ID.
*/
ESRCH = 75,
/**
* Reserved.
*/
ESTALE = 76,
/**
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
* has expired. The cause of this error is device-specific and could
* indicate either a hardware or software failure, or a timeout
* value that is too short for the specific operation. The status
* of the ioctl() operation is unspecified.
*/
ETIME = 77,
/**
* Connection timed out. The connection to a remote machine has
* timed out.
* If the connection timed out during execution of the function that
* reported this error (as opposed to timing out prior to the
* function being called), it is unspecified whether the function
* has completed some or all of the documented behavior associated
* with a successful completion of the function.
* or:
* Operation timed out. The time limit associated with the operation
* was exceeded before the operation completed.
*/
ETIMEDOUT = 78,
/**
* Text file busy. An attempt was made to execute a pure-procedure
* program that is currently open for writing, or an attempt has
* been made to open for writing a pure-procedure program that
* is being executed.
*/
ETXTBSY = 79,
/**
* Operation would block. An operation on a socket marked as
* non-blocking has encountered a situation such as no data available
* that otherwise would have caused the function to suspend execution.
*/
EWOULDBLOCK = 80,
/**
* Improper link. A link to a file on another file system was attempted.
*/
EXDEV = 81,
__ERRNO_MAX
} KernelErrors;
#include <types.h>
EXTERNC int *__errno_location(void) __attribute__((const));
#define errno (*__errno_location())
#ifdef __cplusplus
extern "C"
{
#endif
char *strerror(int errnum);
#ifdef __cplusplus
}
#endif
#endif // !__FENNIX_KERNEL_ERRNO_H__

380
include/fs.h Normal file
View File

@ -0,0 +1,380 @@
/*
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_API_FILESYSTEM_H__
#define __FENNIX_API_FILESYSTEM_H__
#include <types.h>
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
/**
* File type mask for the upper 32 bits of mode_t.
*
* @note Maybe it will be used in the future.
*/
#define S_IFMT32 037777600000
/**
* File type mask.
*
* This mask is used to extract the file type
* from the mode field of a stat structure.
*
* Doing bitwise AND with this mask will return
* the file type.
* Example: st_mode & S_IFMT
*
* Doing bitwise negation and AND with this mask
* will return the permissions.
* Example: st_mode & ~S_IFMT
*/
#define S_IFMT 0170000
/* Whiteout */
#define S_IFWHT 0160000
/* Socket */
#define S_IFSOCK 0140000
/* Symbolic link */
#define S_IFLNK 0120000
/* Regular file */
#define S_IFREG 0100000
/* Block device */
#define S_IFBLK 0060000
/* Directory */
#define S_IFDIR 0040000
/* Character device */
#define S_IFCHR 0020000
/* FIFO */
#define S_IFIFO 0010000
#define S_ISUID 04000
#define S_ISGID 02000
#define S_ISVTX 01000
/** Owner: RWX */
#define S_IRWXU 0700
/** Owner: R */
#define S_IRUSR 0400
/** Owner: W */
#define S_IWUSR 0200
/** Owner: X */
#define S_IXUSR 0100
/** Group: RWX */
#define S_IRWXG 0070
/** Group: R */
#define S_IRGRP 0040
/** Group: W */
#define S_IWGRP 0020
/** Group: X */
#define S_IXGRP 0010
/** Other: RWX */
#define S_IRWXO 0007
/** Other: R */
#define S_IROTH 0004
/** Other: W */
#define S_IWOTH 0002
/** Other: X */
#define S_IXOTH 0001
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100
#define O_EXCL 0200
#define O_TRUNC 01000
#define O_APPEND 02000
#define O_NOFOLLOW 0400000
#define O_CLOEXEC 02000000
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#define DT_UNKNOWN 0x0
#define DT_FIFO 0x1
#define DT_CHR 0x2
#define DT_DIR 0x4
#define DT_BLK 0x6
#define DT_REG 0x8
#define DT_LNK 0xA
#define DT_SOCK 0xC
#define DT_WHT 0xE
#define IFTODT(x) ((x) >> 12 & 0xF)
#define DTTOIF(x) ((x) << 12)
#define SYMLOOP_MAX 40
#ifndef __cplusplus
#define static_assert _Static_assert
#endif
#ifdef __LP64__
static_assert(sizeof(dev_t) == 8, "dev_t must be 64 bits");
static_assert(sizeof(ino_t) == 8, "ino_t must be 64 bits");
static_assert(sizeof(mode_t) == 4, "mode_t must be 32 bits");
static_assert(sizeof(nlink_t) == 4, "nlink_t must be 32 bits");
static_assert(sizeof(uid_t) == 4, "uid_t must be 32 bits");
static_assert(sizeof(gid_t) == 4, "gid_t must be 32 bits");
static_assert(sizeof(off_t) == 8, "off_t must be 64 bits");
static_assert(sizeof(time_t) == 8, "time_t must be 64 bits");
static_assert(sizeof(blksize_t) == 8, "blksize_t must be 64 bits");
static_assert(sizeof(blkcnt_t) == 8, "blkcnt_t must be 64 bits");
#else
static_assert(sizeof(dev_t) == 4, "dev_t must be 32 bits");
static_assert(sizeof(ino_t) == 4, "ino_t must be 32 bits");
static_assert(sizeof(mode_t) == 2, "mode_t must be 16 bits");
static_assert(sizeof(nlink_t) == 2, "nlink_t must be 16 bits");
static_assert(sizeof(uid_t) == 2, "uid_t must be 16 bits");
static_assert(sizeof(gid_t) == 2, "gid_t must be 16 bits");
static_assert(sizeof(off_t) == 4, "off_t must be 32 bits");
static_assert(sizeof(time_t) == 4, "time_t must be 32 bits");
static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits");
static_assert(sizeof(blkcnt_t) == 4, "blkcnt_t must be 32 bits");
#endif
#undef static_assert
struct kstat
{
/** Device ID of the file. */
dev_t Device;
/** Inode number. */
ino_t Index;
/** File type and mode. */
mode_t Mode;
/** Number of hard links. */
nlink_t HardLinks;
/** User ID of the file's owner. */
uid_t UserID;
/** Group ID of the file's owner. */
gid_t GroupID;
/** Device ID for special files. */
dev_t RawDevice;
/** Size of the file in bytes. */
off_t Size;
/** Time of last access. */
time_t AccessTime;
/** Time of last modification. */
time_t ModifyTime;
/** Time of last status change. */
time_t ChangeTime;
/** Optimal I/O block size. */
blksize_t BlockSize;
/** Number of blocks allocated. */
blkcnt_t Blocks;
/** Additional file attributes. */
mode_t Attribute;
#ifdef __cplusplus
dev_t MakeDevice(int Major, int Minor)
{
return ((Major & 0xFFF) << 8) |
(Minor & 0xFF);
}
int GetMajor()
{
return ((unsigned int)(Device) >> 8) & 0xFFF;
}
int GetMinor()
{
return Device & 0xFF;
}
void SetFileType(mode_t Type)
{
Mode = (Mode & ~S_IFMT) |
(Type & S_IFMT);
}
mode_t GetFileType() { return Mode & S_IFMT; }
void ClearFileType() { Mode = Mode & ~S_IFMT; }
bool IsType(mode_t Type) { return (Mode & S_IFMT) == Type; }
void SetPermissions(mode_t Permissions)
{
Mode = (Mode & S_IFMT) |
(Permissions & ~S_IFMT);
}
mode_t GetPermissions() { return Mode & ~S_IFMT; }
void ClearPermissions() { Mode = Mode & S_IFMT; }
#endif // __cplusplus
};
struct kdirent
{
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[];
};
struct Inode
{
dev_t Device, RawDevice;
ino_t Index;
mode_t Mode;
uint32_t Flags;
off_t Offset;
void *PrivateData;
#ifdef __cplusplus
/* ... */
void SetDevice(int Major, int Minor)
{
this->RawDevice = ((Major & 0xFFF) << 8) |
(Minor & 0xFF);
}
int GetMajor()
{
return ((unsigned int)(this->RawDevice) >> 8) & 0xFFF;
}
int GetMinor()
{
return this->RawDevice & 0xFF;
}
Inode()
{
Device = 0;
RawDevice = 0;
Index = 0;
Mode = 0;
Flags = 0;
Offset = 0;
PrivateData = nullptr;
}
~Inode() = default;
#else // __cplusplus
#define INODE_MAKEDEV(major, minor) \
((dev_t)(((major & 0xFFF) << 8) | \
(minor & 0xFF)))
#define INODE_MAJOR(rdev) \
((int)(((rdev) >> 8) & 0xFFF))
#define INODE_MINOR(rdev) \
((int)((rdev) & 0xFF))
#endif // __cplusplus
};
struct InodeOperations
{
int (*Lookup)(struct Inode *Parent, const char *Name, struct Inode **Result);
int (*Create)(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
int (*Remove)(struct Inode *Parent, const char *Name);
int (*Rename)(struct Inode *Parent, const char *OldName, const char *NewName);
ssize_t (*Read)(struct Inode *Node, void *Buffer, size_t Size, off_t Offset);
ssize_t (*Write)(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset);
int (*Truncate)(struct Inode *Node, off_t Size);
int (*Open)(struct Inode *Node, int Flags, mode_t Mode);
int (*Close)(struct Inode *Node);
int (*Ioctl)(struct Inode *Node, unsigned long Request, void *Argp);
ssize_t (*ReadDir)(struct Inode *Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries);
int (*MkDir)(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
int (*RmDir)(struct Inode *Parent, const char *Name);
int (*SymLink)(struct Inode *Parent, const char *Name, const char *Target, struct Inode **Result);
ssize_t (*ReadLink)(struct Inode *Node, char *Buffer, size_t Size);
off_t (*Seek)(struct Inode *Node, off_t Offset);
int (*Stat)(struct Inode *Node, struct kstat *Stat);
} __attribute__((packed));
#define I_FLAG_ROOT 0x1
#define I_FLAG_MOUNTPOINT 0x2
#define I_FLAG_CACHE_KEEP 0x4
struct FileSystemInfo;
struct SuperBlockOperations
{
int (*AllocateInode)(struct FileSystemInfo *Info, struct Inode **Result);
int (*DeleteInode)(struct FileSystemInfo *Info, struct Inode *Node);
/**
* Synchronize the filesystem.
*
* Write all pending changes to the disk.
*
* @param Info Inode to synchronize. If NULL, synchronize all inodes.
*
* @return Zero on success, otherwise an error code.
*/
int (*Synchronize)(struct FileSystemInfo *Info, struct Inode *Node);
/**
* Destroy the filesystem.
*
* Unregister the filesystem and free all resources.
*
* @param Info Filesystem to destroy.
*
* @return Zero on success, otherwise an error code.
*/
int (*Destroy)(struct FileSystemInfo *Info);
} __attribute__((packed));
struct FileSystemInfo
{
const char *Name;
const char *RootName;
int Flags;
struct SuperBlockOperations SuperOps;
struct InodeOperations Ops;
void *PrivateData;
} __attribute__((packed));
dev_t RegisterFileSystem(struct FileSystemInfo *Info, struct Inode *Root);
int UnregisterFileSystem(dev_t Device);
#endif // !__FENNIX_API_FILESYSTEM_H__

View File

@ -1,66 +1,234 @@
/*
This file is part of Fennix Drivers.
This file is part of Fennix Kernel.
Fennix Drivers is free software: you can redistribute it and/or
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 Drivers is distributed in the hope that it will be useful,
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 Drivers. If not, see <https://www.gnu.org/licenses/>.
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_INPUT_H__
#define __FENNIX_API_INPUT_H__
#include <types.h>
#include <driver.h>
#if __has_include(<interface/device.h>)
#include <interface/device.h>
#else
#include <device.h>
#endif
struct InodeOperations;
typedef enum
{
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_0,
KEY_Q,
KEY_W,
KEY_E,
KEY_R,
KEY_T,
KEY_Y,
KEY_U,
KEY_I,
KEY_O,
KEY_P,
KEY_A,
KEY_S,
KEY_D,
KEY_F,
KEY_G,
KEY_H,
KEY_J,
KEY_K,
KEY_L,
KEY_Z,
KEY_X,
KEY_C,
KEY_V,
KEY_B,
KEY_N,
KEY_M,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEYPAD_7,
KEYPAD_8,
KEYPAD_9,
KEYPAD_MINUS,
KEYPAD_4,
KEYPAD_5,
KEYPAD_6,
KEYPAD_PLUS,
KEYPAD_1,
KEYPAD_2,
KEYPAD_3,
KEYPAD_0,
KEYPAD_PERIOD,
KEYPAD_RETURN,
KEYPAD_ASTERISK,
KEYPAD_SLASH,
KEY_LEFT_CTRL,
KEY_RIGHT_CTRL,
KEY_LEFT_SHIFT,
KEY_RIGHT_SHIFT,
KEY_LEFT_ALT,
KEY_RIGHT_ALT,
KEY_ESCAPE,
KEY_MINUS,
KEY_EQUAL,
KEY_BACKSPACE,
KEY_TAB,
KEY_LEFT_BRACKET,
KEY_RIGHT_BRACKET,
KEY_RETURN,
KEY_SEMICOLON,
KEY_APOSTROPHE,
KEY_BACK_TICK,
KEY_BACKSLASH,
KEY_COMMA,
KEY_PERIOD,
KEY_SLASH,
KEY_SPACE,
KEY_CAPS_LOCK,
KEY_NUM_LOCK,
KEY_SCROLL_LOCK,
KEY_PRINT_SCREEN,
KEY_HOME,
KEY_UP_ARROW,
KEY_LEFT_ARROW,
KEY_RIGHT_ARROW,
KEY_DOWN_ARROW,
KEY_PAGE_UP,
KEY_PAGE_DOWN,
KEY_END,
KEY_INSERT,
KEY_DELETE,
KEY_LEFT_GUI,
KEY_RIGHT_GUI,
KEY_APPS,
KEY_MULTIMEDIA_PREV_TRACK,
KEY_MULTIMEDIA_NEXT_TRACK,
KEY_MULTIMEDIA_MUTE,
KEY_MULTIMEDIA_CALCULATOR,
KEY_MULTIMEDIA_PLAY,
KEY_MULTIMEDIA_STOP,
KEY_MULTIMEDIA_VOL_DOWN,
KEY_MULTIMEDIA_VOL_UP,
KEY_MULTIMEDIA_WWW_HOME,
KEY_MULTIMEDIA_WWW_SEARCH,
KEY_MULTIMEDIA_WWW_FAVORITES,
KEY_MULTIMEDIA_WWW_REFRESH,
KEY_MULTIMEDIA_WWW_STOP,
KEY_MULTIMEDIA_WWW_FORWARD,
KEY_MULTIMEDIA_WWW_BACK,
KEY_MULTIMEDIA_MY_COMPUTER,
KEY_MULTIMEDIA_EMAIL,
KEY_MULTIMEDIA_MEDIA_SELECT,
KEY_ACPI_POWER,
KEY_ACPI_SLEEP,
KEY_ACPI_WAKE,
KEY_PRESSED = 0x80,
} KeyScanCodes;
typedef struct
{
union
{
struct
{
uint8_t LeftButton : 1;
uint8_t RightButton : 1;
uint8_t MiddleButton : 1;
uint8_t Button4 : 1;
uint8_t Button5 : 1;
};
uint8_t Buttons;
};
KeyScanCodes Key;
} KeyboardReport;
/**
* @note Ignored if is absolute
*/
int X;
/**
* @note Ignored if is absolute
*/
int Y;
typedef struct
{
long X, Y;
int8_t Z;
uint8_t Absolute : 1;
uint8_t LeftButton : 1;
uint8_t RightButton : 1;
uint8_t MiddleButton : 1;
uint8_t Button4 : 1;
uint8_t Button5 : 1;
uint8_t Button6 : 1;
uint8_t Button7 : 1;
uint8_t Button8 : 1;
} MouseReport;
#ifdef __cplusplus
extern "C"
typedef struct
{
#endif // __cplusplus
} JoystickReport;
dev_t RegisterInputDevice(DeviceDriverType Type);
int UnregisterInputDevice(dev_t DeviceID, DeviceDriverType Type);
int ReportKeyboardEvent(dev_t DeviceID, KeyScanCodes ScanCode, uint8_t Pressed);
int ReportRelativeMouseEvent(dev_t DeviceID, MouseReport Report);
int ReportAbsoluteMouseEvent(dev_t DeviceID, MouseReport Report, uintptr_t X, uintptr_t Y);
typedef struct
{
uint16_t X, Y;
uint8_t Pressure;
} TouchScreenReport;
#ifdef __cplusplus
}
#endif // __cplusplus
typedef struct
{
} GamepadReport;
typedef struct
{
} AccelerometerReport;
typedef struct
{
} GyroscopeReport;
typedef struct
{
} MagnetometerReport;
typedef struct
{
DeviceType Type;
dev_t Device;
union
{
KeyboardReport Keyboard;
MouseReport Mouse;
JoystickReport Joystick;
TouchScreenReport TouchScreen;
GamepadReport Gamepad;
AccelerometerReport Accelerometer;
GyroscopeReport Gyroscope;
MagnetometerReport Magnetometer;
/* ... */
};
} InputReport;
EXTERNC int ReportInputEvent(InputReport *Report);
#endif // !__FENNIX_API_INPUT_H__

View File

@ -1,47 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_AUDIO_H__
#define __FENNIX_API_AUDIO_H__
#include <types.h>
#include <driver.h>
typedef int (*drvOpen_t)(dev_t, dev_t, int, mode_t);
typedef int (*drvClose_t)(dev_t, dev_t);
typedef size_t (*drvRead_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
typedef size_t (*drvWrite_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
typedef int (*drvIoctl_t)(dev_t, dev_t, unsigned long, void *);
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
dev_t RegisterNetDevice(DeviceDriverType Type,
drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
int UnregisterNetDevice(dev_t DeviceID, DeviceDriverType Type);
int ReportNetworkPacket(dev_t DeviceID, void *Buffer, size_t Size);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !__FENNIX_API_AUDIO_H__

29
include/network.h Normal file
View File

@ -0,0 +1,29 @@
/*
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_API_NETWORK_H__
#define __FENNIX_API_NETWORK_H__
#include <types.h>
#if __has_include(<interface/device.h>)
#include <interface/device.h>
#else
#include <device.h>
#endif
#endif // !__FENNIX_API_NETWORK_H__

View File

@ -21,7 +21,7 @@
#include <types.h>
/* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */
enum PCICommands
typedef enum
{
/** @brief Enable response in I/O space */
PCI_COMMAND_IO = 0x1,
@ -45,7 +45,7 @@ enum PCICommands
PCI_COMMAND_FAST_BACK = 0x200,
/** @brief INTx Emulation Disable */
PCI_COMMAND_INTX_DISABLE = 0x400
};
} PCI_COMMANDS;
typedef struct
{
@ -171,7 +171,7 @@ extern "C"
{
#endif
PCIArray *FindPCIDevices(uint16_t Vendors[], uint16_t Devices[]);
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);

View File

@ -21,6 +21,7 @@
#include <types.h>
#if defined(__amd64__)
typedef struct
{
uint64_t r15; // General purpose
@ -49,8 +50,10 @@ typedef struct
uint64_t rsp; // Stack Pointer
uint64_t ss; // Stack Segment
} TrapFrame;
#elif defined(__i386__)
typedef struct TrapFrame
typedef struct
{
uint32_t edi; // Destination index for string operations
uint32_t esi; // Source index for string operations
@ -71,8 +74,10 @@ typedef struct TrapFrame
uint32_t r3_esp; // Stack Pointer
uint32_t r3_ss; // Stack Segment
} TrapFrame;
#elif defined(__aarch64__)
typedef struct TrapFrame
typedef struct
{
uint64_t x19; // General purpose
uint64_t x20; // General purpose
@ -95,6 +100,7 @@ typedef struct TrapFrame
uint64_t InterruptNumber /* iar_el1 */; // Interrupt Acknowledge Register
} TrapFrame;
#endif
#endif // !__FENNIX_API_REGISTERS_H__

View File

@ -1,231 +0,0 @@
/*
BSD 3-Clause License
Copyright (c) 2023, EnderIce2
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FENNIX_KERNEL_SYSCALLS_LIST_H__
#define __FENNIX_KERNEL_SYSCALLS_LIST_H__
/* mmap */
#define sc_PROT_NONE 0
#define sc_PROT_READ 1
#define sc_PROT_WRITE 2
#define sc_PROT_EXEC 4
#define sc_MAP_SHARED 1
#define sc_MAP_PRIVATE 2
#define sc_MAP_FIXED 4
#define sc_MAP_ANONYMOUS 8
/* lseek */
#define sc_SEEK_SET 0
#define sc_SEEK_CUR 1
#define sc_SEEK_END 2
/**
* Enumeration of all the native syscalls
* available in the kernel
*/
typedef enum
{
/**
* This syscall is used to exit the current
* process with the provided exit code.
*
* @fn void exit(int status);
*
* @param Code The exit code
* @return This syscall does not return
*
* @note No permissions are required to call
* this syscall
*/
sc_exit = 0,
/**
* Map pages of memory
*
* @fn void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
*/
sc_mmap,
/**
* Unmap pages of memory
*
* @fn int munmap(void *addr, size_t len);
*/
sc_munmap,
/**
* Change the protection of a page of memory
*
* @fn int mprotect(void *addr, size_t len, int prot);
*/
sc_mprotect,
/**
* Open a file
*
* @fn int open(const char *path, int oflag, ... );
*/
sc_open,
/**
* Close a file descriptor
*
* @fn int close(int fildes);
*/
sc_close,
/**
* Read from a file descriptor
*
* @fn ssize_t read(int fildes, void *buf, size_t nbyte);
*/
sc_read,
/**
* Write to a file descriptor
*
* @fn ssize_t write(int fildes, const void *buf, size_t nbyte);
*/
sc_write,
/**
* Seek to a position in a file descriptor
*
* @fn off_t lseek(int fildes, off_t offset, int whence);
*/
sc_lseek,
/**
* Create a new process
*
* @fn pid_t fork(void);
*/
sc_fork,
/** Not a real syscall */
sc_MaxSyscall
} NativeSyscalls;
#ifndef syscall0
static inline long syscall0(long syscall)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall1
static inline long syscall1(long syscall, long arg1)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall2
static inline long syscall2(long syscall, long arg1, long arg2)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall3
static inline long syscall3(long syscall, long arg1, long arg2, long arg3)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall4
static inline long syscall4(long syscall, long arg1, long arg2, long arg3, long arg4)
{
long ret;
register long r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall5
static inline long syscall5(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall6
static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
register long r9 __asm__("r9") = arg6;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
return ret;
}
#endif
#endif // !__FENNIX_KERNEL_SYSCALLS_LIST_H__

111
include/syscalls.h Normal file
View File

@ -0,0 +1,111 @@
/*
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_API_SYSCALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_LIST_H__
#ifndef syscall0
static inline long syscall0(long syscall)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall1
static inline long syscall1(long syscall, long arg1)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall2
static inline long syscall2(long syscall, long arg1, long arg2)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall3
static inline long syscall3(long syscall, long arg1, long arg2, long arg3)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall4
static inline long syscall4(long syscall, long arg1, long arg2, long arg3, long arg4)
{
long ret;
register long r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall5
static inline long syscall5(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall6
static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
register long r9 __asm__("r9") = arg6;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
return ret;
}
#endif
#endif // !__FENNIX_API_SYSCALLS_LIST_H__

View File

@ -53,11 +53,41 @@ typedef __UINTMAX_TYPE__ uintmax_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __SIZE_TYPE__ size_t;
typedef intptr_t ssize_t;
typedef __SIZE_TYPE__ dev_t;
typedef __SIZE_TYPE__ off_t;
#if defined(__LP64__)
typedef int64_t off_t;
typedef int64_t off64_t;
typedef uint32_t mode_t;
typedef uint64_t dev_t;
typedef uint64_t ino64_t;
typedef uint64_t ino_t;
typedef uint32_t nlink_t;
typedef int64_t blksize_t;
typedef int64_t blkcnt_t;
typedef int64_t blkcnt64_t;
typedef int64_t time_t;
typedef uint32_t uid_t;
typedef uint32_t gid_t;
typedef int64_t clock_t;
typedef int32_t pid_t;
#elif defined(__LP32__)
typedef int32_t off_t;
typedef long long off64_t;
typedef __INT32_TYPE__ mode_t;
typedef int32_t dev_t;
typedef int32_t ino64_t;
typedef int32_t ino_t;
typedef unsigned int nlink_t;
typedef int blksize_t;
typedef int32_t blkcnt_t;
typedef int32_t blkcnt64_t;
typedef int32_t time_t;
typedef unsigned uid_t;
typedef unsigned gid_t;
typedef long clock_t;
typedef int pid_t;
#endif
#define UNUSED(x) (void)(x)
@ -108,4 +138,49 @@ typedef __builtin_va_list va_list;
#define TO_PAGES(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE)
#define FROM_PAGES(d) ((d) * PAGE_SIZE)
#define __unused __attribute__((unused))
#define __packed __attribute__((packed))
#define __naked __attribute__((naked))
#define __aligned(x) __attribute__((aligned(x)))
#define __section(x) __attribute__((section(x)))
#define __noreturn __attribute__((noreturn))
#define __weak __attribute__((weak))
#define __alias(x) __attribute__((alias(x)))
#define __always_inline __attribute__((always_inline))
#define __noinline __attribute__((noinline))
#define __pure __attribute__((pure))
#define __const __attribute__((const))
#define __malloc __attribute__((malloc))
#define __returns_twice __attribute__((returns_twice))
#define __used __attribute__((used))
#define __deprecated __attribute__((deprecated))
#define __deprecated_msg(x) __attribute__((deprecated(x)))
#define __weakref(x) __attribute__((weakref(x)))
#define __weakrefalias(x) __attribute__((weakref(#x)))
#define __visibility(x) __attribute__((visibility(x)))
#define __constructor __attribute__((constructor))
#define __destructor __attribute__((destructor))
#define __cleanup(x) __attribute__((cleanup(x)))
#define __fallthrough __attribute__((fallthrough))
#define __nonnull(x) __attribute__((nonnull x))
#define __nonnull_all __attribute__((nonnull))
#define __returns_nonnull __attribute__((returns_nonnull))
#define __sentinel __attribute__((sentinel))
#define __sentinel_all __attribute__((sentinel(0)))
#define __format(x, y, z) __attribute__((format(x, y, z)))
#define __format_arg(x) __attribute__((format_arg(x)))
#define __nonnull_params(x) __attribute__((nonnull x))
#define __nonnull_all __attribute__((nonnull))
#define __warn_unused_result __attribute__((warn_unused_result))
#define __no_stack_protector __attribute__((no_stack_protector))
#define __no_instrument_function __attribute__((no_instrument_function))
#define __no_debug __attribute__((no_debug))
#define __target(x) __attribute__((target(x)))
#define __min_vector_width(x) __attribute__((min_vector_width(x)))
#define __sync __sync_synchronize()
#define __unreachable __builtin_unreachable()
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif // !__FENNIX_API_TYPES_H__

View File

@ -1,83 +1,22 @@
# Config file
# Config files
include ../../../Makefile.conf
FILENAME = aip.drv
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver
LDFLAGS := \
-fPIC -fPIE -pie \
-Wl,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared -fvisibility=hidden
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
FILENAME = aip.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -19,6 +19,7 @@
#include <driver.h>
#include <errno.h>
#include <fs.h>
#include <input.h>
#include <base.h>
#include <io.h>
@ -161,6 +162,17 @@ const unsigned short ScanCodeSet3[] = {
[0x4B] = KEY_L,
[0x4D] = KEY_P};
InputReport kir = {0};
int ReportKeyboardEvent(dev_t Device, KeyScanCodes ScanCode, uint8_t Pressed)
{
kir.Type = INPUT_TYPE_KEYBOARD;
kir.Device = Device;
kir.Keyboard.Key = ScanCode;
kir.Keyboard.Key |= Pressed ? KEY_PRESSED : 0;
ReportInputEvent(&kir);
return 0;
}
bool IsE0 = false;
bool IsE1 = false;
void PS2KbdInterruptHandler(TrapFrame *)
@ -217,12 +229,21 @@ void PS2KbdInterruptHandler(TrapFrame *)
{
if (IsE0)
IsE0 = false;
Log("Unknown PS/2 Keyboard Scan Code Set: %#x", KeyboardScanCodeSet);
KernelLog("Unknown PS/2 Keyboard Scan Code Set: %#x", KeyboardScanCodeSet);
break;
}
}
}
int __fs_kb_Ioctl(struct Inode *, unsigned long, void *)
{
return 0;
}
const struct InodeOperations KbdOps = {
.Ioctl = __fs_kb_Ioctl,
};
int InitializeKeyboard()
{
// PS2WriteData(PS2_KBD_CMD_RESET);
@ -230,45 +251,50 @@ int InitializeKeyboard()
// if (test != PS2_KBD_RESP_TEST_PASSED &&
// test != PS2_KBD_RESP_ACK)
// {
// Log("PS/2 keyboard reset failed (%#x)", test);
// KernelLog("PS/2 keyboard reset failed (%#x)", test);
// return -EFAULT;
// }
PS2WriteData(PS2_KBD_CMD_DEFAULTS);
if (PS2ACKTimeout() != 0)
Log("PS/2 keyboard failed to set defaults");
KernelLog("PS/2 keyboard failed to set defaults");
PS2WriteData(PS2_KBD_CMD_SCAN_CODE_SET);
if (PS2ACKTimeout() != 0)
Log("PS/2 keyboard failed to set scan code set");
KernelLog("PS/2 keyboard failed to set scan code set");
/* We want Scan Code Set 1 */
PS2WriteData(PS2_KBD_SCAN_CODE_SET_2); /* It will set to 1 but with translation? */
if (PS2ACKTimeout() != 0)
Log("PS/2 keyboard failed to set scan code set 2");
KernelLog("PS/2 keyboard failed to set scan code set 2");
PS2WriteData(PS2_KBD_CMD_SCAN_CODE_SET);
if (PS2ACKTimeout() != 0)
Log("PS/2 keyboard failed to set scan code set");
KernelLog("PS/2 keyboard failed to set scan code set");
PS2WriteData(PS2_KBD_SCAN_CODE_GET_CURRENT);
if (PS2ACKTimeout() != 0)
Log("PS/2 keyboard failed to get current scan code set");
KernelLog("PS/2 keyboard failed to get current scan code set");
KeyboardScanCodeSet = PS2ReadAfterACK();
Log("PS/2 Keyboard Scan Code Set: 0x%X", KeyboardScanCodeSet);
KernelLog("PS/2 Keyboard Scan Code Set: 0x%X", KeyboardScanCodeSet);
PS2ClearOutputBuffer();
PS2WriteData(PS2_KBD_CMD_ENABLE_SCANNING);
RegisterInterruptHandler(1, PS2KbdInterruptHandler);
KeyboardDevID = RegisterInputDevice(ddt_Keyboard);
KeyboardDevID = RegisterDevice(INPUT_TYPE_KEYBOARD, &KbdOps);
return 0;
}
int FinalizeKeyboard()
{
UnregisterInputDevice(KeyboardDevID, ddt_Keyboard);
PS2WriteData(PS2_KBD_CMD_DISABLE_SCANNING);
if (PS2ACKTimeout() != 0)
KernelLog("PS/2 keyboard failed to disable scanning");
UnregisterDevice(KeyboardDevID);
return 0;
}
@ -276,11 +302,11 @@ int DetectPS2Keyboard()
{
PS2WriteData(PS2_KBD_CMD_DISABLE_SCANNING);
if (PS2ACKTimeout() != 0)
Log("PS/2 keyboard failed to disable scanning");
KernelLog("PS/2 keyboard failed to disable scanning");
PS2WriteData(PS2_KBD_CMD_IDENTIFY);
if (PS2ACKTimeout() != 0)
Log("PS/2 keyboard failed to identify");
KernelLog("PS/2 keyboard failed to identify");
uint8_t recByte;
int timeout = 1000000;
@ -300,10 +326,10 @@ int DetectPS2Keyboard()
break;
}
if (timeout == 0)
Log("PS/2 keyboard second byte timed out");
KernelLog("PS/2 keyboard second byte timed out");
else
Device1ID[1] = recByte;
Log("PS2 Keyboard Device: 0x%X 0x%X", Device1ID[0], Device1ID[1]);
KernelLog("PS2 Keyboard Device: 0x%X 0x%X", Device1ID[0], Device1ID[1]);
return 0;
}

View File

@ -104,7 +104,7 @@ int DriverEntry()
DualChannel = cfg.Port2Clock;
if (DualChannel)
Log("Dual channel PS/2 controller detected");
KernelLog("Dual channel PS/2 controller detected");
cfg.Port1Interrupt = 1;
cfg.Port2Interrupt = 1;
cfg.Port1Translation = 1;
@ -116,7 +116,7 @@ int DriverEntry()
uint8_t test = PS2ReadData();
if (test != PS2_TEST_PASSED)
{
Log("PS/2 controller self test failed (%#x)", test);
KernelLog("PS/2 controller self test failed (%#x)", test);
return -EFAULT;
}
@ -137,7 +137,7 @@ int DriverEntry()
test = PS2ReadData();
if (test != 0x00)
{
Log("PS/2 Port 1 self test failed (%#x)", test);
KernelLog("PS/2 Port 1 self test failed (%#x)", test);
return -EFAULT;
}
@ -147,7 +147,7 @@ int DriverEntry()
test = PS2ReadData();
if (test != 0x00)
{
Log("PS/2 Port 2 self test failed (%#x)", test);
KernelLog("PS/2 Port 2 self test failed (%#x)", test);
return -EFAULT;
}
}
@ -204,7 +204,7 @@ int DriverProbe()
{
if (!IsKeyboard(Device1ID[0]))
{
Log("PS/2 Port 1 is not a keyboard");
KernelLog("PS/2 Port 1 is not a keyboard");
// return -EINVAL;
}
}
@ -213,15 +213,15 @@ int DriverProbe()
{
if (!IsMouse(Device2ID[0]))
{
Log("PS/2 Port 2 is not a mouse");
KernelLog("PS/2 Port 2 is not a mouse");
// return -EINVAL;
}
}
KPrint("PS/2 Port 1: %s (0x%X 0x%X)",
KernelPrint("PS/2 Port 1: %s (0x%X 0x%X)",
GetPS2DeviceName(Device1ID[0], Device1ID[1]),
Device1ID[0], Device1ID[1]);
KPrint("PS/2 Port 2: %s (0x%X 0x%X)",
KernelPrint("PS/2 Port 2: %s (0x%X 0x%X)",
GetPS2DeviceName(Device2ID[0], Device2ID[1]),
Device2ID[0], Device2ID[1]);
return 0;
@ -230,5 +230,5 @@ int DriverProbe()
DriverInfo("aip",
"Advanced Integrated Peripheral Driver",
"EnderIce2",
"0.1",
0, 0, 1,
"GPLv3");

View File

@ -18,8 +18,9 @@
#include "aip.h"
#include <errno.h>
#include <input.h>
#include <base.h>
#include <fs.h>
#include <input.h>
dev_t MouseDevID = -1;
bool PacketReady = false;
@ -28,6 +29,7 @@ bool MouseButton45 = false;
uint8_t Cycle = 0;
PS2_MOUSE_PACKET Packet = {0};
InputReport mir = {0};
void PS2MouseInterruptHandler(TrapFrame *)
{
uint8_t data = PS2ReadData();
@ -114,18 +116,17 @@ void PS2MouseInterruptHandler(TrapFrame *)
if (Packet.Base.YOverflow)
Y = 0;
MouseReport mr = {
.LeftButton = Packet.Base.LeftButton,
.RightButton = Packet.Base.RightButton,
.MiddleButton = Packet.Base.MiddleButton,
.Button4 = Packet.ZMovement.Button4,
.Button5 = Packet.ZMovement.Button5,
.X = X,
.Y = -Y,
.Z = Packet.ZMovement.Z,
};
ReportRelativeMouseEvent(MouseDevID, mr);
mir.Type = INPUT_TYPE_MOUSE;
mir.Device = MouseDevID;
mir.Mouse.LeftButton = Packet.Base.LeftButton;
mir.Mouse.RightButton = Packet.Base.RightButton;
mir.Mouse.MiddleButton = Packet.Base.MiddleButton;
mir.Mouse.Button4 = Packet.ZMovement.Button4;
mir.Mouse.Button5 = Packet.ZMovement.Button5;
mir.Mouse.X = X;
mir.Mouse.Y = -Y;
mir.Mouse.Z = Packet.ZMovement.Z;
ReportInputEvent(&mir);
PacketReady = false;
}
@ -140,6 +141,15 @@ void MouseSampleRate(uint8_t SampleRate)
PS2ReadData();
}
int __fs_ms_Ioctl(struct Inode *, unsigned long, void *)
{
return 0;
}
const struct InodeOperations MouseOps = {
.Ioctl = __fs_ms_Ioctl,
};
int InitializeMouse()
{
PS2WriteData(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
@ -148,12 +158,13 @@ int InitializeMouse()
if (test != PS2_MOUSE_RESP_TEST_PASSED &&
test != PS2_MOUSE_RESP_ACK)
{
Log("PS/2 mouse reset failed! (%#x)", test);
KernelLog("PS/2 mouse reset failed! (%#x)", test);
return -EFAULT;
}
RegisterInterruptHandler(12, PS2MouseInterruptHandler);
MouseDevID = RegisterInputDevice(ddt_Mouse);
MouseDevID = RegisterDevice(INPUT_TYPE_MOUSE, &MouseOps);
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
PS2WriteData(PS2_MOUSE_CMD_SET_DEFAULTS);
@ -169,7 +180,7 @@ int InitializeMouse()
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
PS2WriteData(PS2_MOUSE_CMD_READ_ID);
uint8_t Device2ID = PS2ReadData();
Log("PS/2 Mouse ID: %#x", Device2ID);
KernelLog("PS/2 Mouse ID: %#x", Device2ID);
MouseSampleRate(200);
MouseSampleRate(200);
@ -178,7 +189,7 @@ int InitializeMouse()
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
PS2WriteData(PS2_MOUSE_CMD_READ_ID);
Device2ID = PS2ReadData();
Log("PS/2 Mouse ID: %#x", Device2ID);
KernelLog("PS/2 Mouse ID: %#x", Device2ID);
if (Device2ID >= 3 && Device2ID <= 4)
FourPackets = true;
@ -190,10 +201,10 @@ int InitializeMouse()
int FinalizeMouse()
{
UnregisterInputDevice(MouseDevID, ddt_Mouse);
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
PS2WriteData(PS2_MOUSE_CMD_DISABLE_DATA_REPORTING);
UnregisterDevice(MouseDevID);
return 0;
}
@ -202,12 +213,12 @@ int DetectPS2Mouse()
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
PS2WriteData(PS2_MOUSE_CMD_DISABLE_DATA_REPORTING);
if (PS2ACKTimeout() != 0)
Log("PS/2 mouse failed to disable data reporting!");
KernelLog("PS/2 mouse failed to disable data reporting!");
PS2WriteCommand(PS2_CMD_WRITE_NEXT_BYTE_TO_PS2_PORT_2_INPUT);
PS2WriteData(PS2_MOUSE_CMD_READ_ID);
if (PS2ACKTimeout() != 0)
Log("PS/2 mouse failed to read ID!");
KernelLog("PS/2 mouse failed to read ID!");
uint8_t recByte;
int timeout = 1000000;
@ -228,6 +239,6 @@ int DetectPS2Mouse()
}
Device2ID[1] = recByte;
Log("PS2 Mouse Device: 0x%X 0x%X", Device2ID[0], Device2ID[1]);
KernelLog("PS2 Mouse Device: 0x%X 0x%X", Device2ID[0], Device2ID[1]);
return 0;
}

View File

@ -1,7 +1,7 @@
# Config file
include ../../Makefile.conf
FILENAME = libdriver.a
FILENAME = libkernel.so
CC = ../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
@ -17,15 +17,12 @@ OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURC
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../include
LDFLAGS := \
-fPIC -fPIE -pie \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map driver.map -static -fvisibility=hidden
LDFLAGS := -fPIC -fPIE -pie -nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 -Wl,-Map libkernel.map -shared
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
CFLAGS := -I$(INCLUDE_DIR) -shared
ifeq ($(OSARCH), amd64)
@ -46,25 +43,29 @@ CFLAGS += -pipe -fno-builtin -fPIC
endif
CRT_CFLAGS := -fPIC -fPIE -pie -mno-red-zone -std=c++20 -I../include
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
CRT_CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
CRT_CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
CRT_CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
build: $(FILENAME)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -shared -c crt/crt0.c -o dcrt0.o
$(CPP) $(CRT_CFLAGS) -c crt/crt0.cpp -o dcrt0.o
mv dcrt0.o ../out/dcrt0.o
$(FILENAME): $(OBJ)
$(info Linking $@)
$(AR) rcs $@ $(OBJ)
mv $(FILENAME) ../out/$(FILENAME)
$(CC) $(LDFLAGS) $(OBJ) -o ../out/$(FILENAME)
%.o: %.c $(HEADERS)
$(info Compiling $<)
@ -79,4 +80,4 @@ $(FILENAME): $(OBJ)
$(AS) -o $@ $<
clean:
rm -f driver.map $(OBJ) $(FILENAME) $(STACK_USAGE_OBJ) dcrt0.su
rm -f libkernel.map $(OBJ) $(FILENAME) $(STACK_USAGE_OBJ) dcrt0.su

View File

@ -1,146 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <aip.h>
#include <errno.h>
#include <io.h>
extern void Log(const char *Format, ...);
void PIC_EOI(uint8_t IRQ)
{
if (IRQ >= 8)
outb(PIC2_CMD, _PIC_EOI);
outb(PIC1_CMD, _PIC_EOI);
}
void IRQ_MASK(uint8_t IRQ)
{
uint16_t port;
uint8_t value;
if (IRQ < 8)
port = PIC1_DATA;
else
{
port = PIC2_DATA;
IRQ -= 8;
}
value = inb(port) | (1 << IRQ);
outb(port, value);
}
void IRQ_UNMASK(uint8_t IRQ)
{
uint16_t port;
uint8_t value;
if (IRQ < 8)
port = PIC1_DATA;
else
{
port = PIC2_DATA;
IRQ -= 8;
}
value = inb(port) & ~(1 << IRQ);
outb(port, value);
}
void PS2Wait(const bool Output)
{
int Timeout = 100000;
PS2_STATUSES Status = {.Raw = inb(PS2_STATUS)};
while (Timeout--)
{
if (!Output) /* FIXME: Reverse? */
{
if (Status.OutputBufferFull == 0)
return;
}
else
{
if (Status.InputBufferFull == 0)
return;
}
Status.Raw = inb(PS2_STATUS);
}
Log("PS/2 controller timeout! (Status: %#x, %d)", Status, Output);
}
void PS2WriteCommand(uint8_t Command)
{
WaitInput;
outb(PS2_CMD, Command);
}
void PS2WriteData(uint8_t Data)
{
WaitInput;
outb(PS2_DATA, Data);
}
uint8_t PS2ReadData()
{
WaitOutput;
return inb(PS2_DATA);
}
uint8_t PS2ReadStatus()
{
WaitOutput;
return inb(PS2_STATUS);
}
uint8_t PS2ReadAfterACK()
{
uint8_t ret = PS2ReadData();
while (ret == PS2_ACK)
{
WaitOutput;
ret = inb(PS2_DATA);
}
return ret;
}
void PS2ClearOutputBuffer()
{
PS2_STATUSES Status;
int timeout = 0x500;
while (timeout--)
{
Status.Raw = inb(PS2_STATUS);
if (Status.OutputBufferFull == 0)
return;
inb(PS2_DATA);
}
}
int PS2ACKTimeout()
{
int timeout = 0x500;
while (timeout > 0)
{
if (PS2ReadData() == PS2_ACK)
return 0;
timeout--;
}
return -ETIMEDOUT;
}

View File

@ -1,31 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <audio.h>
extern __driverAPI *API;
dev_t RegisterAudioDevice(DeviceDriverType Type, drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
{
return API->RegisterAudioDevice(API->MajorID, Type, Open, Close, Read, Write, Ioctl);
}
int UnregisterAudioDevice(dev_t DeviceID, DeviceDriverType Type)
{
return API->UnregisterAudioDevice(API->MajorID, DeviceID, Type);
}

View File

@ -1,182 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <base.h>
#include <driver.h>
#include <errno.h>
__driverAPI *API = NULL;
int RegisterInterruptHandler(uint8_t IRQ, void *Handler)
{
if (Handler == NULL)
return -EINVAL;
return API->RegisterInterruptHandler(API->MajorID,
IRQ,
Handler);
}
int OverrideInterruptHandler(uint8_t IRQ, void *Handler)
{
if (Handler == NULL)
return -EINVAL;
return API->OverrideInterruptHandler(API->MajorID,
IRQ,
Handler);
}
int UnregisterInterruptHandler(uint8_t IRQ, void *Handler)
{
if (Handler == NULL)
return -EINVAL;
return API->UnregisterInterruptHandler(API->MajorID,
IRQ,
Handler);
}
int UnregisterAllInterruptHandlers(void *Handler)
{
if (Handler == NULL)
return -EINVAL;
return API->UnregisterAllInterruptHandlers(API->MajorID,
Handler);
}
void *AllocateMemory(size_t Pages)
{
if (Pages == 0)
return NULL;
return API->RequestPages(API->MajorID,
Pages);
}
void FreeMemory(void *Pointer, size_t Pages)
{
if (Pointer == NULL || Pages == 0)
return;
API->FreePages(API->MajorID,
Pointer,
Pages);
}
void AppendMapFlag(void *Address, PageMapFlags Flag)
{
API->AppendMapFlag(API->MajorID,
Address,
Flag);
}
void RemoveMapFlag(void *Address, PageMapFlags Flag)
{
API->RemoveMapFlag(API->MajorID,
Address,
Flag);
}
void MapPages(void *PhysicalAddress, void *VirtualAddress, size_t Pages, uint32_t Flags)
{
API->MapPages(API->MajorID,
PhysicalAddress,
VirtualAddress,
Pages,
Flags);
}
void UnmapPages(void *VirtualAddress, size_t Pages)
{
API->UnmapPages(API->MajorID,
VirtualAddress,
Pages);
}
void KPrint(const char *Format, ...)
{
va_list Args;
va_start(Args, Format);
API->KPrint(API->MajorID,
Format,
Args);
va_end(Args);
}
void Log(const char *Format, ...)
{
va_list Args;
va_start(Args, Format);
API->KernelLog(API->MajorID,
Format,
Args);
va_end(Args);
}
CriticalState EnterCriticalSection()
{
CriticalState cs;
#if defined(__i386__) || defined(__x86_64__)
uintptr_t Flags;
#if defined(__x86_64__)
asmv("pushfq");
asmv("popq %0"
: "=r"(Flags));
#else
asmv("pushfl");
asmv("popl %0"
: "=r"(Flags));
#endif
cs = Flags & (1 << 9);
asmv("cli");
#elif defined(__arm__) || defined(__aarch64__)
uintptr_t Flags;
asmv("mrs %0, cpsr"
: "=r"(Flags));
cs = Flags & (1 << 7);
asmv("cpsid i");
#endif
return cs;
}
void LeaveCriticalSection(CriticalState PreviousState)
{
#if defined(__i386__) || defined(__x86_64__)
if (PreviousState)
asmv("sti");
#elif defined(__arm__) || defined(__aarch64__)
if (PreviousState)
asmv("cpsie i");
#endif
}

94
library/base.cpp Normal file
View File

@ -0,0 +1,94 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <base.h>
#include <driver.h>
#include <errno.h>
#include <fs.h>
extern "C" dev_t DriverID;
#define KernelFunction(Name) \
extern "C" __attribute__((naked, used)) long \
__##Name(dev_t, long, long, long, \
long, long, long) { return 0; }
void *operator new(__SIZE_TYPE__) { return (void *)1; }
void *operator new[](__SIZE_TYPE__) { return (void *)1; }
void operator delete(void *) {}
void operator delete[](void *) {}
void operator delete(void *, __SIZE_TYPE__) {}
void operator delete[](void *, __SIZE_TYPE__) {}
KernelFunction(KernelPrint);
KernelFunction(KernelLog);
KernelFunction(RegisterInterruptHandler);
KernelFunction(OverrideInterruptHandler);
KernelFunction(UnregisterInterruptHandler);
KernelFunction(UnregisterAllInterruptHandlers);
KernelFunction(AllocateMemory);
KernelFunction(FreeMemory);
KernelFunction(AppendMapFlag);
KernelFunction(RemoveMapFlag);
KernelFunction(MapPages);
KernelFunction(UnmapPages);
KernelFunction(MemoryCopy);
KernelFunction(MemorySet);
KernelFunction(MemoryMove);
KernelFunction(StringLength);
KernelFunction(strstr);
KernelFunction(EnterCriticalSection);
KernelFunction(LeaveCriticalSection);
KernelFunction(CreateKernelProcess);
KernelFunction(CreateKernelThread);
KernelFunction(GetCurrentProcess);
KernelFunction(KillProcess);
KernelFunction(KillThread);
KernelFunction(Yield);
KernelFunction(Sleep);
KernelFunction(RegisterFileSystem);
KernelFunction(UnregisterFileSystem);
KernelFunction(PIC_EOI);
KernelFunction(IRQ_MASK);
KernelFunction(IRQ_UNMASK);
KernelFunction(PS2Wait);
KernelFunction(PS2WriteCommand);
KernelFunction(PS2WriteData);
KernelFunction(PS2ReadData);
KernelFunction(PS2ReadStatus);
KernelFunction(PS2ReadAfterACK);
KernelFunction(PS2ClearOutputBuffer);
KernelFunction(PS2ACKTimeout);
KernelFunction(RegisterDevice);
KernelFunction(UnregisterDevice);
KernelFunction(ReportInputEvent);
KernelFunction(InitializePCI);
KernelFunction(GetPCIDevices);
KernelFunction(GetBAR);
KernelFunction(iLine);
KernelFunction(iPin);

View File

@ -1,31 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <block.h>
extern __driverAPI *API;
dev_t RegisterBlockDevice(DeviceDriverType Type, drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
{
return API->RegisterBlockDevice(API->MajorID, Type, Open, Close, Read, Write, Ioctl);
}
int UnregisterBlockDevice(dev_t DeviceID, DeviceDriverType Type)
{
return API->UnregisterBlockDevice(API->MajorID, DeviceID, Type);
}

View File

@ -1,85 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <driver.h>
#include <errno.h>
extern __driverAPI *API;
int DriverEntry();
int DriverFinal();
int DriverPanic();
int DriverProbe();
void __IdentifyDriver(
dev_t ID,
int (*GetDriverInfo)(dev_t, const char *, const char *,
const char *, const char *, const char *));
typedef void (*CallPtr)(void);
extern CallPtr __init_array_start[0], __init_array_end[0];
extern CallPtr __fini_array_start[0], __fini_array_end[0];
int _entry()
{
for (CallPtr *func = __init_array_start; func != __init_array_end; func++)
(*func)();
return DriverEntry();
}
int _final()
{
int err = DriverFinal();
for (CallPtr *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
return err;
}
#define API_MajorRequiredVersion 0
#define API_MinorRequiredVersion 0
#define API_PatchRequiredVersion 0
int _start(__driverAPI *__API)
{
if (unlikely(__API == NULL))
return -EINVAL;
if (unlikely(__API->APIVersion.Major != API_MajorRequiredVersion ||
__API->APIVersion.Minor != API_MinorRequiredVersion ||
__API->APIVersion.Patch != API_PatchRequiredVersion))
return -EPROTO;
if (unlikely(__API->RegisterFunction == NULL))
return -ENOSYS;
if (unlikely(DriverEntry == NULL ||
DriverFinal == NULL ||
DriverPanic == NULL ||
DriverProbe == NULL ||
__IdentifyDriver == NULL))
return -EFAULT;
API = __API;
__API->RegisterFunction(__API->MajorID, _entry, _drf_Entry);
__API->RegisterFunction(__API->MajorID, _final, _drf_Final);
__API->RegisterFunction(__API->MajorID, DriverPanic, _drf_Panic);
__API->RegisterFunction(__API->MajorID, DriverProbe, _drf_Probe);
__IdentifyDriver(__API->MajorID, __API->GetDriverInfo);
return 0;
}

144
library/crt/crt0.cpp Normal file
View File

@ -0,0 +1,144 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <driver.h>
#include <errno.h>
dev_t DriverID = -1;
extern "C" int DriverEntry();
extern "C" int DriverFinal();
extern "C" int DriverPanic();
extern "C" int DriverProbe();
typedef void (*CallPtr)(void);
extern "C" CallPtr __init_array_start[0], __init_array_end[0];
extern "C" CallPtr __fini_array_start[0], __fini_array_end[0];
extern "C" int _start(dev_t id)
{
DriverID = id;
for (CallPtr *func = __init_array_start; func != __init_array_end; func++)
(*func)();
return 0;
}
extern "C" int _final()
{
int err = DriverFinal();
for (CallPtr *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
return err;
}
/* ---------------------------------------------------------- */
#define KCALL extern "C" __attribute__((used))
#define KernelFunction(Name) \
KCALL long __##Name(dev_t id, \
long arg0 = 0, long arg1 = 0, long arg2 = 0, \
long arg3 = 0, long arg4 = 0, long arg5 = 0);
#define DefineFunction(ReturnType, Name, ...) \
KernelFunction(Name); \
KCALL ReturnType Name(__VA_ARGS__)
#define DefineWrapper(Name) \
KernelFunction(Name); \
KCALL long Name(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5) \
{ \
return __##Name(DriverID, arg0, arg1, arg2, arg3, arg4, arg5); \
}
DefineFunction(void, KernelPrint, const char *format, ...)
{
__builtin_va_list args;
__builtin_va_start(args, format);
__KernelPrint(DriverID, (long)format, (long)args);
__builtin_va_end(args);
}
DefineFunction(void, KernelLog, const char *format, ...)
{
__builtin_va_list args;
__builtin_va_start(args, format);
__KernelLog(DriverID, (long)format, (long)args);
__builtin_va_end(args);
}
DefineWrapper(RegisterInterruptHandler);
DefineWrapper(OverrideInterruptHandler);
DefineWrapper(UnregisterInterruptHandler);
DefineWrapper(UnregisterAllInterruptHandlers);
DefineWrapper(AllocateMemory);
DefineWrapper(FreeMemory);
DefineWrapper(AppendMapFlag);
DefineWrapper(RemoveMapFlag);
DefineWrapper(MapPages);
DefineWrapper(UnmapPages);
DefineWrapper(MemoryCopy);
DefineWrapper(MemorySet);
DefineWrapper(MemoryMove);
DefineWrapper(StringLength);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
DefineWrapper(strstr);
#pragma GCC diagnostic pop
DefineWrapper(EnterCriticalSection);
DefineWrapper(LeaveCriticalSection);
DefineWrapper(CreateKernelProcess);
DefineWrapper(CreateKernelThread);
DefineWrapper(GetCurrentProcess);
DefineWrapper(KillProcess);
DefineWrapper(KillThread);
DefineWrapper(Yield);
DefineWrapper(Sleep);
DefineWrapper(RegisterFileSystem);
DefineWrapper(UnregisterFileSystem);
DefineWrapper(PIC_EOI);
DefineWrapper(IRQ_MASK);
DefineWrapper(IRQ_UNMASK);
DefineWrapper(PS2Wait);
DefineWrapper(PS2WriteCommand);
DefineWrapper(PS2WriteData);
DefineWrapper(PS2ReadData);
DefineWrapper(PS2ReadStatus);
DefineWrapper(PS2ReadAfterACK);
DefineWrapper(PS2ClearOutputBuffer);
DefineWrapper(PS2ACKTimeout);
DefineWrapper(RegisterDevice);
DefineWrapper(UnregisterDevice);
DefineWrapper(ReportInputEvent);
DefineWrapper(InitializePCI);
DefineWrapper(GetPCIDevices);
DefineWrapper(GetBAR);
DefineWrapper(iLine);
DefineWrapper(iPin);

View File

@ -1,61 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <input.h>
extern __driverAPI *API;
dev_t RegisterInputDevice(DeviceDriverType Type)
{
return API->RegisterInputDevice(API->MajorID, Type);
}
int UnregisterInputDevice(dev_t DeviceID, DeviceDriverType Type)
{
return API->UnregisterInputDevice(API->MajorID, DeviceID, Type);
}
int ReportKeyboardEvent(dev_t DeviceID, KeyScanCodes ScanCode, uint8_t Pressed)
{
if (Pressed)
ScanCode |= KEY_PRESSED;
return API->ReportKeyboardEvent(API->MajorID, DeviceID, ScanCode);
}
int ReportRelativeMouseEvent(dev_t DeviceID, MouseReport Report)
{
__MouseButtons mb = {
.LeftButton = Report.LeftButton,
.RightButton = Report.RightButton,
.MiddleButton = Report.MiddleButton,
.Button4 = Report.Button4,
.Button5 = Report.Button5,
};
return API->ReportRelativeMouseEvent(API->MajorID, DeviceID, mb, Report.X, Report.Y, Report.Z);
}
int ReportAbsoluteMouseEvent(dev_t DeviceID, MouseReport Report, uintptr_t X, uintptr_t Y)
{
__MouseButtons mb = {
.LeftButton = Report.LeftButton,
.RightButton = Report.RightButton,
.MiddleButton = Report.MiddleButton,
.Button4 = Report.Button4,
.Button5 = Report.Button5,
};
return API->ReportAbsoluteMouseEvent(API->MajorID, DeviceID, mb, X, Y, Report.Z);
}

View File

@ -1,36 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <net.h>
extern __driverAPI *API;
dev_t RegisterNetDevice(DeviceDriverType Type, drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
{
return API->RegisterNetDevice(API->MajorID, Type, Open, Close, Read, Write, Ioctl);
}
int UnregisterNetDevice(dev_t DeviceID, DeviceDriverType Type)
{
return API->UnregisterNetDevice(API->MajorID, DeviceID, Type);
}
int ReportNetworkPacket(dev_t DeviceID, void *Buffer, size_t Size)
{
return API->ReportNetworkPacket(API->MajorID, DeviceID, Buffer, Size);
}

View File

@ -1,57 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <pci.h>
#include <driver.h>
extern __driverAPI *API;
static_assert(sizeof(PCIArray) == sizeof(__PCIArray),
"PCIArray size mismatch");
PCIArray *FindPCIDevices(uint16_t Vendors[], uint16_t Devices[])
{
return (PCIArray *)API->GetPCIDevices(API->MajorID,
Vendors,
Devices);
}
void InitializePCI(PCIDevice *Device)
{
API->InitializePCI(API->MajorID,
(void *)Device->Header);
}
uint32_t GetBAR(uint8_t Index, PCIDevice *Device)
{
return API->GetBAR(API->MajorID,
Index,
(void *)Device->Header);
}
uint8_t iLine(PCIDevice *Device)
{
PCIHeader0 *Header = (PCIHeader0 *)Device->Header;
return Header->InterruptLine;
}
uint8_t iPin(PCIDevice *Device)
{
PCIHeader0 *Header = (PCIHeader0 *)Device->Header;
return Header->InterruptPin;
}

View File

@ -1,51 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <base.h>
#include <driver.h>
#undef memcpy
#undef memset
#undef memmove
#undef strlen
extern __driverAPI *API;
void *MemoryCopy(void *Destination, const void *Source, size_t Length)
{
return API->memcpy(API->MajorID, Destination, Source, Length);
}
void *MemorySet(void *Destination, int Value, size_t Length)
{
return API->memset(API->MajorID, Destination, Value, Length);
}
void *MemoryMove(void *Destination, const void *Source, size_t Length)
{
return API->memmove(API->MajorID, Destination, Source, Length);
}
size_t StringLength(const char String[])
{
return API->strlen(API->MajorID, String);
}
char *strstr(const char *Haystack, const char *Needle)
{
return API->strstr(API->MajorID, Haystack, Needle);
}

View File

@ -1,73 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <base.h>
#include <driver.h>
extern __driverAPI *API;
/**
* TODO: memory allocator
* we can't really call kernel's malloc because the
* kernel keep track of memory usage for each driver
*
* maybe implement the allocator in vma?
*/
void *__new_alloc_page(std::size_t Size)
{
/* Do not allow allocations larger than 4 KiB */
if (Size > PAGE_SIZE)
asmv("ud2");
return API->RequestPages(API->MajorID, 1);
}
void __delete_alloc_page(void *Pointer)
{
API->FreePages(API->MajorID, Pointer, 1);
}
void *operator new(std::size_t Size)
{
return __new_alloc_page(Size);
}
void *operator new[](std::size_t Size)
{
return __new_alloc_page(Size);
}
void operator delete(void *Pointer)
{
__delete_alloc_page(Pointer);
}
void operator delete[](void *Pointer)
{
__delete_alloc_page(Pointer);
}
void operator delete(void *Pointer, std::size_t)
{
__delete_alloc_page(Pointer);
}
void operator delete[](void *Pointer, std::size_t)
{
__delete_alloc_page(Pointer);
}

View File

@ -1,64 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <driver.h>
#include <base.h>
extern __driverAPI *API;
pid_t CreateKernelProcess(const char *Name)
{
return API->CreateKernelProcess(API->MajorID,
Name);
}
pid_t CreateKernelThread(pid_t pId, const char *Name, void *EntryPoint, void *Argument)
{
return API->CreateKernelThread(API->MajorID,
pId,
Name,
EntryPoint,
Argument);
}
pid_t GetCurrentProcess()
{
return API->GetCurrentProcess(API->MajorID);
}
int KillProcess(pid_t pId, int ExitCode)
{
return API->KillProcess(API->MajorID,
pId, ExitCode);
}
int KillThread(pid_t tId, pid_t pId, int ExitCode)
{
return API->KillThread(API->MajorID,
tId, pId, ExitCode);
}
void Yield()
{
API->Yield(API->MajorID);
}
void Sleep(uint64_t Milliseconds)
{
API->Sleep(API->MajorID,
Milliseconds);
}

View File

@ -1,114 +0,0 @@
/*
This file is part of Fennix Drivers.
Fennix Drivers 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 Drivers 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 Drivers. If not, see <https://www.gnu.org/licenses/>.
*/
#include <vm.h>
int __strcmp(const char *l, const char *r)
{
for (; *l == *r && *l; l++, r++)
;
return *(unsigned char *)l - *(unsigned char *)r;
}
void __cpuid(uint32_t Function,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
{
asmv("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(Function));
}
bool __CheckHypervisorBit()
{
uint32_t eax, ebx, ecx, edx;
__cpuid(0x1, &eax, &ebx, &ecx, &edx);
if (!(ecx & (1 << 31)))
return false; /* Hypervisor not detected */
return true;
}
bool __VMwareBackdoorHypervisors()
{
const char hv[13] = {0};
uint32_t eax, ebx, ecx, edx;
__cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
*(uint32_t *)hv = ebx;
*(uint32_t *)(hv + 4) = ecx;
*(uint32_t *)(hv + 8) = edx;
if (__strcmp(hv, "VMwareVMware") != 0 &&
__strcmp(hv, "KVMKVMKVM") != 0 &&
__strcmp(hv, "TCGTCGTCGTCG") != 0)
{
return false;
}
return true;
}
bool IsVMwareBackdoorAvailable()
{
if (!__CheckHypervisorBit())
return false;
if (!__VMwareBackdoorHypervisors())
return false;
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;
} cmd;
cmd.si = cmd.di = 0;
cmd.bx = ~0x564D5868;
cmd.command = 0xA;
cmd.magic = 0x564D5868;
cmd.port = 0x5658;
asmv("in %%dx, %0"
: "+a"(cmd.ax), "+b"(cmd.bx),
"+c"(cmd.cx), "+d"(cmd.dx),
"+S"(cmd.si), "+D"(cmd.di));
if (cmd.bx != 0x564D5868 ||
cmd.ax == 0xFFFFFFFF)
return false;
return true;
}

View File

@ -1,83 +1,22 @@
# Config file
# Config files
include ../../../Makefile.conf
FILENAME = example.drv
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver
LDFLAGS := \
-fPIC -fPIE -pie \
-Wl,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared -fvisibility=hidden
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
FILENAME = example.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -20,16 +20,15 @@
int DriverEntry()
{
/** This is the main function of the driver.
* This function is called when the driver is loaded.
* This function should be used to initialize the PCI device
* and allocate resources.
*/
/* Print a message to the screen */
KPrint("Hello World from Example Driver!");
/* Print a message to the kernel terminal */
KernelPrint("Hello World from Example Driver!");
/* Print a message to the kernel log */
Log("Hello World from Example Driver!");
KernelLog("Hello World from Example Driver!");
/* Print a message only if DEBUG is set */
DebugLog("Hello World from Example Driver!");
@ -52,7 +51,7 @@ int DriverPanic()
{
/** This function is called when the kernel panics.
* This function should be used to stop the driver from
* receiving interrupts or anything else that is not
* sending interrupts or anything else that is not
* safe to do when the kernel panics.
*/
@ -63,13 +62,14 @@ int DriverProbe()
{
/** This is the first function that is called when the
* driver is loaded.
* We can use this function to test if the driver is
* compatible with the hardware.
* Like if we have a specific PCI device or if we have
* a specific CPU feature.
*
* This function is to test if the driver is compatible
* with the hardware.
* Example: Like if there is a PCI device that the driver
* is for, or a CPU feature that etc.
*
* Return 0 if the driver is compatible with the hardware.
* Otherwise, we return a value from the errno.h header.
* Otherwise, return a value that is not 0.
*
* Note: In this function you cannot use variables that
* have constructors or destructors. Before DriverEntry,
@ -80,8 +80,18 @@ int DriverProbe()
return 0;
}
/** DriverInfo() is a macro that is used to define the
* driver's information.
*
* The parameters are:
* - Name: Lowercase name
* - Description: A short description
* - Author: The author
* - Version: The version
* - License: The license
*/
DriverInfo("example",
"Example Driver",
"EnderIce2",
"0.1",
0, 0, 1,
"GPLv3");

View File

@ -1,83 +1,22 @@
# Config file
# Config files
include ../../../Makefile.conf
FILENAME = vmware.drv
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver
LDFLAGS := \
-fPIC -fPIE -pie \
-Wl,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared -fvisibility=hidden
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
FILENAME = vmware.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -17,11 +17,11 @@
#include <driver.h>
#include <errno.h>
#include <fs.h>
#include <input.h>
#include <regs.h>
#include <base.h>
#include <aip.h>
#include <vm.h>
#include <io.h>
enum RPCMessages
@ -170,7 +170,7 @@ typedef struct
"r"(bp) : "memory", "cc")
/* TODO:
- use vmcall or vmmcall instead of out or in if available
- use vmcall or vmmcall instead of "out" and "in" if available
*/
typedef struct
@ -183,6 +183,102 @@ typedef struct
dev_t MouseDevID = -1;
int __strcmp(const char *l, const char *r)
{
for (; *l == *r && *l; l++, r++)
;
return *(unsigned char *)l - *(unsigned char *)r;
}
void __cpuid(uint32_t Function,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
{
asmv("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(Function));
}
bool __CheckHypervisorBit()
{
uint32_t eax, ebx, ecx, edx;
__cpuid(0x1, &eax, &ebx, &ecx, &edx);
if (!(ecx & (1 << 31)))
return false; /* Hypervisor not detected */
return true;
}
bool __VMwareBackdoorHypervisors()
{
const char hv[13] = {0};
uint32_t eax, ebx, ecx, edx;
__cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
*(uint32_t *)hv = ebx;
*(uint32_t *)(hv + 4) = ecx;
*(uint32_t *)(hv + 8) = edx;
if (__strcmp(hv, "VMwareVMware") != 0 &&
__strcmp(hv, "KVMKVMKVM") != 0 &&
__strcmp(hv, "TCGTCGTCGTCG") != 0)
{
return false;
}
return true;
}
bool IsVMwareBackdoorAvailable()
{
if (!__CheckHypervisorBit())
return false;
if (!__VMwareBackdoorHypervisors())
return false;
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;
} cmd;
cmd.si = cmd.di = 0;
cmd.bx = ~0x564D5868;
cmd.command = 0xA;
cmd.magic = 0x564D5868;
cmd.port = 0x5658;
asmv("in %%dx, %0"
: "+a"(cmd.ax), "+b"(cmd.bx),
"+c"(cmd.cx), "+d"(cmd.dx),
"+S"(cmd.si), "+D"(cmd.di));
if (cmd.bx != 0x564D5868 ||
cmd.ax == 0xFFFFFFFF)
return false;
return true;
}
static int OpenMessageChannel(ToolboxContext *ctx, uint32_t Protocol)
{
uintptr_t ax, bx, cx, dx, si = 0, di = 0;
@ -194,7 +290,7 @@ static int OpenMessageChannel(ToolboxContext *ctx, uint32_t Protocol)
if ((HighWord(cx) & STATUS_SUCCESS) == 0)
{
Log("Failed to open message channel %#lx", Protocol);
KernelLog("Failed to open message channel %#lx", Protocol);
return -EINVAL;
}
@ -343,8 +439,8 @@ static int MessageSend(ToolboxContext *ctx,
if ((HighWord(cx) & STATUS_SUCCESS) == 0)
{
Log("Failed to send message size for \"%s\": %d",
Message, cx);
KernelLog("Failed to send message size for \"%s\": %d",
Message, cx);
return -EINVAL;
}
@ -363,14 +459,14 @@ static int MessageSend(ToolboxContext *ctx,
}
else if ((status & STATUS_CPT) == 0)
{
Log("Checkpoint occurred for message \"%s\"", Message);
KernelLog("Checkpoint occurred for message \"%s\"", Message);
continue;
}
else
break;
}
Log("Failed to send message \"%s\": %#lx", Message, bx);
KernelLog("Failed to send message \"%s\": %#lx", Message, bx);
return -EINVAL;
}
@ -401,12 +497,12 @@ static int MessageReceive(ToolboxContext *ctx,
if ((HighWord(cx) & STATUS_SUCCESS) == 0)
{
Log("Failed to receive message size: %d", cx);
KernelLog("Failed to receive message size: %d", cx);
return -EINVAL;
}
else if ((HighWord(cx) & STATUS_DORECV) == 0)
{
// Log("No message to receive");
DebugLog("No message to receive");
return -EAGAIN;
}
@ -427,11 +523,11 @@ static int MessageReceive(ToolboxContext *ctx,
{
if ((HighWord(bx) & STATUS_CPT) == 0)
{
Log("Checkpoint occurred for message payload");
KernelLog("Checkpoint occurred for message payload");
continue;
}
Log("Failed to receive message payload: %d", HighWord(bx));
KernelLog("Failed to receive message payload: %d", HighWord(bx));
FreeMemory(ReplyBuf, ReplyBufPages);
return -EINVAL;
}
@ -451,11 +547,11 @@ static int MessageReceive(ToolboxContext *ctx,
{
if ((HighWord(cx) & STATUS_CPT) == 0)
{
Log("Retrying message receive");
KernelLog("Retrying message receive");
continue;
}
Log("Failed to receive message status: %d", HighWord(cx));
KernelLog("Failed to receive message status: %d", HighWord(cx));
FreeMemory(ReplyBuf, ReplyBufPages);
return -EINVAL;
}
@ -465,7 +561,7 @@ static int MessageReceive(ToolboxContext *ctx,
if (ReplyBuf == NULL)
{
Log("Failed to receive message");
KernelLog("Failed to receive message");
return -EINVAL;
}
@ -481,14 +577,14 @@ static int SendRPCI(ToolboxContext *, const char *Request)
int status = OpenMessageChannel(&rpci_ctx, MESSAGE_RPCI);
if (status < 0)
{
Log("Failed to open RPCI channel: %d", status);
KernelLog("Failed to open RPCI channel: %d", status);
return status;
}
status = MessageSend(&rpci_ctx, Request);
if (status < 0)
{
Log("Failed to send RPCI request: %d", status);
KernelLog("Failed to send RPCI request: %d", status);
return status;
}
@ -524,7 +620,7 @@ static int DisplayGetSize(ToolboxContext *ctx)
}
else if (status < 0)
{
Log("Failed to receive message");
KernelLog("Failed to receive message");
return 1;
}
@ -579,7 +675,7 @@ void DisplayScaleThread()
while (true)
{
if (DisplayGetSize(tb_ctx) != 0)
Log("Failed to scale display");
KernelLog("Failed to scale display");
Sleep(1000);
}
}
@ -627,6 +723,7 @@ void Relative()
CommandSend(&cmd);
}
InputReport ir = {0};
void InterruptHandler(TrapFrame *)
{
uint8_t Data = inb(0x60);
@ -639,7 +736,7 @@ void InterruptHandler(TrapFrame *)
if (cmd.ax == 0xFFFF0000)
{
Log("VMware mouse is not connected?");
KernelLog("VMware mouse is not connected?");
Relative();
Absolute();
return;
@ -654,17 +751,6 @@ void InterruptHandler(TrapFrame *)
int Buttons = (cmd.ax & 0xFFFF);
MouseReport mr = {
.LeftButton = Buttons & 0x20,
.RightButton = Buttons & 0x10,
.MiddleButton = Buttons & 0x08,
.Button4 = 0x0,
.Button5 = 0x0,
.X = 0,
.Y = 0,
.Z = (int8_t)cmd.dx,
};
/**
* How should I handle this?
* (cmd.[bx,cx] * Width) / 0xFFFF
@ -672,9 +758,44 @@ void InterruptHandler(TrapFrame *)
*/
uintptr_t AbsoluteX = cmd.bx;
uintptr_t AbsoluteY = cmd.cx;
ReportAbsoluteMouseEvent(MouseDevID, mr, AbsoluteX, AbsoluteY);
ir.Type = INPUT_TYPE_MOUSE;
ir.Device = MouseDevID;
ir.Mouse.X = AbsoluteX;
ir.Mouse.Y = AbsoluteY;
ir.Mouse.Z = (int8_t)cmd.dx;
ir.Mouse.Absolute = 1;
ir.Mouse.LeftButton = Buttons & 0x20;
ir.Mouse.RightButton = Buttons & 0x10;
ir.Mouse.MiddleButton = Buttons & 0x08;
// ir.Mouse.Button4 = 0x0;
// ir.Mouse.Button5 = 0x0;
// ir.Mouse.Button6 = 0x0;
// ir.Mouse.Button7 = 0x0;
// ir.Mouse.Button8 = 0x0;
ReportInputEvent(&ir);
}
int __fs_Ioctl(struct Inode *, unsigned long Request, void *)
{
switch (Request)
{
case 0x1:
Relative();
break;
case 0x2:
Absolute();
break;
default:
return -EINVAL;
}
return 0;
}
const struct InodeOperations MouseOps = {
.Ioctl = __fs_Ioctl,
};
bool ToolboxSupported = false;
int DriverEntry()
{
@ -711,7 +832,8 @@ int DriverEntry()
* override its interrupt handler.
*/
OverrideInterruptHandler(12, InterruptHandler);
MouseDevID = RegisterInputDevice(ddt_Mouse);
MouseDevID = RegisterDevice(INPUT_TYPE_MOUSE, &MouseOps);
return 0;
}
@ -721,7 +843,8 @@ int DriverFinal()
PS2WriteData(PS2_MOUSE_CMD_DISABLE_DATA_REPORTING);
Relative();
UnregisterInputDevice(MouseDevID, ddt_Mouse);
UnregisterDevice(MouseDevID);
if (ToolboxSupported)
{
@ -751,5 +874,5 @@ int DriverProbe()
DriverInfo("vmware",
"VMware Tools Driver",
"EnderIce2",
"0.1",
0, 0, 1,
"GPLv3");

View File

@ -1,83 +1,22 @@
# Config file
# Config files
include ../../../Makefile.conf
FILENAME = e1000.drv
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver
LDFLAGS := \
-fPIC -fPIE -pie \
-Wl,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared -fvisibility=hidden
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
FILENAME = e1000.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -20,7 +20,7 @@
#include <regs.h>
#include <base.h>
#include <pci.h>
#include <net.h>
#include <network.h>
#include <io.h>
#include "e1000.hpp"
@ -205,7 +205,7 @@ public:
mac.Address[i] = BaseMac8[i];
else
{
Log("No MAC address found.");
KernelLog("No MAC address found.");
return MediaAccessControl();
}
}
@ -240,7 +240,11 @@ public:
uint8_t *data = (uint8_t *)RX[RXCurrent]->Address;
uint16_t dataSz = RX[RXCurrent]->Length;
ReportNetworkPacket(ID, data, dataSz);
// ReportNetworkPacket(ID, data, dataSz);
/* FIXME: Implement */
KernelLog("FIXME: Received packet");
(void)data;
(void)dataSz;
RX[RXCurrent]->Status = 0;
uint16_t OldRXCurrent = RXCurrent;
@ -270,7 +274,7 @@ public:
{
case 0x100E:
{
Log("Found Intel 82540EM Gigabit Ethernet Controller.");
KernelLog("Found Intel 82540EM Gigabit Ethernet Controller.");
/* Detect EEPROM */
WriteCMD(REG::EEPROM, 0x1);
@ -282,7 +286,7 @@ public:
if (!GetMAC().Valid())
{
Log("Failed to get MAC");
KernelLog("Failed to get MAC");
return;
}
@ -303,7 +307,7 @@ public:
}
default:
{
Log("Unimplemented E1000 device.");
KernelLog("Unimplemented E1000 device.");
return;
}
}
@ -343,7 +347,7 @@ public:
}
default:
{
Log("Unimplemented E1000 device.");
KernelLog("Unimplemented E1000 device.");
return;
}
}
@ -351,7 +355,7 @@ public:
};
E1000Device *Drivers[4] = {nullptr};
dev_t AudioID[4] = {0};
dev_t NetID[4] = {(dev_t)-1};
#define OIR(x) OIR_##x
#define CREATE_OIR(x) \
@ -362,20 +366,40 @@ CREATE_OIR(1);
CREATE_OIR(2);
CREATE_OIR(3);
int drvOpen(dev_t, dev_t, int, mode_t) { return 0; }
int drvClose(dev_t, dev_t) { return 0; }
size_t drvRead(dev_t, dev_t, uint8_t *, size_t, off_t) { return 0; }
int __fs_Open(struct Inode *, int, mode_t) { return 0; }
int __fs_Close(struct Inode *) { return 0; }
ssize_t __fs_Read(struct Inode *, void *, size_t, off_t) { return 0; }
size_t drvWrite(dev_t, dev_t min, uint8_t *Buffer, size_t Size, off_t)
ssize_t __fs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t)
{
return Drivers[AudioID[min]]->write(Buffer, Size);
return Drivers[NetID[Node->GetMinor()]]->write((uint8_t *)Buffer, Size);
}
int drvIoctl(dev_t, dev_t min, unsigned long Request, void *Argp)
int __fs_Ioctl(struct Inode *Node, unsigned long Request, void *Argp)
{
return Drivers[AudioID[min]]->ioctl((NetIoctl)Request, Argp);
return Drivers[NetID[Node->GetMinor()]]->ioctl((NetIoctl)Request, Argp);
}
const struct InodeOperations NetOps = {
.Lookup = nullptr,
.Create = nullptr,
.Remove = nullptr,
.Rename = nullptr,
.Read = __fs_Read,
.Write = __fs_Write,
.Truncate = nullptr,
.Open = __fs_Open,
.Close = __fs_Close,
.Ioctl = __fs_Ioctl,
.ReadDir = nullptr,
.MkDir = nullptr,
.RmDir = nullptr,
.SymLink = nullptr,
.ReadLink = nullptr,
.Seek = nullptr,
.Stat = nullptr,
};
PCIArray *Devices;
EXTERNC int cxx_Panic()
{
@ -402,10 +426,10 @@ EXTERNC int cxx_Probe()
0x10EA, /* I217-LM */
0x153A, /* 82577LM */
PCI_END};
Devices = FindPCIDevices(VendorIDs, DeviceIDs);
Devices = GetPCIDevices(VendorIDs, DeviceIDs);
if (Devices == nullptr)
{
Log("No E1000 device found.");
KernelLog("No E1000 device found.");
return -ENODEV;
}
return 0;
@ -427,11 +451,8 @@ EXTERNC int cxx_Initialize()
if (Drivers[Count]->IsInitialized())
{
dev_t ret = RegisterNetDevice(ddt_Network,
drvOpen, drvClose,
drvRead, drvWrite,
drvIoctl);
AudioID[Count] = ret;
dev_t ret = RegisterDevice(NETWORK_TYPE_ETHERNET, &NetOps);
NetID[Count] = ret;
Drivers[Count]->ID = ret;
/* FIXME: bad code */
@ -460,7 +481,7 @@ EXTERNC int cxx_Initialize()
if (Count == 0)
{
Log("No valid E1000 device found.");
KernelLog("No valid E1000 device found.");
return -EINVAL;
}
@ -481,5 +502,11 @@ EXTERNC int cxx_Finalize()
ctx = (PCIArray *)ctx->Next;
}
for (size_t i = 0; i < sizeof(NetID) / sizeof(dev_t); i++)
{
if (NetID[i] != (dev_t)-1)
UnregisterDevice(NetID[i]);
}
return 0;
}

View File

@ -27,5 +27,5 @@ int DriverProbe() { return cxx_Probe(); }
DriverInfo("e1000",
"Intel(R) PRO/1000 Network Driver",
"EnderIce2",
"0.1",
0, 0, 1,
"GPLv3");

View File

@ -1,83 +1,22 @@
# Config file
# Config files
include ../../../Makefile.conf
FILENAME = rtl8139.drv
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver
LDFLAGS := \
-fPIC -fPIE -pie \
-Wl,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared -fvisibility=hidden
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
FILENAME = rtl8139.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -27,5 +27,5 @@ int DriverProbe() { return cxx_Probe(); }
DriverInfo("rtl8139",
"Realtek RTL8139 Network Driver",
"EnderIce2",
"0.1",
0, 0, 1,
"GPLv3");

View File

@ -20,7 +20,7 @@
#include <regs.h>
#include <base.h>
#include <pci.h>
#include <net.h>
#include <network.h>
#include <io.h>
#include "rtl8139.hpp"
@ -99,7 +99,11 @@ public:
uint16_t dataSz = *(data + 1);
data += 2;
ReportNetworkPacket(ID, data, dataSz);
// ReportNetworkPacket(ID, data, dataSz);
/* FIXME: Implement */
KernelLog("FIXME: Received packet");
(void)data;
(void)dataSz;
/* Update CAPR */
#define RX_READ_PTR_MASK (~0x3)
@ -169,7 +173,7 @@ public:
};
RTL8139Device *Drivers[4] = {nullptr};
dev_t AudioID[4] = {0};
dev_t NetID[4] = {(dev_t)-1};
#define OIR(x) OIR_##x
#define CREATE_OIR(x) \
@ -180,20 +184,40 @@ CREATE_OIR(1);
CREATE_OIR(2);
CREATE_OIR(3);
int drvOpen(dev_t, dev_t, int, mode_t) { return 0; }
int drvClose(dev_t, dev_t) { return 0; }
size_t drvRead(dev_t, dev_t, uint8_t *, size_t, off_t) { return 0; }
int __fs_Open(struct Inode *, int, mode_t) { return 0; }
int __fs_Close(struct Inode *) { return 0; }
ssize_t __fs_Read(struct Inode *, void *, size_t, off_t) { return 0; }
size_t drvWrite(dev_t, dev_t min, uint8_t *Buffer, size_t Size, off_t)
ssize_t __fs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t)
{
return Drivers[AudioID[min]]->write(Buffer, Size);
return Drivers[NetID[Node->GetMinor()]]->write((uint8_t *)Buffer, Size);
}
int drvIoctl(dev_t, dev_t min, unsigned long Request, void *Argp)
int __fs_Ioctl(struct Inode *Node, unsigned long Request, void *Argp)
{
return Drivers[AudioID[min]]->ioctl((NetIoctl)Request, Argp);
return Drivers[NetID[Node->GetMinor()]]->ioctl((NetIoctl)Request, Argp);
}
const struct InodeOperations NetOps = {
.Lookup = nullptr,
.Create = nullptr,
.Remove = nullptr,
.Rename = nullptr,
.Read = __fs_Read,
.Write = __fs_Write,
.Truncate = nullptr,
.Open = __fs_Open,
.Close = __fs_Close,
.Ioctl = __fs_Ioctl,
.ReadDir = nullptr,
.MkDir = nullptr,
.RmDir = nullptr,
.SymLink = nullptr,
.ReadLink = nullptr,
.Seek = nullptr,
.Stat = nullptr,
};
PCIArray *Devices;
EXTERNC int cxx_Panic()
{
@ -216,10 +240,10 @@ EXTERNC int cxx_Probe()
PCI_END};
uint16_t DeviceIDs[] = {0x8139, /* RTL8139 */
PCI_END};
Devices = FindPCIDevices(VendorIDs, DeviceIDs);
Devices = GetPCIDevices(VendorIDs, DeviceIDs);
if (Devices == nullptr)
{
Log("No RTL8139 device found.");
KernelLog("No RTL8139 device found.");
return -ENODEV;
}
return 0;
@ -240,11 +264,8 @@ EXTERNC int cxx_Initialize()
if (Drivers[Count]->IsInitialized())
{
dev_t ret = RegisterNetDevice(ddt_Network,
drvOpen, drvClose,
drvRead, drvWrite,
drvIoctl);
AudioID[Count] = ret;
dev_t ret = RegisterDevice(NETWORK_TYPE_ETHERNET, &NetOps);
NetID[Count] = ret;
Drivers[Count]->ID = ret;
/* FIXME: bad code */
@ -273,7 +294,7 @@ EXTERNC int cxx_Initialize()
if (Count == 0)
{
Log("No valid RTL8139 device found.");
KernelLog("No valid RTL8139 device found.");
return -EINVAL;
}
@ -294,5 +315,11 @@ EXTERNC int cxx_Finalize()
ctx = (PCIArray *)ctx->Next;
}
for (size_t i = 0; i < sizeof(NetID) / sizeof(dev_t); i++)
{
if (NetID[i] != (dev_t)-1)
UnregisterDevice(NetID[i]);
}
return 0;
}

View File

@ -1,83 +1,22 @@
# Config file
# Config files
include ../../../Makefile.conf
FILENAME = ahci.drv
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver
LDFLAGS := \
-fPIC -fPIE -pie \
-Wl,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared -fvisibility=hidden
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
FILENAME = ahci.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -16,7 +16,7 @@
*/
#include <errno.h>
#include <block.h>
#include <device.h>
#include <regs.h>
#include <base.h>
#include <pci.h>
@ -634,9 +634,9 @@ public:
Identify();
Log("Port %d \"%x %x %x %x\" configured", PortNumber,
HBAPortPtr->Vendor[0], HBAPortPtr->Vendor[1],
HBAPortPtr->Vendor[2], HBAPortPtr->Vendor[3]);
KernelLog("Port %d \"%x %x %x %x\" configured", PortNumber,
HBAPortPtr->Vendor[0], HBAPortPtr->Vendor[1],
HBAPortPtr->Vendor[2], HBAPortPtr->Vendor[3]);
}
bool ReadWrite(uint64_t Sector, uint32_t SectorCount, uint8_t *Buffer, bool Write)
@ -644,7 +644,7 @@ public:
if (this->AHCIPortType == PortType::SATAPI &&
Write == true)
{
Log("SATAPI port does not support write.");
KernelLog("SATAPI port does not support write.");
return false;
}
@ -702,7 +702,7 @@ public:
if (Spin == 1000000)
{
Log("Port not responding.");
KernelLog("Port not responding.");
return false;
}
@ -715,8 +715,8 @@ public:
{
if (Spin > 100000000)
{
Log("Port %d not responding. (%d)",
this->PortNumber, TryCount);
KernelLog("Port %d not responding. (%d)",
this->PortNumber, TryCount);
Spin = 0;
TryCount++;
@ -730,7 +730,7 @@ public:
if (HBAPortPtr->InterruptStatus & HBA_PxIS_TFES)
{
Log("Error reading/writing (%d).", Write);
KernelLog("Error reading/writing (%d).", Write);
return false;
}
}
@ -766,12 +766,12 @@ public:
if (HBAPortPtr->InterruptStatus & HBA_PxIS_TFES)
{
Log("Error reading IDENTIFY command.");
KernelLog("Error reading IDENTIFY command.");
return;
}
if (IdentifyData->Signature != 0xA5)
Log("Port %d has no validity signature.", PortNumber);
KernelLog("Port %d has no validity signature.", PortNumber);
else
{
uint8_t *ptr = (uint8_t *)IdentifyData;
@ -780,11 +780,11 @@ public:
sum += ptr[i];
if (sum != 0)
{
Log("Port %d has invalid checksum.", PortNumber);
KernelLog("Port %d has invalid checksum.", PortNumber);
return;
}
else
Log("Port %d has valid checksum.", PortNumber);
KernelLog("Port %d has valid checksum.", PortNumber);
}
char *Model = (char *)this->IdentifyData->ModelNumber;
@ -796,11 +796,11 @@ public:
}
ModelSwap[40] = 0;
Log("Port %d \"%s\" identified", PortNumber,
ModelSwap);
Log("Port %d is %s (%d rotation rate)", PortNumber,
IdentifyData->NominalMediaRotationRate == 1 ? "SSD" : "HDD",
IdentifyData->NominalMediaRotationRate);
KernelLog("Port %d \"%s\" identified", PortNumber,
ModelSwap);
KernelLog("Port %d is %s (%d rotation rate)", PortNumber,
IdentifyData->NominalMediaRotationRate == 1 ? "SSD" : "HDD",
IdentifyData->NominalMediaRotationRate);
}
};
@ -839,26 +839,47 @@ PortType CheckPortType(HBAPort *Port)
}
}
size_t drvRead(dev_t, dev_t min,
uint8_t *Buffer, size_t Size, off_t Offset)
int __fs_Open(struct Inode *, int, mode_t) { return 0; }
int __fs_Close(struct Inode *) { return 0; }
ssize_t __fs_Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset)
{
bool ok = Ports[min]->ReadWrite(Offset / 512,
uint32_t(Size / 512),
Buffer,
false);
bool ok = Ports[Node->GetMinor()]->ReadWrite(Offset / 512,
uint32_t(Size / 512),
(uint8_t *)Buffer,
false);
return ok ? Size : 0;
}
size_t drvWrite(dev_t, dev_t min,
uint8_t *Buffer, size_t Size, off_t Offset)
ssize_t __fs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset)
{
bool ok = Ports[min]->ReadWrite(Offset / 512,
uint32_t(Size / 512),
Buffer,
true);
bool ok = Ports[Node->GetMinor()]->ReadWrite(Offset / 512,
uint32_t(Size / 512),
(uint8_t *)Buffer,
true);
return ok ? Size : 0;
}
const struct InodeOperations BlockOps = {
.Lookup = nullptr,
.Create = nullptr,
.Remove = nullptr,
.Rename = nullptr,
.Read = __fs_Read,
.Write = __fs_Write,
.Truncate = nullptr,
.Open = __fs_Open,
.Close = __fs_Close,
.Ioctl = nullptr,
.ReadDir = nullptr,
.MkDir = nullptr,
.RmDir = nullptr,
.SymLink = nullptr,
.ReadLink = nullptr,
.Seek = nullptr,
.Stat = nullptr,
};
void OnInterruptReceived(TrapFrame *)
{
}
@ -880,10 +901,10 @@ EXTERNC int cxx_Probe()
0x2829, /* ICH8 */
0x07E0, /* SATA AHCI (VMware) */
PCI_END};
Devices = FindPCIDevices(VendorIDs, DeviceIDs);
Devices = GetPCIDevices(VendorIDs, DeviceIDs);
if (Devices == nullptr)
{
Log("No AHCI device found.");
KernelLog("No AHCI device found.");
return -ENODEV;
}
return 0;
@ -905,31 +926,28 @@ EXTERNC int cxx_Initialize()
HBAMemory *HBA = (HBAMemory *)(uintptr_t)GetBAR(5, ctx->Device);
uint32_t PortsImplemented = HBA->PortsImplemented;
Log("AHCI ports implemented: %x", PortsImplemented);
KernelLog("AHCI ports implemented: %x", PortsImplemented);
for (int i = 0; i < 32; i++)
{
if (PortCount > 64)
{
Log("There are more than 64 AHCI ports implemented");
KernelLog("There are more than 64 AHCI ports implemented");
break;
}
if (PortsImplemented & (1 << i))
{
Log("Port %d implemented", i);
KernelLog("Port %d implemented", i);
PortType portType = CheckPortType(&HBA->Ports[i]);
if (portType == PortType::SATA || portType == PortType::SATAPI)
{
KPrint("%s drive found at port %d", PortTypeName[portType], i);
KernelPrint("%s drive found at port %d", PortTypeName[portType], i);
Ports[PortCount] = new Port(portType, &HBA->Ports[i], PortCount);
dev_t ret = RegisterBlockDevice(ddt_SATA,
nullptr, nullptr,
drvRead, drvWrite,
nullptr);
dev_t ret = RegisterDevice(BLOCK_TYPE_HDD, &BlockOps);
if (ret != (dev_t)PortCount)
{
KPrint("Failed to register block device %d", ret);
return -EBADSLT;
KernelPrint("Failed to register block device %d", ret);
return -EBADF;
}
PortCount++;
@ -939,8 +957,8 @@ EXTERNC int cxx_Initialize()
{
if (portType != PortType::None)
{
KPrint("Unsupported drive type %s found at port %d",
PortTypeName[portType], i);
KernelPrint("Unsupported drive type %s found at port %d",
PortTypeName[portType], i);
}
}
}
@ -949,7 +967,7 @@ EXTERNC int cxx_Initialize()
ctx = (PCIArray *)ctx->Next;
}
Log("Initializing AHCI ports");
KernelLog("Initializing AHCI ports");
for (int i = 0; i < PortCount; i++)
Ports[i]->Configure();
@ -968,7 +986,7 @@ EXTERNC int cxx_Finalize()
do
{
UnregisterBlockDevice(PortCount, ddt_SATA);
UnregisterDevice(PortCount);
PortCount--;
} while (PortCount >= 0);

View File

@ -27,5 +27,5 @@ int DriverProbe() { return cxx_Probe(); }
DriverInfo("ahci",
"Advanced Host Controller Interface Driver",
"EnderIce2",
"0.1",
0, 0, 1,
"GPLv3");

View File

@ -1,83 +1,22 @@
# Config file
# Config files
include ../../../Makefile.conf
FILENAME = ata.drv
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver
LDFLAGS := \
-fPIC -fPIE -pie \
-Wl,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared -fvisibility=hidden
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
FILENAME = ata.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -72,5 +72,5 @@ int DriverProbe()
DriverInfo("ata",
"Advanced Technology Attachment Driver",
"EnderIce2",
"0.1",
0, 0, 1,
"GPLv3");