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", "head",
], ],
"body": [ "body": [
"#ifndef __FENNIX_API_${2:header}_H__", "#ifndef __FENNIX_DRIVER_${2:header}_H__",
"#define __FENNIX_API_${2:header}_H__", "#define __FENNIX_DRIVER_${2:header}_H__",
"", "",
"#include <types.h>", "#include <types.h>",
"", "",
"$0", "$0",
"", "",
"#endif // !__FENNIX_API_${2:header}_H__", "#endif // !__FENNIX_DRIVER_${2:header}_H__",
"" ""
], ],
"description": "Create header." "description": "Create header."

View File

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

View File

@ -1,83 +1,22 @@
# Config file # Config files
include ../../../Makefile.conf include ../../../Makefile.conf
include ../../config.mk
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
S_SOURCES = $(shell find ./ -type f -name '*.S') S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c') C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp') CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*))) 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) STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver FILENAME = ac97.drv
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
build: $(FILENAME) build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME) mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ) $(FILENAME): $(OBJ)
$(info Linking $@) $(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@ $(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -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 $@ $<
clean: clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ) rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

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

View File

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

View File

@ -1,83 +1,22 @@
# Config file # Config files
include ../../../Makefile.conf include ../../../Makefile.conf
include ../../config.mk
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
S_SOURCES = $(shell find ./ -type f -name '*.S') S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c') C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp') CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*))) 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) STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver FILENAME = hda.drv
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
build: $(FILENAME) build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME) mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ) $(FILENAME): $(OBJ)
$(info Linking $@) $(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@ $(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -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 $@ $<
clean: clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ) rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -21,6 +21,7 @@
#include <base.h> #include <base.h>
#include <pci.h> #include <pci.h>
#include <io.h> #include <io.h>
#include <fs.h>
#include "hda.hpp" #include "hda.hpp"
@ -62,7 +63,7 @@ public:
RIRB((uint64_t *)AllocateMemory(1)) RIRB((uint64_t *)AllocateMemory(1))
{ {
CTL = (ControllerRegisters *)(uintptr_t)Header->BAR0; CTL = (ControllerRegisters *)(uintptr_t)Header->BAR0;
Log("Unimplemented HDA driver"); KernelLog("Unimplemented HDA driver");
return; return;
Initialized = true; Initialized = true;
} }
@ -75,7 +76,7 @@ public:
}; };
HDADevice *Drivers[4] = {nullptr}; HDADevice *Drivers[4] = {nullptr};
dev_t AudioID[4] = {0}; dev_t AudioID[4] = {(dev_t)-1};
#define OIR(x) OIR_##x #define OIR(x) OIR_##x
#define CREATE_OIR(x) \ #define CREATE_OIR(x) \
@ -86,20 +87,40 @@ CREATE_OIR(1);
CREATE_OIR(2); CREATE_OIR(2);
CREATE_OIR(3); CREATE_OIR(3);
int drvOpen(dev_t, dev_t, int, mode_t) { return 0; } int __fs_Open(struct Inode *, int, mode_t) { return 0; }
int drvClose(dev_t, dev_t) { return 0; } int __fs_Close(struct Inode *) { return 0; }
size_t drvRead(dev_t, dev_t, uint8_t *, size_t, off_t) { 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; PCIArray *Devices;
EXTERNC int cxx_Panic() EXTERNC int cxx_Panic()
{ {
@ -125,10 +146,10 @@ EXTERNC int cxx_Probe()
0x2668 /* ICH6 */, 0x2668 /* ICH6 */,
0x293E /* ICH9 */, 0x293E /* ICH9 */,
PCI_END}; PCI_END};
Devices = FindPCIDevices(VendorIDs, DeviceIDs); Devices = GetPCIDevices(VendorIDs, DeviceIDs);
if (Devices == nullptr) if (Devices == nullptr)
{ {
Log("No HDA device found."); KernelLog("No HDA device found.");
return -ENODEV; return -ENODEV;
} }
@ -145,10 +166,10 @@ EXTERNC int cxx_Probe()
uint8_t Type = PCIBAR0 & 1; uint8_t Type = PCIBAR0 & 1;
if (Type == 1) if (Type == 1)
{ {
Log("Device %x:%x.%d BAR0 is I/O.", KernelLog("Device %x:%x.%d BAR0 is I/O.",
PCIBaseAddress->Header.VendorID, PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID, PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF); PCIBaseAddress->Header.ProgIF);
continue; continue;
} }
@ -158,7 +179,7 @@ EXTERNC int cxx_Probe()
if (!Found) if (!Found)
{ {
Log("No valid HDA device found."); KernelLog("No valid HDA device found.");
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
@ -178,10 +199,10 @@ EXTERNC int cxx_Initialize()
uint8_t Type = PCIBAR0 & 1; uint8_t Type = PCIBAR0 & 1;
if (Type == 1) if (Type == 1)
{ {
Log("Device %x:%x.%d BAR0 is I/O.", KernelLog("Device %x:%x.%d BAR0 is I/O.",
PCIBaseAddress->Header.VendorID, PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID, PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF); PCIBaseAddress->Header.ProgIF);
continue; continue;
} }
@ -191,10 +212,7 @@ EXTERNC int cxx_Initialize()
if (Drivers[Count]->IsInitialized()) if (Drivers[Count]->IsInitialized())
{ {
dev_t ret = RegisterAudioDevice(ddt_Audio, dev_t ret = RegisterDevice(AUDIO_TYPE_PCM, &AudioOps);
drvOpen, drvClose,
drvRead, drvWrite,
drvIoctl);
AudioID[Count] = ret; AudioID[Count] = ret;
Count++; Count++;
} }
@ -203,7 +221,7 @@ EXTERNC int cxx_Initialize()
if (Count == 0) if (Count == 0)
{ {
Log("No valid HDA device found."); KernelLog("No valid HDA device found.");
return -EINVAL; return -EINVAL;
} }
@ -224,10 +242,10 @@ EXTERNC int cxx_Finalize()
uint8_t Type = PCIBAR0 & 1; uint8_t Type = PCIBAR0 & 1;
if (Type == 1) if (Type == 1)
{ {
Log("Device %x:%x.%d BAR0 is I/O.", KernelLog("Device %x:%x.%d BAR0 is I/O.",
PCIBaseAddress->Header.VendorID, PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID, PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF); PCIBaseAddress->Header.ProgIF);
continue; continue;
} }
@ -235,5 +253,11 @@ EXTERNC int cxx_Finalize()
ctx = (PCIArray *)ctx->Next; 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; return 0;
} }

View File

@ -27,5 +27,5 @@ int DriverProbe() { return cxx_Probe(); }
DriverInfo("hda", DriverInfo("hda",
"Intel High Definition Audio Driver", "Intel High Definition Audio Driver",
"EnderIce2", "EnderIce2",
"0.1", 0, 0, 1,
"GPLv3"); "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", DriverInfo("name",
"description", "description",
"author", "author",
"version", 0, 0, 0,
"license"); "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/>. along with Fennix Drivers. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef __FENNIX_API_VM_H__ #include <base.h>
#define __FENNIX_API_VM_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__ #define __FENNIX_API_AIP_H__
#include <types.h> #include <types.h>
#include <aip/kbd.h>
#include <aip/mouse.h>
#define PIC1_CMD 0x20 #define PIC1_CMD 0x20
#define PIC1_DATA (PIC1_CMD + 1) #define PIC1_DATA (PIC1_CMD + 1)
@ -117,7 +115,145 @@ uint8_t PS2ReadAfterACK();
void PS2ClearOutputBuffer(); void PS2ClearOutputBuffer();
int PS2ACKTimeout(); int PS2ACKTimeout();
#define WaitOutput PS2Wait(true) #define WaitOutput PS2Wait(DriverID, true)
#define WaitInput PS2Wait(false) #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__ #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 modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version. 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 but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License 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__ #ifndef __FENNIX_API_AUDIO_H__
#define __FENNIX_API_AUDIO_H__ #define __FENNIX_API_AUDIO_H__
#include <types.h> #include <types.h>
#include <driver.h>
typedef int (*drvOpen_t)(dev_t, dev_t, int, mode_t); #if __has_include(<interface/device.h>)
typedef int (*drvClose_t)(dev_t, dev_t); #include <interface/device.h>
typedef size_t (*drvRead_t)(dev_t, dev_t, uint8_t *, size_t, off_t); #else
typedef size_t (*drvWrite_t)(dev_t, dev_t, uint8_t *, size_t, off_t); #include <device.h>
typedef int (*drvIoctl_t)(dev_t, dev_t, unsigned long, void *); #endif
#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
#endif // !__FENNIX_API_AUDIO_H__ #endif // !__FENNIX_API_AUDIO_H__

View File

@ -77,20 +77,20 @@ extern "C"
void UnmapPages(void *VirtualAddress, size_t Pages); void UnmapPages(void *VirtualAddress, size_t Pages);
/** /**
* @brief Print to the screen * @brief Print to the kernel terminal
* @param Format The format string * @param Format The format string
* @param ... The arguments to the format string * @param ... The arguments to the format string
* *
* @note The newline character is automatically appended * @note The newline character is automatically appended
*/ */
void KPrint(const char *Format, ...); void KernelPrint(const char *Format, ...);
/** /**
* @brief Print to the kernel logger * @brief Print to the kernel logger
* @param Format The format string * @param Format The format string
* @param ... The arguments to 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 * @brief Register an interrupt handler
@ -241,17 +241,20 @@ extern "C"
/** @copydoc LeaveCriticalSection */ /** @copydoc LeaveCriticalSection */
#define LCS LeaveCriticalSection(__ECS) #define LCS LeaveCriticalSection(__ECS)
#define DriverInfo(Name, Description, Author, Version, License) \ #define DriverInfo(_Name, _Description, _Author, _MajorVersion, \
void __IdentifyDriver( \ _MinorVersion, _PathVersion, _License) \
dev_t ID, \ __attribute__((section(".driver.info"))) struct __DriverInfo \
int (*GetDriverInfo)(dev_t, const char *, const char *, \ __di = {.Name = _Name, \
const char *, const char *, const char *)) \ .Description = _Description, \
{ \ .Author = _Author, \
GetDriverInfo(ID, Name, Description, Author, Version, License); \ .Version = {.APIVersion = 0, \
} .Major = _MajorVersion, \
.Minor = _MinorVersion, \
.Patch = _PathVersion}, \
.License = _License}
#ifdef DEBUG #ifdef DEBUG
#define DebugLog(m, ...) Log(m, ##__VA_ARGS__) #define DebugLog(m, ...) KernelLog(m, ##__VA_ARGS__)
#else #else
#define DebugLog(m, ...) #define DebugLog(m, ...)
#endif // DEBUG #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> #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 typedef struct
{ {
/* PCIDevice */ void *Device; /* PCIDevice */ void *Device;
@ -57,177 +33,22 @@ typedef struct
typedef enum typedef enum
{ {
KEY_1, IOCTL_AUDIO_GET_VOLUME = 0,
KEY_2, IOCTL_AUDIO_SET_VOLUME = 1,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_0,
KEY_Q, IOCTL_AUDIO_GET_MUTE = 2,
KEY_W, IOCTL_AUDIO_SET_MUTE = 3,
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, IOCTL_AUDIO_GET_SAMPLE_RATE = 4,
KEY_F2, IOCTL_AUDIO_SET_SAMPLE_RATE = 5,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEYPAD_7, IOCTL_AUDIO_GET_CHANNELS = 6,
KEYPAD_8, IOCTL_AUDIO_SET_CHANNELS = 7,
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,
} AudioIoctl; } AudioIoctl;
typedef enum typedef enum
{ {
IOCTL_NET_GET_MAC, IOCTL_NET_GET_MAC = 0,
} NetIoctl; } NetIoctl;
typedef enum typedef enum
@ -239,89 +60,17 @@ typedef enum
MAP_CACHE_DISABLE = 1 << 4, MAP_CACHE_DISABLE = 1 << 4,
} PageMapFlags; } PageMapFlags;
typedef struct struct __DriverInfo
{ {
struct const char *Name;
const char *Description;
const char *Author;
struct __DriverVersion
{ {
uint8_t Major; int APIVersion;
uint8_t Minor; int Major, Minor, Patch;
uint8_t Patch; } Version;
} APIVersion; const char *License;
};
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;
#endif // !__FENNIX_API_DRIVER_FUNCTIONS_H__ #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 modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version. 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 but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License 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 #ifndef __FENNIX_KERNEL_ERRNO_H__
#define _ERRNO_H #define __FENNIX_KERNEL_ERRNO_H__
/** Operation not permitted */ /**
#define EPERM 1 * The documentation for these error codes are from:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
/** No such file or directory */ *
#define ENOENT 2 * Full list:
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
/** No such process */ */
#define ESRCH 3 typedef enum
{
/** Interrupted system call */ /**
#define EINTR 4 * No Error
*/
/** I/O error */ EOK = 0,
#define EIO 5
/**
/** No such device or address */ * Argument list too long. The sum of the number of bytes used by the
#define ENXIO 6 * new process image's argument list and environment list is greater
* than the system-imposed limit of {ARG_MAX} bytes.
/** Argument list too long */ * or:
#define E2BIG 7 * Lack of space in an output buffer.
* or:
/** Exec format error */ * Argument is greater than the system-imposed maximum.
#define ENOEXEC 8 */
E2BIG = 1,
/** Bad file number */
#define EBADF 9 /**
* Permission denied. An attempt was made to access a file in a way
/** No child processes */ * forbidden by its file access permissions.
#define ECHILD 10 */
EACCES = 2,
/** Try again */
#define EAGAIN 11 /**
* Address in use. The specified address is in use.
/** Out of memory */ */
#define ENOMEM 12 EADDRINUSE = 3,
/** Permission denied */ /**
#define EACCES 13 * Address not available. The specified address is not available from
* the local system.
/** Bad address */ */
#define EFAULT 14 EADDRNOTAVAIL = 4,
/** Block device required */ /**
#define ENOTBLK 15 * Address family not supported. The implementation does not support
* the specified address family, or the specified address is not a
/** Device or resource busy */ * valid address for the address family of the specified socket.
#define EBUSY 16 */
EAFNOSUPPORT = 5,
/** File exists */
#define EEXIST 17 /**
* Resource temporarily unavailable. This is a temporary condition
/** Cross-device link */ * and later calls to the same routine may complete normally.
#define EXDEV 18 */
EAGAIN = 6,
/** No such device */
#define ENODEV 19 /**
* Connection already in progress. A connection request is already in
/** Not a directory */ * progress for the specified socket.
#define ENOTDIR 20 */
EALREADY = 7,
/** Is a directory */
#define EISDIR 21 /**
* Bad file descriptor. A file descriptor argument is out of range,
/** Invalid argument */ * refers to no open file, or a read (write) request is made to a
#define EINVAL 22 * file that is only open for writing (reading).
*/
/** File table overflow */ EBADF = 8,
#define ENFILE 23
/**
/** Too many open files */ * Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
#define EMFILE 24 * I_RECVFD request to a STREAMS device, a message arrived at the
* head of the STREAM that is inappropriate for the function
/** Not a typewriter */ * receiving the message.
#define ENOTTY 25 * read()
* Message waiting to be read on a STREAM is not a data message.
/** Text file busy */ * getmsg() or getpmsg()
#define ETXTBSY 26 * A file descriptor was received instead of a control message.
* ioctl()
/** File too large */ * Control or data information was received instead of a file
#define EFBIG 27 * descriptor when I_RECVFD was specified.
*/
/** No space left on device */ EBADMSG = 9,
#define ENOSPC 28
/**
/** Illegal seek */ * Resource busy. An attempt was made to make use of a system
#define ESPIPE 29 * resource that is not currently available, as it is being
* used by another process in a manner that would have
/** Read-only file system */ * conflicted with the request being made by this process.
#define EROFS 30 */
EBUSY = 10,
/** Too many links */
#define EMLINK 31 /**
* Operation canceled. The associated asynchronous operation was
/** Broken pipe */ * canceled before completion.
#define EPIPE 32 */
ECANCELED = 11,
/** Math argument out of domain of func */
#define EDOM 33 /**
* No child process. A wait(), waitid(), or waitpid() function was
/** Math result not representable */ * executed by a process that had no existing or unwaited-for
#define ERANGE 34 * child process.
*/
/** Resource deadlock would occur */ ECHILD = 12,
#define EDEADLK 35
/**
/** File name too long */ * Connection aborted. The connection has been aborted.
#define ENAMETOOLONG 36 */
ECONNABORTED = 13,
/** No record locks available */
#define ENOLCK 37 /**
* Connection refused. An attempt to connect to a socket was refused
/** Function not implemented */ * because there was no process listening or because the queue of
#define ENOSYS 38 * connection requests was full and the underlying protocol does not
* support retransmissions.
/** Directory not empty */ */
#define ENOTEMPTY 39 ECONNREFUSED = 14,
/** Too many symbolic links encountered */ /**
#define ELOOP 40 * Connection reset. The connection was forcibly closed by the peer.
*/
/** No message of desired type */ ECONNRESET = 15,
#define ENOMSG 42
/**
/** Identifier removed */ * Resource deadlock would occur. An attempt was made to lock a system
#define EIDRM 43 * resource that would have resulted in a deadlock situation.
*/
/** Channel number out of range */ EDEADLK = 16,
#define ECHRNG 44
/**
/** Level 2 not synchronized */ * Destination address required. No bind address was established.
#define EL2NSYNC 45 */
EDESTADDRREQ = 17,
/** Level 3 halted */
#define EL3HLT 46 /**
* Domain error. An input argument is outside the defined domain of the
/** Level 3 reset */ * mathematical function (defined in the ISO C standard).
#define EL3RST 47 */
EDOM = 18,
/** Link number out of range */
#define ELNRNG 48 /**
* Reserved.
/** Protocol driver not attached */ */
#define EUNATCH 49 EDQUOT = 19,
/** No CSI structure available */ /**
#define ENOCSI 50 * File exists. An existing file was mentioned in an inappropriate
* context; for example, as a new link name in the link() function.
/** Level 2 halted */ */
#define EL2HLT 51 EEXIST = 20,
/** Invalid exchange */ /**
#define EBADE 52 * Bad address. The system detected an invalid address in attempting
* to use an argument of a call. The reliable detection of this error
/** Invalid request descriptor */ * cannot be guaranteed, and when not detected may result in the
#define EBADR 53 * generation of a signal, indicating an address violation, which is
* sent to the process.
/** Exchange full */ */
#define EXFULL 54 EFAULT = 21,
/** No anode */ /**
#define ENOANO 55 * File too large. The size of a file would exceed the maximum file
* size of an implementation or offset maximum established in the
/** Invalid request code */ * corresponding file description.
#define EBADRQC 56 */
EFBIG = 22,
/** Invalid slot */
#define EBADSLT 57 /**
* Host is unreachable. The destination host cannot be reached
/** Bad font file format */ * (probably because the host is down or a remote router cannot
#define EBFONT 59 * reach it).
*/
/** Device not a stream */ EHOSTUNREACH = 23,
#define ENOSTR 60
/**
/** No data available */ * Identifier removed. Returned during XSI interprocess communication
#define ENODATA 61 * if an identifier has been removed from the system.
*/
/** Timer expired */ EIDRM = 24,
#define ETIME 62
/**
/** Out of streams resources */ * Illegal byte sequence. A wide-character code has been detected that
#define ENOSR 63 * 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).
/** Machine is not on the network */ */
#define ENONET 64 EILSEQ = 25,
/** Package not installed */ /**
#define ENOPKG 65 * Operation in progress. This code is used to indicate that an
* asynchronous operation has not yet completed.
/** Object is remote */ * or:
#define EREMOTE 66 * O_NONBLOCK is set for the socket file descriptor and the connection
* cannot be immediately established.
/** Link has been severed */ */
#define ENOLINK 67 EINPROGRESS = 26,
/** Advertise error */ /**
#define EADV 68 * Interrupted function call. An asynchronous signal was caught by the
* process during the execution of an interruptible function. If the
/** Srmount error */ * signal handler performs a normal return, the interrupted function
#define ESRMNT 69 * call may return this condition (see the Base Definitions volume
* of POSIX.1-2017, <signal.h>).
/** Communication error on send */ */
#define ECOMM 70 EINTR = 27,
/** Protocol error */ /**
#define EPROTO 71 * Invalid argument. Some invalid argument was supplied; for example,
* specifying an undefined signal in a signal() function or a
/** Multihop attempted */ * kill() function.
#define EMULTIHOP 72 */
EINVAL = 28,
/** RFS specific error */
#define EDOTDOT 73 /**
* Input/output error. Some physical input or output error has occurred.
/** Not a data message */ * This error may be reported on a subsequent operation on the same
#define EBADMSG 74 * file descriptor. Any other error-causing operation on the same file
* descriptor may cause the [EIO] error indication to be lost.
/** Value too large for defined data type */ */
#define EOVERFLOW 75 EIO = 29,
/** Name not unique on network */ /**
#define ENOTUNIQ 76 * Socket is connected. The specified socket is already connected.
*/
/** File descriptor in bad state */ EISCONN = 30,
#define EBADFD 77
/**
/** Remote address changed */ * Is a directory. An attempt was made to open a directory with write
#define EREMCHG 78 * mode specified.
*/
/** Can not access a needed shared library */ EISDIR = 31,
#define ELIBACC 79
/**
/** Accessing a corrupted shared library */ * Symbolic link loop. A loop exists in symbolic links encountered
#define ELIBBAD 80 * during pathname resolution. This error may also be returned if
* more than {SYMLOOP_MAX} symbolic links are encountered during
/** .lib section in a.out corrupted */ * pathname resolution.
#define ELIBSCN 81 */
ELOOP = 32,
/** Attempting to link in too many shared libraries */
#define ELIBMAX 82 /**
* File descriptor value too large or too many open streams. An
/** Cannot exec a shared library directly */ * attempt was made to open a file descriptor with a value greater
#define ELIBEXEC 83 * than or equal to {OPEN_MAX}, or an attempt was made to open more
* than the maximum number of streams allowed in the process.
/** Illegal byte sequence */ */
#define EILSEQ 84 EMFILE = 33,
/** Interrupted system call should be restarted */ /**
#define ERESTART 85 * Too many links. An attempt was made to have the link count of a
* single file exceed {LINK_MAX}.
/** Streams pipe error */ */
#define ESTRPIPE 86 EMLINK = 34,
/** Too many users */ /**
#define EUSERS 87 * Message too large. A message sent on a transport provider was
* larger than an internal message buffer or some other network limit.
/** Socket operation on non-socket */ * or:
#define ENOTSOCK 88 * Inappropriate message buffer length.
*/
/** Destination address required */ EMSGSIZE = 35,
#define EDESTADDRREQ 89
/**
/** Message too long */ * Reserved.
#define EMSGSIZE 90 */
EMULTIHOP = 36,
/** Protocol wrong type for socket */
#define EPROTOTYPE 91 /**
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
/** Protocol not available */ * the implementation considers this to be an error, or a pathname
#define ENOPROTOOPT 92 * component is longer than {NAME_MAX}. This error may also occur
* when pathname substitution, as a result of encountering a
/** Protocol not supported */ * symbolic link during pathname resolution, results in a pathname
#define EPROTONOSUPPORT 93 * string the size of which exceeds {PATH_MAX}.
*/
/** Socket type not supported */ ENAMETOOLONG = 37,
#define ESOCKTNOSUPPORT 94
/**
/** Operation not supported on transport endpoint */ * Network is down. The local network interface used to reach the
#define EOPNOTSUPP 95 * destination is down.
*/
/** Protocol family not supported */ ENETDOWN = 38,
#define EPFNOSUPPORT 96
/**
/** Address family not supported by protocol */ * The connection was aborted by the network.
#define EAFNOSUPPORT 97 */
ENETRESET = 39,
/** Address already in use */
#define EADDRINUSE 98 /**
* Network unreachable. No route to the network is present.
/** Cannot assign requested address */ */
#define EADDRNOTAVAIL 99 ENETUNREACH = 40,
/** Network is down */ /**
#define ENETDOWN 100 * Too many files open in system. Too many files are currently open
* in the system. The system has reached its predefined limit for
/** Network is unreachable */ * simultaneously open files and temporarily cannot accept requests
#define ENETUNREACH 101 * to open another one.
*/
/** Network dropped connection because of reset */ ENFILE = 41,
#define ENETRESET 102
/**
/** Software caused connection abort */ * No buffer space available. Insufficient buffer resources were
#define ECONNABORTED 103 * available in the system to perform the socket operation.
*/
/** Connection reset by peer */ ENOBUFS = 42,
#define ECONNRESET 104
/**
/** No buffer space available */ * No message available. No message is available on the STREAM head
#define ENOBUFS 105 * read queue.
*/
/** Transport endpoint is already connected */ ENODATA = 43,
#define EISCONN 106
/**
/** Transport endpoint is not connected */ * No such device. An attempt was made to apply an inappropriate
#define ENOTCONN 107 * function to a device; for example, trying to read a write-only
* device such as a printer.
/** Cannot send after transport endpoint shutdown */ */
#define ESHUTDOWN 108 ENODEV = 44,
/** Too many references: cannot splice */ /**
#define ETOOMANYREFS 109 * No such file or directory. A component of a specified pathname
* does not exist, or the pathname is an empty string.
/** Connection timed out */ */
#define ETIMEDOUT 110 ENOENT = 45,
/** Connection refused */ /**
#define ECONNREFUSED 111 * Executable file format error. A request is made to execute a file
* that, although it has appropriate privileges, is not in the
/** Host is down */ * format required by the implementation for executable files.
#define EHOSTDOWN 112 */
ENOEXEC = 46,
/** No route to host */
#define EHOSTUNREACH 113 /**
* No locks available. A system-imposed limit on the number of
/** Operation already in progress */ * simultaneous file and record locks has been reached and no more
#define EALREADY 114 * are currently available.
*/
/** Operation now in progress */ ENOLCK = 47,
#define EINPROGRESS 115
/**
/** Stale NFS file handle */ * Reserved.
#define ESTALE 116 */
ENOLINK = 48,
/** Structure needs cleaning */
#define EUCLEAN 117 /**
* Not enough space. The new process image requires more memory than
/** Not a XENIX named type file */ * is allowed by the hardware or system-imposed memory management
#define ENOTNAM 118 * constraints.
*/
/** No XENIX semaphores available */ ENOMEM = 49,
#define ENAVAIL 119
/**
/** Is a named type file */ * No message of the desired type. The message queue does not contain
#define EISNAM 120 * a message of the required type during XSI interprocess communication.
*/
/** Remote I/O error */ ENOMSG = 50,
#define EREMOTEIO 121
/**
/** Quota exceeded */ * Protocol not available. The protocol option specified to
#define EDQUOT 122 * setsockopt() is not supported by the implementation.
*/
/** No medium found */ ENOPROTOOPT = 51,
#define ENOMEDIUM 123
/**
/** Wrong medium type */ * No space left on a device. During the write() function on a
#define EMEDIUMTYPE 124 * regular file or when extending a directory, there is no free
* space left on the device.
/** Operation Canceled */ */
#define ECANCELED 125 ENOSPC = 52,
/** Required key not available */ /**
#define ENOKEY 126 * No STREAM resources. Insufficient STREAMS memory resources are
* available to perform a STREAMS-related function. This is a
/** Key has expired */ * temporary condition; it may be recovered from if other
#define EKEYEXPIRED 127 * processes release resources.
*/
/** Key has been revoked */ ENOSR = 53,
#define EKEYREVOKED 128
/**
/** Key was rejected by service */ * Not a STREAM. A STREAM function was attempted on a file descriptor
#define EKEYREJECTED 129 * that was not associated with a STREAMS device.
*/
/** Owner died */ ENOSTR = 54,
#define EOWNERDEAD 130
/**
/** State not recoverable */ * Functionality not supported. An attempt was made to use optional
#define ENOTRECOVERABLE 131 * functionality that is not supported in this implementation.
*/
#endif // !_ERRNO_H 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 modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version. 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 but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License 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__ #ifndef __FENNIX_API_INPUT_H__
#define __FENNIX_API_INPUT_H__ #define __FENNIX_API_INPUT_H__
#include <types.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 typedef struct
{ {
union KeyScanCodes Key;
{ } KeyboardReport;
struct
{
uint8_t LeftButton : 1;
uint8_t RightButton : 1;
uint8_t MiddleButton : 1;
uint8_t Button4 : 1;
uint8_t Button5 : 1;
};
uint8_t Buttons;
};
/** typedef struct
* @note Ignored if is absolute {
*/ long X, Y;
int X;
/**
* @note Ignored if is absolute
*/
int Y;
int8_t Z; 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; } MouseReport;
#ifdef __cplusplus typedef struct
extern "C"
{ {
#endif // __cplusplus } JoystickReport;
dev_t RegisterInputDevice(DeviceDriverType Type); typedef struct
int UnregisterInputDevice(dev_t DeviceID, DeviceDriverType Type); {
int ReportKeyboardEvent(dev_t DeviceID, KeyScanCodes ScanCode, uint8_t Pressed); uint16_t X, Y;
int ReportRelativeMouseEvent(dev_t DeviceID, MouseReport Report); uint8_t Pressure;
int ReportAbsoluteMouseEvent(dev_t DeviceID, MouseReport Report, uintptr_t X, uintptr_t Y); } TouchScreenReport;
#ifdef __cplusplus typedef struct
} {
#endif // __cplusplus } 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__ #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> #include <types.h>
/* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */ /* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */
enum PCICommands typedef enum
{ {
/** @brief Enable response in I/O space */ /** @brief Enable response in I/O space */
PCI_COMMAND_IO = 0x1, PCI_COMMAND_IO = 0x1,
@ -45,7 +45,7 @@ enum PCICommands
PCI_COMMAND_FAST_BACK = 0x200, PCI_COMMAND_FAST_BACK = 0x200,
/** @brief INTx Emulation Disable */ /** @brief INTx Emulation Disable */
PCI_COMMAND_INTX_DISABLE = 0x400 PCI_COMMAND_INTX_DISABLE = 0x400
}; } PCI_COMMANDS;
typedef struct typedef struct
{ {
@ -171,7 +171,7 @@ extern "C"
{ {
#endif #endif
PCIArray *FindPCIDevices(uint16_t Vendors[], uint16_t Devices[]); PCIArray *GetPCIDevices(uint16_t Vendors[], uint16_t Devices[]);
void InitializePCI(PCIDevice *Device); void InitializePCI(PCIDevice *Device);
uint32_t GetBAR(uint8_t Index, PCIDevice *Device); uint32_t GetBAR(uint8_t Index, PCIDevice *Device);
uint8_t iLine(PCIDevice *Device); uint8_t iLine(PCIDevice *Device);

View File

@ -21,6 +21,7 @@
#include <types.h> #include <types.h>
#if defined(__amd64__) #if defined(__amd64__)
typedef struct typedef struct
{ {
uint64_t r15; // General purpose uint64_t r15; // General purpose
@ -49,8 +50,10 @@ typedef struct
uint64_t rsp; // Stack Pointer uint64_t rsp; // Stack Pointer
uint64_t ss; // Stack Segment uint64_t ss; // Stack Segment
} TrapFrame; } TrapFrame;
#elif defined(__i386__) #elif defined(__i386__)
typedef struct TrapFrame
typedef struct
{ {
uint32_t edi; // Destination index for string operations uint32_t edi; // Destination index for string operations
uint32_t esi; // Source 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_esp; // Stack Pointer
uint32_t r3_ss; // Stack Segment uint32_t r3_ss; // Stack Segment
} TrapFrame; } TrapFrame;
#elif defined(__aarch64__) #elif defined(__aarch64__)
typedef struct TrapFrame
typedef struct
{ {
uint64_t x19; // General purpose uint64_t x19; // General purpose
uint64_t x20; // General purpose uint64_t x20; // General purpose
@ -95,6 +100,7 @@ typedef struct TrapFrame
uint64_t InterruptNumber /* iar_el1 */; // Interrupt Acknowledge Register uint64_t InterruptNumber /* iar_el1 */; // Interrupt Acknowledge Register
} TrapFrame; } TrapFrame;
#endif #endif
#endif // !__FENNIX_API_REGISTERS_H__ #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 __PTRDIFF_TYPE__ ptrdiff_t;
typedef __SIZE_TYPE__ size_t; typedef __SIZE_TYPE__ size_t;
typedef intptr_t ssize_t;
typedef __SIZE_TYPE__ dev_t; #if defined(__LP64__)
typedef __SIZE_TYPE__ off_t; 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_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; typedef int pid_t;
#endif
#define UNUSED(x) (void)(x) #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 TO_PAGES(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE)
#define FROM_PAGES(d) ((d) * 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__ #endif // !__FENNIX_API_TYPES_H__

View File

@ -1,83 +1,22 @@
# Config file # Config files
include ../../../Makefile.conf include ../../../Makefile.conf
include ../../config.mk
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
S_SOURCES = $(shell find ./ -type f -name '*.S') S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c') C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp') CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*))) 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) STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver FILENAME = aip.drv
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
build: $(FILENAME) build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME) mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ) $(FILENAME): $(OBJ)
$(info Linking $@) $(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@ $(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -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 $@ $<
clean: clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ) rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
# Config file # Config file
include ../../Makefile.conf include ../../Makefile.conf
FILENAME = libdriver.a FILENAME = libkernel.so
CC = ../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc CC = ../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++ 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) STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../include INCLUDE_DIR = ../include
LDFLAGS := \ LDFLAGS := -fPIC -fPIE -pie -nostdlib -nodefaultlibs -nolibc \
-fPIC -fPIE -pie \ -zmax-page-size=0x1000 -Wl,-Map libkernel.map -shared
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map driver.map -static -fvisibility=hidden
WARNCFLAG = -Wall -Wextra WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden CFLAGS := -I$(INCLUDE_DIR) -shared
ifeq ($(OSARCH), amd64) ifeq ($(OSARCH), amd64)
@ -46,25 +43,29 @@ CFLAGS += -pipe -fno-builtin -fPIC
endif endif
CRT_CFLAGS := -fPIC -fPIE -pie -mno-red-zone -std=c++20 -I../include
ifeq ($(DEBUG), 1) ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
CRT_CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64) ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm CFLAGS += -fverbose-asm
CRT_CFLAGS += -fverbose-asm
endif endif
ifneq ($(OSARCH), aarch64) ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check CFLAGS += -fstack-check
CRT_CFLAGS += -fstack-check
endif endif
LDFLAGS += -ggdb3 -O0 LDFLAGS += -ggdb3 -O0
endif endif
build: $(FILENAME) 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 mv dcrt0.o ../out/dcrt0.o
$(FILENAME): $(OBJ) $(FILENAME): $(OBJ)
$(info Linking $@) $(info Linking $@)
$(AR) rcs $@ $(OBJ) $(CC) $(LDFLAGS) $(OBJ) -o ../out/$(FILENAME)
mv $(FILENAME) ../out/$(FILENAME)
%.o: %.c $(HEADERS) %.o: %.c $(HEADERS)
$(info Compiling $<) $(info Compiling $<)
@ -79,4 +80,4 @@ $(FILENAME): $(OBJ)
$(AS) -o $@ $< $(AS) -o $@ $<
clean: 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 include ../../../Makefile.conf
include ../../config.mk
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
S_SOURCES = $(shell find ./ -type f -name '*.S') S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c') C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp') CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*))) 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) STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver FILENAME = example.drv
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
build: $(FILENAME) build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME) mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ) $(FILENAME): $(OBJ)
$(info Linking $@) $(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@ $(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -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 $@ $<
clean: clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ) rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -20,16 +20,15 @@
int DriverEntry() int DriverEntry()
{ {
/** This is the main function of the driver. /** 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 * This function should be used to initialize the PCI device
* and allocate resources. * and allocate resources.
*/ */
/* Print a message to the screen */ /* Print a message to the kernel terminal */
KPrint("Hello World from Example Driver!"); KernelPrint("Hello World from Example Driver!");
/* Print a message to the kernel log */ /* 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 */ /* Print a message only if DEBUG is set */
DebugLog("Hello World from Example Driver!"); DebugLog("Hello World from Example Driver!");
@ -52,7 +51,7 @@ int DriverPanic()
{ {
/** This function is called when the kernel panics. /** This function is called when the kernel panics.
* This function should be used to stop the driver from * 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. * safe to do when the kernel panics.
*/ */
@ -63,13 +62,14 @@ int DriverProbe()
{ {
/** This is the first function that is called when the /** This is the first function that is called when the
* driver is loaded. * driver is loaded.
* We can use this function to test if the driver is *
* compatible with the hardware. * This function is to test if the driver is compatible
* Like if we have a specific PCI device or if we have * with the hardware.
* a specific CPU feature. * 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. * 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 * Note: In this function you cannot use variables that
* have constructors or destructors. Before DriverEntry, * have constructors or destructors. Before DriverEntry,
@ -80,8 +80,18 @@ int DriverProbe()
return 0; 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", DriverInfo("example",
"Example Driver", "Example Driver",
"EnderIce2", "EnderIce2",
"0.1", 0, 0, 1,
"GPLv3"); "GPLv3");

View File

@ -1,83 +1,22 @@
# Config file # Config files
include ../../../Makefile.conf include ../../../Makefile.conf
include ../../config.mk
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
S_SOURCES = $(shell find ./ -type f -name '*.S') S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c') C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp') CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*))) 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) STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver FILENAME = vmware.drv
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
build: $(FILENAME) build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME) mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ) $(FILENAME): $(OBJ)
$(info Linking $@) $(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@ $(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -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 $@ $<
clean: clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ) rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -17,11 +17,11 @@
#include <driver.h> #include <driver.h>
#include <errno.h> #include <errno.h>
#include <fs.h>
#include <input.h> #include <input.h>
#include <regs.h> #include <regs.h>
#include <base.h> #include <base.h>
#include <aip.h> #include <aip.h>
#include <vm.h>
#include <io.h> #include <io.h>
enum RPCMessages enum RPCMessages
@ -170,7 +170,7 @@ typedef struct
"r"(bp) : "memory", "cc") "r"(bp) : "memory", "cc")
/* TODO: /* 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 typedef struct
@ -183,6 +183,102 @@ typedef struct
dev_t MouseDevID = -1; 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) static int OpenMessageChannel(ToolboxContext *ctx, uint32_t Protocol)
{ {
uintptr_t ax, bx, cx, dx, si = 0, di = 0; 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) if ((HighWord(cx) & STATUS_SUCCESS) == 0)
{ {
Log("Failed to open message channel %#lx", Protocol); KernelLog("Failed to open message channel %#lx", Protocol);
return -EINVAL; return -EINVAL;
} }
@ -343,8 +439,8 @@ static int MessageSend(ToolboxContext *ctx,
if ((HighWord(cx) & STATUS_SUCCESS) == 0) if ((HighWord(cx) & STATUS_SUCCESS) == 0)
{ {
Log("Failed to send message size for \"%s\": %d", KernelLog("Failed to send message size for \"%s\": %d",
Message, cx); Message, cx);
return -EINVAL; return -EINVAL;
} }
@ -363,14 +459,14 @@ static int MessageSend(ToolboxContext *ctx,
} }
else if ((status & STATUS_CPT) == 0) else if ((status & STATUS_CPT) == 0)
{ {
Log("Checkpoint occurred for message \"%s\"", Message); KernelLog("Checkpoint occurred for message \"%s\"", Message);
continue; continue;
} }
else else
break; break;
} }
Log("Failed to send message \"%s\": %#lx", Message, bx); KernelLog("Failed to send message \"%s\": %#lx", Message, bx);
return -EINVAL; return -EINVAL;
} }
@ -401,12 +497,12 @@ static int MessageReceive(ToolboxContext *ctx,
if ((HighWord(cx) & STATUS_SUCCESS) == 0) if ((HighWord(cx) & STATUS_SUCCESS) == 0)
{ {
Log("Failed to receive message size: %d", cx); KernelLog("Failed to receive message size: %d", cx);
return -EINVAL; return -EINVAL;
} }
else if ((HighWord(cx) & STATUS_DORECV) == 0) else if ((HighWord(cx) & STATUS_DORECV) == 0)
{ {
// Log("No message to receive"); DebugLog("No message to receive");
return -EAGAIN; return -EAGAIN;
} }
@ -427,11 +523,11 @@ static int MessageReceive(ToolboxContext *ctx,
{ {
if ((HighWord(bx) & STATUS_CPT) == 0) if ((HighWord(bx) & STATUS_CPT) == 0)
{ {
Log("Checkpoint occurred for message payload"); KernelLog("Checkpoint occurred for message payload");
continue; continue;
} }
Log("Failed to receive message payload: %d", HighWord(bx)); KernelLog("Failed to receive message payload: %d", HighWord(bx));
FreeMemory(ReplyBuf, ReplyBufPages); FreeMemory(ReplyBuf, ReplyBufPages);
return -EINVAL; return -EINVAL;
} }
@ -451,11 +547,11 @@ static int MessageReceive(ToolboxContext *ctx,
{ {
if ((HighWord(cx) & STATUS_CPT) == 0) if ((HighWord(cx) & STATUS_CPT) == 0)
{ {
Log("Retrying message receive"); KernelLog("Retrying message receive");
continue; continue;
} }
Log("Failed to receive message status: %d", HighWord(cx)); KernelLog("Failed to receive message status: %d", HighWord(cx));
FreeMemory(ReplyBuf, ReplyBufPages); FreeMemory(ReplyBuf, ReplyBufPages);
return -EINVAL; return -EINVAL;
} }
@ -465,7 +561,7 @@ static int MessageReceive(ToolboxContext *ctx,
if (ReplyBuf == NULL) if (ReplyBuf == NULL)
{ {
Log("Failed to receive message"); KernelLog("Failed to receive message");
return -EINVAL; return -EINVAL;
} }
@ -481,14 +577,14 @@ static int SendRPCI(ToolboxContext *, const char *Request)
int status = OpenMessageChannel(&rpci_ctx, MESSAGE_RPCI); int status = OpenMessageChannel(&rpci_ctx, MESSAGE_RPCI);
if (status < 0) if (status < 0)
{ {
Log("Failed to open RPCI channel: %d", status); KernelLog("Failed to open RPCI channel: %d", status);
return status; return status;
} }
status = MessageSend(&rpci_ctx, Request); status = MessageSend(&rpci_ctx, Request);
if (status < 0) if (status < 0)
{ {
Log("Failed to send RPCI request: %d", status); KernelLog("Failed to send RPCI request: %d", status);
return status; return status;
} }
@ -524,7 +620,7 @@ static int DisplayGetSize(ToolboxContext *ctx)
} }
else if (status < 0) else if (status < 0)
{ {
Log("Failed to receive message"); KernelLog("Failed to receive message");
return 1; return 1;
} }
@ -579,7 +675,7 @@ void DisplayScaleThread()
while (true) while (true)
{ {
if (DisplayGetSize(tb_ctx) != 0) if (DisplayGetSize(tb_ctx) != 0)
Log("Failed to scale display"); KernelLog("Failed to scale display");
Sleep(1000); Sleep(1000);
} }
} }
@ -627,6 +723,7 @@ void Relative()
CommandSend(&cmd); CommandSend(&cmd);
} }
InputReport ir = {0};
void InterruptHandler(TrapFrame *) void InterruptHandler(TrapFrame *)
{ {
uint8_t Data = inb(0x60); uint8_t Data = inb(0x60);
@ -639,7 +736,7 @@ void InterruptHandler(TrapFrame *)
if (cmd.ax == 0xFFFF0000) if (cmd.ax == 0xFFFF0000)
{ {
Log("VMware mouse is not connected?"); KernelLog("VMware mouse is not connected?");
Relative(); Relative();
Absolute(); Absolute();
return; return;
@ -654,17 +751,6 @@ void InterruptHandler(TrapFrame *)
int Buttons = (cmd.ax & 0xFFFF); 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? * How should I handle this?
* (cmd.[bx,cx] * Width) / 0xFFFF * (cmd.[bx,cx] * Width) / 0xFFFF
@ -672,9 +758,44 @@ void InterruptHandler(TrapFrame *)
*/ */
uintptr_t AbsoluteX = cmd.bx; uintptr_t AbsoluteX = cmd.bx;
uintptr_t AbsoluteY = cmd.cx; 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; bool ToolboxSupported = false;
int DriverEntry() int DriverEntry()
{ {
@ -711,7 +832,8 @@ int DriverEntry()
* override its interrupt handler. * override its interrupt handler.
*/ */
OverrideInterruptHandler(12, InterruptHandler); OverrideInterruptHandler(12, InterruptHandler);
MouseDevID = RegisterInputDevice(ddt_Mouse);
MouseDevID = RegisterDevice(INPUT_TYPE_MOUSE, &MouseOps);
return 0; return 0;
} }
@ -721,7 +843,8 @@ int DriverFinal()
PS2WriteData(PS2_MOUSE_CMD_DISABLE_DATA_REPORTING); PS2WriteData(PS2_MOUSE_CMD_DISABLE_DATA_REPORTING);
Relative(); Relative();
UnregisterInputDevice(MouseDevID, ddt_Mouse);
UnregisterDevice(MouseDevID);
if (ToolboxSupported) if (ToolboxSupported)
{ {
@ -751,5 +874,5 @@ int DriverProbe()
DriverInfo("vmware", DriverInfo("vmware",
"VMware Tools Driver", "VMware Tools Driver",
"EnderIce2", "EnderIce2",
"0.1", 0, 0, 1,
"GPLv3"); "GPLv3");

View File

@ -1,83 +1,22 @@
# Config file # Config files
include ../../../Makefile.conf include ../../../Makefile.conf
include ../../config.mk
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
S_SOURCES = $(shell find ./ -type f -name '*.S') S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c') C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp') CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*))) 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) STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver FILENAME = e1000.drv
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
build: $(FILENAME) build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME) mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ) $(FILENAME): $(OBJ)
$(info Linking $@) $(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@ $(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -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 $@ $<
clean: clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ) rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -20,7 +20,7 @@
#include <regs.h> #include <regs.h>
#include <base.h> #include <base.h>
#include <pci.h> #include <pci.h>
#include <net.h> #include <network.h>
#include <io.h> #include <io.h>
#include "e1000.hpp" #include "e1000.hpp"
@ -205,7 +205,7 @@ public:
mac.Address[i] = BaseMac8[i]; mac.Address[i] = BaseMac8[i];
else else
{ {
Log("No MAC address found."); KernelLog("No MAC address found.");
return MediaAccessControl(); return MediaAccessControl();
} }
} }
@ -240,7 +240,11 @@ public:
uint8_t *data = (uint8_t *)RX[RXCurrent]->Address; uint8_t *data = (uint8_t *)RX[RXCurrent]->Address;
uint16_t dataSz = RX[RXCurrent]->Length; 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; RX[RXCurrent]->Status = 0;
uint16_t OldRXCurrent = RXCurrent; uint16_t OldRXCurrent = RXCurrent;
@ -270,7 +274,7 @@ public:
{ {
case 0x100E: case 0x100E:
{ {
Log("Found Intel 82540EM Gigabit Ethernet Controller."); KernelLog("Found Intel 82540EM Gigabit Ethernet Controller.");
/* Detect EEPROM */ /* Detect EEPROM */
WriteCMD(REG::EEPROM, 0x1); WriteCMD(REG::EEPROM, 0x1);
@ -282,7 +286,7 @@ public:
if (!GetMAC().Valid()) if (!GetMAC().Valid())
{ {
Log("Failed to get MAC"); KernelLog("Failed to get MAC");
return; return;
} }
@ -303,7 +307,7 @@ public:
} }
default: default:
{ {
Log("Unimplemented E1000 device."); KernelLog("Unimplemented E1000 device.");
return; return;
} }
} }
@ -343,7 +347,7 @@ public:
} }
default: default:
{ {
Log("Unimplemented E1000 device."); KernelLog("Unimplemented E1000 device.");
return; return;
} }
} }
@ -351,7 +355,7 @@ public:
}; };
E1000Device *Drivers[4] = {nullptr}; E1000Device *Drivers[4] = {nullptr};
dev_t AudioID[4] = {0}; dev_t NetID[4] = {(dev_t)-1};
#define OIR(x) OIR_##x #define OIR(x) OIR_##x
#define CREATE_OIR(x) \ #define CREATE_OIR(x) \
@ -362,20 +366,40 @@ CREATE_OIR(1);
CREATE_OIR(2); CREATE_OIR(2);
CREATE_OIR(3); CREATE_OIR(3);
int drvOpen(dev_t, dev_t, int, mode_t) { return 0; } int __fs_Open(struct Inode *, int, mode_t) { return 0; }
int drvClose(dev_t, dev_t) { return 0; } int __fs_Close(struct Inode *) { return 0; }
size_t drvRead(dev_t, dev_t, uint8_t *, size_t, off_t) { 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; PCIArray *Devices;
EXTERNC int cxx_Panic() EXTERNC int cxx_Panic()
{ {
@ -402,10 +426,10 @@ EXTERNC int cxx_Probe()
0x10EA, /* I217-LM */ 0x10EA, /* I217-LM */
0x153A, /* 82577LM */ 0x153A, /* 82577LM */
PCI_END}; PCI_END};
Devices = FindPCIDevices(VendorIDs, DeviceIDs); Devices = GetPCIDevices(VendorIDs, DeviceIDs);
if (Devices == nullptr) if (Devices == nullptr)
{ {
Log("No E1000 device found."); KernelLog("No E1000 device found.");
return -ENODEV; return -ENODEV;
} }
return 0; return 0;
@ -427,11 +451,8 @@ EXTERNC int cxx_Initialize()
if (Drivers[Count]->IsInitialized()) if (Drivers[Count]->IsInitialized())
{ {
dev_t ret = RegisterNetDevice(ddt_Network, dev_t ret = RegisterDevice(NETWORK_TYPE_ETHERNET, &NetOps);
drvOpen, drvClose, NetID[Count] = ret;
drvRead, drvWrite,
drvIoctl);
AudioID[Count] = ret;
Drivers[Count]->ID = ret; Drivers[Count]->ID = ret;
/* FIXME: bad code */ /* FIXME: bad code */
@ -460,7 +481,7 @@ EXTERNC int cxx_Initialize()
if (Count == 0) if (Count == 0)
{ {
Log("No valid E1000 device found."); KernelLog("No valid E1000 device found.");
return -EINVAL; return -EINVAL;
} }
@ -481,5 +502,11 @@ EXTERNC int cxx_Finalize()
ctx = (PCIArray *)ctx->Next; 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; return 0;
} }

View File

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

View File

@ -1,83 +1,22 @@
# Config file # Config files
include ../../../Makefile.conf include ../../../Makefile.conf
include ../../config.mk
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
S_SOURCES = $(shell find ./ -type f -name '*.S') S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c') C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp') CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*))) 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) STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver FILENAME = rtl8139.drv
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
build: $(FILENAME) build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME) mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ) $(FILENAME): $(OBJ)
$(info Linking $@) $(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@ $(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -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 $@ $<
clean: clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ) rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

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

View File

@ -20,7 +20,7 @@
#include <regs.h> #include <regs.h>
#include <base.h> #include <base.h>
#include <pci.h> #include <pci.h>
#include <net.h> #include <network.h>
#include <io.h> #include <io.h>
#include "rtl8139.hpp" #include "rtl8139.hpp"
@ -99,7 +99,11 @@ public:
uint16_t dataSz = *(data + 1); uint16_t dataSz = *(data + 1);
data += 2; data += 2;
ReportNetworkPacket(ID, data, dataSz); // ReportNetworkPacket(ID, data, dataSz);
/* FIXME: Implement */
KernelLog("FIXME: Received packet");
(void)data;
(void)dataSz;
/* Update CAPR */ /* Update CAPR */
#define RX_READ_PTR_MASK (~0x3) #define RX_READ_PTR_MASK (~0x3)
@ -169,7 +173,7 @@ public:
}; };
RTL8139Device *Drivers[4] = {nullptr}; RTL8139Device *Drivers[4] = {nullptr};
dev_t AudioID[4] = {0}; dev_t NetID[4] = {(dev_t)-1};
#define OIR(x) OIR_##x #define OIR(x) OIR_##x
#define CREATE_OIR(x) \ #define CREATE_OIR(x) \
@ -180,20 +184,40 @@ CREATE_OIR(1);
CREATE_OIR(2); CREATE_OIR(2);
CREATE_OIR(3); CREATE_OIR(3);
int drvOpen(dev_t, dev_t, int, mode_t) { return 0; } int __fs_Open(struct Inode *, int, mode_t) { return 0; }
int drvClose(dev_t, dev_t) { return 0; } int __fs_Close(struct Inode *) { return 0; }
size_t drvRead(dev_t, dev_t, uint8_t *, size_t, off_t) { 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; PCIArray *Devices;
EXTERNC int cxx_Panic() EXTERNC int cxx_Panic()
{ {
@ -216,10 +240,10 @@ EXTERNC int cxx_Probe()
PCI_END}; PCI_END};
uint16_t DeviceIDs[] = {0x8139, /* RTL8139 */ uint16_t DeviceIDs[] = {0x8139, /* RTL8139 */
PCI_END}; PCI_END};
Devices = FindPCIDevices(VendorIDs, DeviceIDs); Devices = GetPCIDevices(VendorIDs, DeviceIDs);
if (Devices == nullptr) if (Devices == nullptr)
{ {
Log("No RTL8139 device found."); KernelLog("No RTL8139 device found.");
return -ENODEV; return -ENODEV;
} }
return 0; return 0;
@ -240,11 +264,8 @@ EXTERNC int cxx_Initialize()
if (Drivers[Count]->IsInitialized()) if (Drivers[Count]->IsInitialized())
{ {
dev_t ret = RegisterNetDevice(ddt_Network, dev_t ret = RegisterDevice(NETWORK_TYPE_ETHERNET, &NetOps);
drvOpen, drvClose, NetID[Count] = ret;
drvRead, drvWrite,
drvIoctl);
AudioID[Count] = ret;
Drivers[Count]->ID = ret; Drivers[Count]->ID = ret;
/* FIXME: bad code */ /* FIXME: bad code */
@ -273,7 +294,7 @@ EXTERNC int cxx_Initialize()
if (Count == 0) if (Count == 0)
{ {
Log("No valid RTL8139 device found."); KernelLog("No valid RTL8139 device found.");
return -EINVAL; return -EINVAL;
} }
@ -294,5 +315,11 @@ EXTERNC int cxx_Finalize()
ctx = (PCIArray *)ctx->Next; 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; return 0;
} }

View File

@ -1,83 +1,22 @@
# Config file # Config files
include ../../../Makefile.conf include ../../../Makefile.conf
include ../../config.mk
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
S_SOURCES = $(shell find ./ -type f -name '*.S') S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c') C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp') CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*))) 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) STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver FILENAME = ahci.drv
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
build: $(FILENAME) build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME) mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ) $(FILENAME): $(OBJ)
$(info Linking $@) $(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@ $(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -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 $@ $<
clean: clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ) rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

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

View File

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

View File

@ -1,83 +1,22 @@
# Config file # Config files
include ../../../Makefile.conf include ../../../Makefile.conf
include ../../config.mk
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
S_SOURCES = $(shell find ./ -type f -name '*.S') S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c') C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp') CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*))) 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) STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver FILENAME = ata.drv
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
build: $(FILENAME) build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME) mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ) $(FILENAME): $(OBJ)
$(info Linking $@) $(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@ $(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -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 $@ $<
clean: clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ) rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

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