diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/src/kernel/drivers/interrupts/irqs.c b/src/kernel/drivers/interrupts/irqs.c index 60d95f8..1cd8c79 100644 --- a/src/kernel/drivers/interrupts/irqs.c +++ b/src/kernel/drivers/interrupts/irqs.c @@ -61,7 +61,7 @@ return; } if (irqNumber == 7 || irqNumber == 2) { - // irq2 should not be fired, irq 7 is a spurious irq + // irq2 should not be fired, irq 7 indicates a spurious irq return; } printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber); diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/src/kernel/drivers/interrupts/irqs.c b/src/kernel/drivers/interrupts/irqs.c index 60d95f8..1cd8c79 100644 --- a/src/kernel/drivers/interrupts/irqs.c +++ b/src/kernel/drivers/interrupts/irqs.c @@ -61,7 +61,7 @@ return; } if (irqNumber == 7 || irqNumber == 2) { - // irq2 should not be fired, irq 7 is a spurious irq + // irq2 should not be fired, irq 7 indicates a spurious irq return; } printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber); diff --git a/src/kernel/drivers/interrupts/keyboard/keyboard.c b/src/kernel/drivers/interrupts/keyboard/keyboard.c index 94b3dad..99fdd04 100644 --- a/src/kernel/drivers/interrupts/keyboard/keyboard.c +++ b/src/kernel/drivers/interrupts/keyboard/keyboard.c @@ -77,6 +77,7 @@ message->type = KEYBOARD_STRING; message->size = strlen(message->data); listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); return; } if (scancode & 0x80) { @@ -96,15 +97,16 @@ } void *data = NULL; if (modifiers & MODIFIER_LEFT_SHIFT || modifiers & MODIFIER_RIGHT_SHIFT) { - data = capitalKeycodes[scancode]; + data = (void *)(uint32_t)capitalKeycodes[scancode]; } else { - data = keycodes[scancode]; + data = (void *)(uint32_t)keycodes[scancode]; } Message *message = malloc(sizeof(Message)); message->data = data; message->size = 1; message->type = KEYBOARD_CHAR; listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); } void setupKeyboard() { setIRQHandler(1, &keyboardHandler); } diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/src/kernel/drivers/interrupts/irqs.c b/src/kernel/drivers/interrupts/irqs.c index 60d95f8..1cd8c79 100644 --- a/src/kernel/drivers/interrupts/irqs.c +++ b/src/kernel/drivers/interrupts/irqs.c @@ -61,7 +61,7 @@ return; } if (irqNumber == 7 || irqNumber == 2) { - // irq2 should not be fired, irq 7 is a spurious irq + // irq2 should not be fired, irq 7 indicates a spurious irq return; } printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber); diff --git a/src/kernel/drivers/interrupts/keyboard/keyboard.c b/src/kernel/drivers/interrupts/keyboard/keyboard.c index 94b3dad..99fdd04 100644 --- a/src/kernel/drivers/interrupts/keyboard/keyboard.c +++ b/src/kernel/drivers/interrupts/keyboard/keyboard.c @@ -77,6 +77,7 @@ message->type = KEYBOARD_STRING; message->size = strlen(message->data); listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); return; } if (scancode & 0x80) { @@ -96,15 +97,16 @@ } void *data = NULL; if (modifiers & MODIFIER_LEFT_SHIFT || modifiers & MODIFIER_RIGHT_SHIFT) { - data = capitalKeycodes[scancode]; + data = (void *)(uint32_t)capitalKeycodes[scancode]; } else { - data = keycodes[scancode]; + data = (void *)(uint32_t)keycodes[scancode]; } Message *message = malloc(sizeof(Message)); message->data = data; message->size = 1; message->type = KEYBOARD_CHAR; listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); } void setupKeyboard() { setIRQHandler(1, &keyboardHandler); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index e57a651..35addee 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -27,14 +27,20 @@ #define CMD_COUNTER0 0x00 #define CMD_COUNTER2 0x80 -void setTimerFreq(uint32_t hz) { +void sleep(uint16_t millis) { + uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + getCurrentTask()->ticksLeft = millis; + yield(); +} + +void setTimerFrequency(uint32_t hz) { int divisor = PIT_SCALE / hz; outb(PIT_CONTROL, CMD_BINARY | CMD_MODE3 | CMD_RW_BOTH | CMD_COUNTER0); outb(PIT_A, (uint8_t)divisor); outb(PIT_A, (uint8_t)(divisor >> 8)); } -uint64_t timerMillis = 0; +uint32_t timerMillis = 0; void timerHandler() { timerMillis++; @@ -59,7 +65,6 @@ } void setupTimer() { - printf("setting timer frequency to 1kHz\n"); - setTimerFreq(1000); + setTimerFrequency(1000); setIRQHandler(0, &timerHandler); } diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/src/kernel/drivers/interrupts/irqs.c b/src/kernel/drivers/interrupts/irqs.c index 60d95f8..1cd8c79 100644 --- a/src/kernel/drivers/interrupts/irqs.c +++ b/src/kernel/drivers/interrupts/irqs.c @@ -61,7 +61,7 @@ return; } if (irqNumber == 7 || irqNumber == 2) { - // irq2 should not be fired, irq 7 is a spurious irq + // irq2 should not be fired, irq 7 indicates a spurious irq return; } printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber); diff --git a/src/kernel/drivers/interrupts/keyboard/keyboard.c b/src/kernel/drivers/interrupts/keyboard/keyboard.c index 94b3dad..99fdd04 100644 --- a/src/kernel/drivers/interrupts/keyboard/keyboard.c +++ b/src/kernel/drivers/interrupts/keyboard/keyboard.c @@ -77,6 +77,7 @@ message->type = KEYBOARD_STRING; message->size = strlen(message->data); listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); return; } if (scancode & 0x80) { @@ -96,15 +97,16 @@ } void *data = NULL; if (modifiers & MODIFIER_LEFT_SHIFT || modifiers & MODIFIER_RIGHT_SHIFT) { - data = capitalKeycodes[scancode]; + data = (void *)(uint32_t)capitalKeycodes[scancode]; } else { - data = keycodes[scancode]; + data = (void *)(uint32_t)keycodes[scancode]; } Message *message = malloc(sizeof(Message)); message->data = data; message->size = 1; message->type = KEYBOARD_CHAR; listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); } void setupKeyboard() { setIRQHandler(1, &keyboardHandler); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index e57a651..35addee 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -27,14 +27,20 @@ #define CMD_COUNTER0 0x00 #define CMD_COUNTER2 0x80 -void setTimerFreq(uint32_t hz) { +void sleep(uint16_t millis) { + uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + getCurrentTask()->ticksLeft = millis; + yield(); +} + +void setTimerFrequency(uint32_t hz) { int divisor = PIT_SCALE / hz; outb(PIT_CONTROL, CMD_BINARY | CMD_MODE3 | CMD_RW_BOTH | CMD_COUNTER0); outb(PIT_A, (uint8_t)divisor); outb(PIT_A, (uint8_t)(divisor >> 8)); } -uint64_t timerMillis = 0; +uint32_t timerMillis = 0; void timerHandler() { timerMillis++; @@ -59,7 +65,6 @@ } void setupTimer() { - printf("setting timer frequency to 1kHz\n"); - setTimerFreq(1000); + setTimerFrequency(1000); setIRQHandler(0, &timerHandler); } diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c new file mode 100644 index 0000000..ea36871 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -0,0 +1,291 @@ +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +#define IDE_DATA_REGISTER 0 +#define IDE_ERROR_REGISTER 1 +#define IDE_SECTOR_COUNT_REGISTER 2 +#define IDE_SECTOR_NUMBER_REGISTER 3 +#define IDE_CYLINDER_LOW_REGISTER 4 +#define IDE_CYLINDER_HIGH_REGISTER 5 +// sector size, drive, head +#define IDE_SDH_REGISTER 6 +#define IDE_STATUS_REGISTER 7 +#define IDE_COMMAND_REGISTER 7 +#define IDE_ALTERNATE_STATUS_CONTROL_REGISTER 0 +#define IDE_DRIVE_ADDRESS_CONTROL_REGISTER 1 + +#define IDE_STATUS_BUSY 0x80 +#define IDE_STATUS_READY 0x40 +#define IDE_STATUS_WRITE_FAULT 0x20 +#define IDE_STATUS_SEEK_COMPLETE 0x10 +#define IDE_STATUS_DATA_REQUEST 0x08 +#define IDE_STATUS_CORRECTED_DATA 0x04 +#define IDE_STATUS_INDEX 0x02 +#define IDE_STATUS_ERROR 0x01 + +#define IDE_IDENTIFY_COMMAND 0xEC + +char *driveTypes[] = { + "ISA Compatibility mode-only controller", + "PCI native mode-only controller", + "ISA Compatibility mode controller", + "PCI native mode controller", +}; + +void setupIDEChannels(IdeChannels *channels, PciDevice *pciDevice) { + if (pciDevice->programmingInterface & 0x01) { + channels->base = pciDevice->bar0; + channels->control = pciDevice->bar1; + } else { + channels->base = 0x1F0; + channels->control = 0x3F6; + } + if (pciDevice->programmingInterface & 0x04) { + channels[1].base = pciDevice->bar2; + channels[1].control = pciDevice->bar3; + } else { + channels[1].base = 0x170; + channels[1].control = 0x376; + } +} + +void ideWriteControlRegister(IdeChannels *channel, uint8_t reg, uint8_t data) { + outb(channel->control + reg, data); +} + +void ideWriteRegister(IdeChannels *channel, uint8_t reg, uint16_t data) { + outb(channel->base + reg, data); + if (data > 0xFF) { + // set higher half bit in the control register + outb(channel->control, 0x0A); + outb(channel->base + reg, data >> 8); + outb(channel->control, 0x02); + } +} + +uint8_t ideReadControlRegister(IdeChannels *channel, uint8_t reg) { + return inb(channel->control + reg); +} + +uint8_t ideReadRegister(IdeChannels *channel, uint16_t reg) { + return inw(channel->base + reg); +} + +void ideReadBuffer(IdeChannels *channel, uint32_t *data) { + for (uint16_t i = 0; i < 128; i++) { + data[i] = ini(channel->base + IDE_DATA_REGISTER); + } +} + +void printError(uint16_t); + +void ideWaitUntilNotBusy(IdeChannels *channel, bool checkErrors) { + for (uint8_t i = 0; i < 4; i++) { + ideReadControlRegister(channel, 0); + } + uint16_t status = ideReadRegister(channel, IDE_STATUS_REGISTER); + while (status & IDE_STATUS_BUSY) { + status = ideReadRegister(channel, IDE_STATUS_REGISTER); + } + if (checkErrors && status & IDE_STATUS_ERROR) { + printf("encountered an error\n"); + printError(ideReadRegister(channel, IDE_ERROR_REGISTER)); + } +} + +void ideCommand(IdeChannels *channel, uint8_t command) { + ideWaitUntilNotBusy(channel, false); + ideWriteRegister(channel, IDE_COMMAND_REGISTER, command); +} + +#define CHANNEL &channels[channel] + +void initializeIDEDrive(PciDevice *pciDevice, ListElement **drives) { + uint8_t *buffer = malloc(2048); + IdeChannels *channels = malloc(sizeof(IdeChannels) * 2); + setupIDEChannels(channels, pciDevice); + for (uint8_t channel = 0; channel < 2; channel++) { + if (ideReadRegister(CHANNEL, IDE_STATUS_REGISTER) == 0) { + // no device + continue; + } + ideWriteControlRegister(CHANNEL, IDE_ALTERNATE_STATUS_CONTROL_REGISTER, + 2); + for (uint8_t drive = 0; drive < 2; drive++) { + ideWaitUntilNotBusy(CHANNEL, true); + // set the drive + ideWriteRegister(CHANNEL, IDE_SDH_REGISTER, 0xA0 | (drive << 4)); + ideWriteRegister(CHANNEL, IDE_SECTOR_COUNT_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_SECTOR_NUMBER_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_LOW_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_HIGH_REGISTER, 0); + ideCommand(CHANNEL, IDE_IDENTIFY_COMMAND); + ideWaitUntilNotBusy(CHANNEL, true); + ideReadBuffer(CHANNEL, (void *)buffer); + if (*((uint16_t *)buffer) == 0) { + // any bit has to be set if it is a real device + continue; + } + char *model = malloc(41); + for (int i = 0; i < 40; i += 2) { + *((uint16_t *)&model[i]) = buffer[54 + i + 1]; + *((uint16_t *)&model[i + 1]) = buffer[54 + i]; + } + model[40] = 0; + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->model = model; + hardDrive->channels = CHANNEL; + hardDrive->channel = channel; + hardDrive->drive = drive; + hardDrive->type = *(uint16_t *)buffer; + hardDrive->cylinders = *(uint16_t *)buffer + 2; + hardDrive->heads = *(uint16_t *)buffer + 6; + hardDrive->sectors = *(uint16_t *)buffer + 12; + hardDrive->capabilities = *(uint16_t *)buffer + 98; + hardDrive->commandSets = *(uint32_t *)(buffer + 164); + if (hardDrive->commandSets + (1 << 26)) { + hardDrive->size = *(uint32_t *)buffer + 200; + } else { + hardDrive->size = *(uint32_t *)buffer + 120; + } + listAdd(drives, hardDrive); + printf("found a hard drive %i bytes, %i:%i, model: %s\n", + hardDrive->size, channel, drive, model); + } + } + free(buffer); +} + +void printError(uint16_t status) { + if (status & 0x01) { + printf("No address mark\n"); + } + if (status & 0x02) { + printf("Track 0 not found\n"); + } + if (status & 0x04) { + printf("command aborted\n"); + } + if (status & 0x08) { + printf("Media change request\n"); + } + if (status & 0x10) { + printf("ID mark not found\n"); + } + if (status & 0x20) { + printf("Media changed\n"); + } + if (status & 0x40) { + printf("uncorrectable data\n"); + } + if (status & 0x80) { + printf("bad block\n"); + } +} + +void driveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, + uint8_t sectorCount, uint8_t direction) { + uint8_t accessMode = 0, head = 0, sector = 0, cylinder = 0; + uint32_t lbaIo[6] = {0, 0, 0, 0, 0, 0}; + if (lba >= 0x10000000) { + accessMode = 2; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x0000FF00) >> 8; + lbaIo[2] = (lba & 0x00FF0000) >> 16; + lbaIo[3] = (lba & 0xFF000000) >> 24; + } else if (hardDrive->capabilities & 0x200) { + accessMode = 1; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x000FF00) >> 8; + lbaIo[2] = (lba & 0x0FF0000) >> 16; + head = (lba & 0xF000000) >> 24; + } else { + sector = (lba % 63) + 1; + cylinder = (lba + 1 - sector) / (16 * 63); + lbaIo[0] = sector; + lbaIo[1] = (uint8_t)cylinder; + lbaIo[2] = (cylinder >> 8) & 0xFF; + head = (lba + 1 - sector) % (16 * 63) / (63); + } + ideWaitUntilNotBusy(hardDrive->channels, true); + if (accessMode == 0) { + // chs + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xA0 | (hardDrive->drive << 4)); + } else { + // lba + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xE0 | (hardDrive->drive << 4) | head); + } + ideWriteRegister(hardDrive->channels, IDE_SECTOR_COUNT_REGISTER, + sectorCount); + ideWriteRegister(hardDrive->channels, IDE_SECTOR_NUMBER_REGISTER, + lbaIo[3] << 8 | lbaIo[0]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_LOW_REGISTER, + lbaIo[4] << 8 | lbaIo[1]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_HIGH_REGISTER, + lbaIo[5] << 8 | lbaIo[2]); + uint8_t command = 0; + if (direction == 0) { + // read + if (accessMode == 2) { + command = 0x24; + } else { + command = 0x20; + } + } else { + // write + if (accessMode == 2) { + command = 0x34; + } else { + command = 0x30; + } + } + ideCommand(hardDrive->channels, command); + ideWaitUntilNotBusy(hardDrive->channels, true); + if (direction == 0) { + uint16_t status; + void *current = buffer; + for (uint8_t i = 0; i < sectorCount; i++) { + ideWaitUntilNotBusy(hardDrive->channels, true); + ideReadBuffer(hardDrive->channels, (void *)buffer); + } + } +} + +void initializeSATADrive(PciDevice *pciDevice) { + // todo +} + +void scanHardDrives() { + ListElement *drives = NULL; + for (ListElement *current = *getPciDevices(); current; + current = current->next) { + PciDevice *pciDevice = current->data; + if (pciDevice->class != 1) { + continue; + } + switch (pciDevice->subclass) { + case 1: + initializeIDEDrive(pciDevice, &drives); + break; + case 6: + printf("found a SATA-controller: %i:%i:%i\n", pciDevice->bus, + pciDevice->device, pciDevice->function); + initializeSATADrive(pciDevice); + break; + } + } + void *buffer = malloc(2000); + for (ListElement *current = drives; current; current = current->next) { + driveAccess(current->data, 0, buffer, 1, 0); + printf("data: %x %x %s\n", *(uint32_t *)buffer, + *((uint32_t *)buffer + 1), buffer); + } + free(buffer); +} diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/src/kernel/drivers/interrupts/irqs.c b/src/kernel/drivers/interrupts/irqs.c index 60d95f8..1cd8c79 100644 --- a/src/kernel/drivers/interrupts/irqs.c +++ b/src/kernel/drivers/interrupts/irqs.c @@ -61,7 +61,7 @@ return; } if (irqNumber == 7 || irqNumber == 2) { - // irq2 should not be fired, irq 7 is a spurious irq + // irq2 should not be fired, irq 7 indicates a spurious irq return; } printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber); diff --git a/src/kernel/drivers/interrupts/keyboard/keyboard.c b/src/kernel/drivers/interrupts/keyboard/keyboard.c index 94b3dad..99fdd04 100644 --- a/src/kernel/drivers/interrupts/keyboard/keyboard.c +++ b/src/kernel/drivers/interrupts/keyboard/keyboard.c @@ -77,6 +77,7 @@ message->type = KEYBOARD_STRING; message->size = strlen(message->data); listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); return; } if (scancode & 0x80) { @@ -96,15 +97,16 @@ } void *data = NULL; if (modifiers & MODIFIER_LEFT_SHIFT || modifiers & MODIFIER_RIGHT_SHIFT) { - data = capitalKeycodes[scancode]; + data = (void *)(uint32_t)capitalKeycodes[scancode]; } else { - data = keycodes[scancode]; + data = (void *)(uint32_t)keycodes[scancode]; } Message *message = malloc(sizeof(Message)); message->data = data; message->size = 1; message->type = KEYBOARD_CHAR; listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); } void setupKeyboard() { setIRQHandler(1, &keyboardHandler); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index e57a651..35addee 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -27,14 +27,20 @@ #define CMD_COUNTER0 0x00 #define CMD_COUNTER2 0x80 -void setTimerFreq(uint32_t hz) { +void sleep(uint16_t millis) { + uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + getCurrentTask()->ticksLeft = millis; + yield(); +} + +void setTimerFrequency(uint32_t hz) { int divisor = PIT_SCALE / hz; outb(PIT_CONTROL, CMD_BINARY | CMD_MODE3 | CMD_RW_BOTH | CMD_COUNTER0); outb(PIT_A, (uint8_t)divisor); outb(PIT_A, (uint8_t)(divisor >> 8)); } -uint64_t timerMillis = 0; +uint32_t timerMillis = 0; void timerHandler() { timerMillis++; @@ -59,7 +65,6 @@ } void setupTimer() { - printf("setting timer frequency to 1kHz\n"); - setTimerFreq(1000); + setTimerFrequency(1000); setIRQHandler(0, &timerHandler); } diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c new file mode 100644 index 0000000..ea36871 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -0,0 +1,291 @@ +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +#define IDE_DATA_REGISTER 0 +#define IDE_ERROR_REGISTER 1 +#define IDE_SECTOR_COUNT_REGISTER 2 +#define IDE_SECTOR_NUMBER_REGISTER 3 +#define IDE_CYLINDER_LOW_REGISTER 4 +#define IDE_CYLINDER_HIGH_REGISTER 5 +// sector size, drive, head +#define IDE_SDH_REGISTER 6 +#define IDE_STATUS_REGISTER 7 +#define IDE_COMMAND_REGISTER 7 +#define IDE_ALTERNATE_STATUS_CONTROL_REGISTER 0 +#define IDE_DRIVE_ADDRESS_CONTROL_REGISTER 1 + +#define IDE_STATUS_BUSY 0x80 +#define IDE_STATUS_READY 0x40 +#define IDE_STATUS_WRITE_FAULT 0x20 +#define IDE_STATUS_SEEK_COMPLETE 0x10 +#define IDE_STATUS_DATA_REQUEST 0x08 +#define IDE_STATUS_CORRECTED_DATA 0x04 +#define IDE_STATUS_INDEX 0x02 +#define IDE_STATUS_ERROR 0x01 + +#define IDE_IDENTIFY_COMMAND 0xEC + +char *driveTypes[] = { + "ISA Compatibility mode-only controller", + "PCI native mode-only controller", + "ISA Compatibility mode controller", + "PCI native mode controller", +}; + +void setupIDEChannels(IdeChannels *channels, PciDevice *pciDevice) { + if (pciDevice->programmingInterface & 0x01) { + channels->base = pciDevice->bar0; + channels->control = pciDevice->bar1; + } else { + channels->base = 0x1F0; + channels->control = 0x3F6; + } + if (pciDevice->programmingInterface & 0x04) { + channels[1].base = pciDevice->bar2; + channels[1].control = pciDevice->bar3; + } else { + channels[1].base = 0x170; + channels[1].control = 0x376; + } +} + +void ideWriteControlRegister(IdeChannels *channel, uint8_t reg, uint8_t data) { + outb(channel->control + reg, data); +} + +void ideWriteRegister(IdeChannels *channel, uint8_t reg, uint16_t data) { + outb(channel->base + reg, data); + if (data > 0xFF) { + // set higher half bit in the control register + outb(channel->control, 0x0A); + outb(channel->base + reg, data >> 8); + outb(channel->control, 0x02); + } +} + +uint8_t ideReadControlRegister(IdeChannels *channel, uint8_t reg) { + return inb(channel->control + reg); +} + +uint8_t ideReadRegister(IdeChannels *channel, uint16_t reg) { + return inw(channel->base + reg); +} + +void ideReadBuffer(IdeChannels *channel, uint32_t *data) { + for (uint16_t i = 0; i < 128; i++) { + data[i] = ini(channel->base + IDE_DATA_REGISTER); + } +} + +void printError(uint16_t); + +void ideWaitUntilNotBusy(IdeChannels *channel, bool checkErrors) { + for (uint8_t i = 0; i < 4; i++) { + ideReadControlRegister(channel, 0); + } + uint16_t status = ideReadRegister(channel, IDE_STATUS_REGISTER); + while (status & IDE_STATUS_BUSY) { + status = ideReadRegister(channel, IDE_STATUS_REGISTER); + } + if (checkErrors && status & IDE_STATUS_ERROR) { + printf("encountered an error\n"); + printError(ideReadRegister(channel, IDE_ERROR_REGISTER)); + } +} + +void ideCommand(IdeChannels *channel, uint8_t command) { + ideWaitUntilNotBusy(channel, false); + ideWriteRegister(channel, IDE_COMMAND_REGISTER, command); +} + +#define CHANNEL &channels[channel] + +void initializeIDEDrive(PciDevice *pciDevice, ListElement **drives) { + uint8_t *buffer = malloc(2048); + IdeChannels *channels = malloc(sizeof(IdeChannels) * 2); + setupIDEChannels(channels, pciDevice); + for (uint8_t channel = 0; channel < 2; channel++) { + if (ideReadRegister(CHANNEL, IDE_STATUS_REGISTER) == 0) { + // no device + continue; + } + ideWriteControlRegister(CHANNEL, IDE_ALTERNATE_STATUS_CONTROL_REGISTER, + 2); + for (uint8_t drive = 0; drive < 2; drive++) { + ideWaitUntilNotBusy(CHANNEL, true); + // set the drive + ideWriteRegister(CHANNEL, IDE_SDH_REGISTER, 0xA0 | (drive << 4)); + ideWriteRegister(CHANNEL, IDE_SECTOR_COUNT_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_SECTOR_NUMBER_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_LOW_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_HIGH_REGISTER, 0); + ideCommand(CHANNEL, IDE_IDENTIFY_COMMAND); + ideWaitUntilNotBusy(CHANNEL, true); + ideReadBuffer(CHANNEL, (void *)buffer); + if (*((uint16_t *)buffer) == 0) { + // any bit has to be set if it is a real device + continue; + } + char *model = malloc(41); + for (int i = 0; i < 40; i += 2) { + *((uint16_t *)&model[i]) = buffer[54 + i + 1]; + *((uint16_t *)&model[i + 1]) = buffer[54 + i]; + } + model[40] = 0; + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->model = model; + hardDrive->channels = CHANNEL; + hardDrive->channel = channel; + hardDrive->drive = drive; + hardDrive->type = *(uint16_t *)buffer; + hardDrive->cylinders = *(uint16_t *)buffer + 2; + hardDrive->heads = *(uint16_t *)buffer + 6; + hardDrive->sectors = *(uint16_t *)buffer + 12; + hardDrive->capabilities = *(uint16_t *)buffer + 98; + hardDrive->commandSets = *(uint32_t *)(buffer + 164); + if (hardDrive->commandSets + (1 << 26)) { + hardDrive->size = *(uint32_t *)buffer + 200; + } else { + hardDrive->size = *(uint32_t *)buffer + 120; + } + listAdd(drives, hardDrive); + printf("found a hard drive %i bytes, %i:%i, model: %s\n", + hardDrive->size, channel, drive, model); + } + } + free(buffer); +} + +void printError(uint16_t status) { + if (status & 0x01) { + printf("No address mark\n"); + } + if (status & 0x02) { + printf("Track 0 not found\n"); + } + if (status & 0x04) { + printf("command aborted\n"); + } + if (status & 0x08) { + printf("Media change request\n"); + } + if (status & 0x10) { + printf("ID mark not found\n"); + } + if (status & 0x20) { + printf("Media changed\n"); + } + if (status & 0x40) { + printf("uncorrectable data\n"); + } + if (status & 0x80) { + printf("bad block\n"); + } +} + +void driveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, + uint8_t sectorCount, uint8_t direction) { + uint8_t accessMode = 0, head = 0, sector = 0, cylinder = 0; + uint32_t lbaIo[6] = {0, 0, 0, 0, 0, 0}; + if (lba >= 0x10000000) { + accessMode = 2; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x0000FF00) >> 8; + lbaIo[2] = (lba & 0x00FF0000) >> 16; + lbaIo[3] = (lba & 0xFF000000) >> 24; + } else if (hardDrive->capabilities & 0x200) { + accessMode = 1; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x000FF00) >> 8; + lbaIo[2] = (lba & 0x0FF0000) >> 16; + head = (lba & 0xF000000) >> 24; + } else { + sector = (lba % 63) + 1; + cylinder = (lba + 1 - sector) / (16 * 63); + lbaIo[0] = sector; + lbaIo[1] = (uint8_t)cylinder; + lbaIo[2] = (cylinder >> 8) & 0xFF; + head = (lba + 1 - sector) % (16 * 63) / (63); + } + ideWaitUntilNotBusy(hardDrive->channels, true); + if (accessMode == 0) { + // chs + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xA0 | (hardDrive->drive << 4)); + } else { + // lba + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xE0 | (hardDrive->drive << 4) | head); + } + ideWriteRegister(hardDrive->channels, IDE_SECTOR_COUNT_REGISTER, + sectorCount); + ideWriteRegister(hardDrive->channels, IDE_SECTOR_NUMBER_REGISTER, + lbaIo[3] << 8 | lbaIo[0]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_LOW_REGISTER, + lbaIo[4] << 8 | lbaIo[1]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_HIGH_REGISTER, + lbaIo[5] << 8 | lbaIo[2]); + uint8_t command = 0; + if (direction == 0) { + // read + if (accessMode == 2) { + command = 0x24; + } else { + command = 0x20; + } + } else { + // write + if (accessMode == 2) { + command = 0x34; + } else { + command = 0x30; + } + } + ideCommand(hardDrive->channels, command); + ideWaitUntilNotBusy(hardDrive->channels, true); + if (direction == 0) { + uint16_t status; + void *current = buffer; + for (uint8_t i = 0; i < sectorCount; i++) { + ideWaitUntilNotBusy(hardDrive->channels, true); + ideReadBuffer(hardDrive->channels, (void *)buffer); + } + } +} + +void initializeSATADrive(PciDevice *pciDevice) { + // todo +} + +void scanHardDrives() { + ListElement *drives = NULL; + for (ListElement *current = *getPciDevices(); current; + current = current->next) { + PciDevice *pciDevice = current->data; + if (pciDevice->class != 1) { + continue; + } + switch (pciDevice->subclass) { + case 1: + initializeIDEDrive(pciDevice, &drives); + break; + case 6: + printf("found a SATA-controller: %i:%i:%i\n", pciDevice->bus, + pciDevice->device, pciDevice->function); + initializeSATADrive(pciDevice); + break; + } + } + void *buffer = malloc(2000); + for (ListElement *current = drives; current; current = current->next) { + driveAccess(current->data, 0, buffer, 1, 0); + printf("data: %x %x %s\n", *(uint32_t *)buffer, + *((uint32_t *)buffer + 1), buffer); + } + free(buffer); +} diff --git a/src/kernel/drivers/pci/pci.c b/src/kernel/drivers/pci/pci.c index 9874077..96cbfc3 100644 --- a/src/kernel/drivers/pci/pci.c +++ b/src/kernel/drivers/pci/pci.c @@ -35,6 +35,8 @@ ListElement *pciDevices = NULL; +ListElement **getPciDevices() { return &pciDevices; } + uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset) { uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | @@ -46,6 +48,16 @@ return result; } +void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data) { + uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | + (offset & 0xFC) | 0x80000000); + asm("cli"); + outi(0xCF8, address); + outb(0xCFC, data); + asm("sti"); +} + uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) { return (uint16_t)pciConfigReadByte(bus, device, function, offset) | @@ -53,6 +65,13 @@ << 8); } +uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset) { + return (uint32_t)pciConfigReadWord(bus, device, function, offset) | + ((uint32_t)pciConfigReadWord(bus, device, function, offset + 2) + << 16); +} + uint8_t getHeaderType(uint8_t bus, uint8_t device, uint8_t function) { return pciConfigReadByte(bus, device, function, 0x0E); } @@ -74,6 +93,14 @@ pciDevice->subclass = subclass; pciDevice->vendorId = pciConfigReadWord(bus, device, function, 0x00); pciDevice->deviceId = pciConfigReadWord(bus, device, function, 0x02); + pciDevice->programmingInterface = + pciConfigReadByte(bus, device, function, 0x09); + pciDevice->bar0 = pciConfigReadInt(bus, device, function, 0x10); + pciDevice->bar1 = pciConfigReadInt(bus, device, function, 0x14); + pciDevice->bar2 = pciConfigReadInt(bus, device, function, 0x18); + pciDevice->bar3 = pciConfigReadInt(bus, device, function, 0x1C); + pciDevice->bar4 = pciConfigReadInt(bus, device, function, 0x20); + pciDevice->bar5 = pciConfigReadInt(bus, device, function, 0x24); listAdd(&pciDevices, pciDevice); if (class == 6 && subclass == 4) { checkBus(pciConfigReadByte(bus, device, function, 0x19)); @@ -87,7 +114,7 @@ } if (getHeaderType(bus, device, 0) & 0x80) { // multifunction device - for (uint16_t function = 0; function < 256; function++) { + for (uint16_t function = 0; function < 8; function++) { if (getVendorID(bus, device, function) != 0xFFFF) { checkFunction(bus, device, function); } @@ -102,7 +129,7 @@ return; } checkedBuses[bus] = true; - for (uint16_t device = 0; device < 256; device++) { + for (uint16_t device = 0; device < 32; device++) { checkDevice(bus, device); } } diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/src/kernel/drivers/interrupts/irqs.c b/src/kernel/drivers/interrupts/irqs.c index 60d95f8..1cd8c79 100644 --- a/src/kernel/drivers/interrupts/irqs.c +++ b/src/kernel/drivers/interrupts/irqs.c @@ -61,7 +61,7 @@ return; } if (irqNumber == 7 || irqNumber == 2) { - // irq2 should not be fired, irq 7 is a spurious irq + // irq2 should not be fired, irq 7 indicates a spurious irq return; } printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber); diff --git a/src/kernel/drivers/interrupts/keyboard/keyboard.c b/src/kernel/drivers/interrupts/keyboard/keyboard.c index 94b3dad..99fdd04 100644 --- a/src/kernel/drivers/interrupts/keyboard/keyboard.c +++ b/src/kernel/drivers/interrupts/keyboard/keyboard.c @@ -77,6 +77,7 @@ message->type = KEYBOARD_STRING; message->size = strlen(message->data); listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); return; } if (scancode & 0x80) { @@ -96,15 +97,16 @@ } void *data = NULL; if (modifiers & MODIFIER_LEFT_SHIFT || modifiers & MODIFIER_RIGHT_SHIFT) { - data = capitalKeycodes[scancode]; + data = (void *)(uint32_t)capitalKeycodes[scancode]; } else { - data = keycodes[scancode]; + data = (void *)(uint32_t)keycodes[scancode]; } Message *message = malloc(sizeof(Message)); message->data = data; message->size = 1; message->type = KEYBOARD_CHAR; listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); } void setupKeyboard() { setIRQHandler(1, &keyboardHandler); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index e57a651..35addee 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -27,14 +27,20 @@ #define CMD_COUNTER0 0x00 #define CMD_COUNTER2 0x80 -void setTimerFreq(uint32_t hz) { +void sleep(uint16_t millis) { + uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + getCurrentTask()->ticksLeft = millis; + yield(); +} + +void setTimerFrequency(uint32_t hz) { int divisor = PIT_SCALE / hz; outb(PIT_CONTROL, CMD_BINARY | CMD_MODE3 | CMD_RW_BOTH | CMD_COUNTER0); outb(PIT_A, (uint8_t)divisor); outb(PIT_A, (uint8_t)(divisor >> 8)); } -uint64_t timerMillis = 0; +uint32_t timerMillis = 0; void timerHandler() { timerMillis++; @@ -59,7 +65,6 @@ } void setupTimer() { - printf("setting timer frequency to 1kHz\n"); - setTimerFreq(1000); + setTimerFrequency(1000); setIRQHandler(0, &timerHandler); } diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c new file mode 100644 index 0000000..ea36871 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -0,0 +1,291 @@ +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +#define IDE_DATA_REGISTER 0 +#define IDE_ERROR_REGISTER 1 +#define IDE_SECTOR_COUNT_REGISTER 2 +#define IDE_SECTOR_NUMBER_REGISTER 3 +#define IDE_CYLINDER_LOW_REGISTER 4 +#define IDE_CYLINDER_HIGH_REGISTER 5 +// sector size, drive, head +#define IDE_SDH_REGISTER 6 +#define IDE_STATUS_REGISTER 7 +#define IDE_COMMAND_REGISTER 7 +#define IDE_ALTERNATE_STATUS_CONTROL_REGISTER 0 +#define IDE_DRIVE_ADDRESS_CONTROL_REGISTER 1 + +#define IDE_STATUS_BUSY 0x80 +#define IDE_STATUS_READY 0x40 +#define IDE_STATUS_WRITE_FAULT 0x20 +#define IDE_STATUS_SEEK_COMPLETE 0x10 +#define IDE_STATUS_DATA_REQUEST 0x08 +#define IDE_STATUS_CORRECTED_DATA 0x04 +#define IDE_STATUS_INDEX 0x02 +#define IDE_STATUS_ERROR 0x01 + +#define IDE_IDENTIFY_COMMAND 0xEC + +char *driveTypes[] = { + "ISA Compatibility mode-only controller", + "PCI native mode-only controller", + "ISA Compatibility mode controller", + "PCI native mode controller", +}; + +void setupIDEChannels(IdeChannels *channels, PciDevice *pciDevice) { + if (pciDevice->programmingInterface & 0x01) { + channels->base = pciDevice->bar0; + channels->control = pciDevice->bar1; + } else { + channels->base = 0x1F0; + channels->control = 0x3F6; + } + if (pciDevice->programmingInterface & 0x04) { + channels[1].base = pciDevice->bar2; + channels[1].control = pciDevice->bar3; + } else { + channels[1].base = 0x170; + channels[1].control = 0x376; + } +} + +void ideWriteControlRegister(IdeChannels *channel, uint8_t reg, uint8_t data) { + outb(channel->control + reg, data); +} + +void ideWriteRegister(IdeChannels *channel, uint8_t reg, uint16_t data) { + outb(channel->base + reg, data); + if (data > 0xFF) { + // set higher half bit in the control register + outb(channel->control, 0x0A); + outb(channel->base + reg, data >> 8); + outb(channel->control, 0x02); + } +} + +uint8_t ideReadControlRegister(IdeChannels *channel, uint8_t reg) { + return inb(channel->control + reg); +} + +uint8_t ideReadRegister(IdeChannels *channel, uint16_t reg) { + return inw(channel->base + reg); +} + +void ideReadBuffer(IdeChannels *channel, uint32_t *data) { + for (uint16_t i = 0; i < 128; i++) { + data[i] = ini(channel->base + IDE_DATA_REGISTER); + } +} + +void printError(uint16_t); + +void ideWaitUntilNotBusy(IdeChannels *channel, bool checkErrors) { + for (uint8_t i = 0; i < 4; i++) { + ideReadControlRegister(channel, 0); + } + uint16_t status = ideReadRegister(channel, IDE_STATUS_REGISTER); + while (status & IDE_STATUS_BUSY) { + status = ideReadRegister(channel, IDE_STATUS_REGISTER); + } + if (checkErrors && status & IDE_STATUS_ERROR) { + printf("encountered an error\n"); + printError(ideReadRegister(channel, IDE_ERROR_REGISTER)); + } +} + +void ideCommand(IdeChannels *channel, uint8_t command) { + ideWaitUntilNotBusy(channel, false); + ideWriteRegister(channel, IDE_COMMAND_REGISTER, command); +} + +#define CHANNEL &channels[channel] + +void initializeIDEDrive(PciDevice *pciDevice, ListElement **drives) { + uint8_t *buffer = malloc(2048); + IdeChannels *channels = malloc(sizeof(IdeChannels) * 2); + setupIDEChannels(channels, pciDevice); + for (uint8_t channel = 0; channel < 2; channel++) { + if (ideReadRegister(CHANNEL, IDE_STATUS_REGISTER) == 0) { + // no device + continue; + } + ideWriteControlRegister(CHANNEL, IDE_ALTERNATE_STATUS_CONTROL_REGISTER, + 2); + for (uint8_t drive = 0; drive < 2; drive++) { + ideWaitUntilNotBusy(CHANNEL, true); + // set the drive + ideWriteRegister(CHANNEL, IDE_SDH_REGISTER, 0xA0 | (drive << 4)); + ideWriteRegister(CHANNEL, IDE_SECTOR_COUNT_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_SECTOR_NUMBER_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_LOW_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_HIGH_REGISTER, 0); + ideCommand(CHANNEL, IDE_IDENTIFY_COMMAND); + ideWaitUntilNotBusy(CHANNEL, true); + ideReadBuffer(CHANNEL, (void *)buffer); + if (*((uint16_t *)buffer) == 0) { + // any bit has to be set if it is a real device + continue; + } + char *model = malloc(41); + for (int i = 0; i < 40; i += 2) { + *((uint16_t *)&model[i]) = buffer[54 + i + 1]; + *((uint16_t *)&model[i + 1]) = buffer[54 + i]; + } + model[40] = 0; + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->model = model; + hardDrive->channels = CHANNEL; + hardDrive->channel = channel; + hardDrive->drive = drive; + hardDrive->type = *(uint16_t *)buffer; + hardDrive->cylinders = *(uint16_t *)buffer + 2; + hardDrive->heads = *(uint16_t *)buffer + 6; + hardDrive->sectors = *(uint16_t *)buffer + 12; + hardDrive->capabilities = *(uint16_t *)buffer + 98; + hardDrive->commandSets = *(uint32_t *)(buffer + 164); + if (hardDrive->commandSets + (1 << 26)) { + hardDrive->size = *(uint32_t *)buffer + 200; + } else { + hardDrive->size = *(uint32_t *)buffer + 120; + } + listAdd(drives, hardDrive); + printf("found a hard drive %i bytes, %i:%i, model: %s\n", + hardDrive->size, channel, drive, model); + } + } + free(buffer); +} + +void printError(uint16_t status) { + if (status & 0x01) { + printf("No address mark\n"); + } + if (status & 0x02) { + printf("Track 0 not found\n"); + } + if (status & 0x04) { + printf("command aborted\n"); + } + if (status & 0x08) { + printf("Media change request\n"); + } + if (status & 0x10) { + printf("ID mark not found\n"); + } + if (status & 0x20) { + printf("Media changed\n"); + } + if (status & 0x40) { + printf("uncorrectable data\n"); + } + if (status & 0x80) { + printf("bad block\n"); + } +} + +void driveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, + uint8_t sectorCount, uint8_t direction) { + uint8_t accessMode = 0, head = 0, sector = 0, cylinder = 0; + uint32_t lbaIo[6] = {0, 0, 0, 0, 0, 0}; + if (lba >= 0x10000000) { + accessMode = 2; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x0000FF00) >> 8; + lbaIo[2] = (lba & 0x00FF0000) >> 16; + lbaIo[3] = (lba & 0xFF000000) >> 24; + } else if (hardDrive->capabilities & 0x200) { + accessMode = 1; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x000FF00) >> 8; + lbaIo[2] = (lba & 0x0FF0000) >> 16; + head = (lba & 0xF000000) >> 24; + } else { + sector = (lba % 63) + 1; + cylinder = (lba + 1 - sector) / (16 * 63); + lbaIo[0] = sector; + lbaIo[1] = (uint8_t)cylinder; + lbaIo[2] = (cylinder >> 8) & 0xFF; + head = (lba + 1 - sector) % (16 * 63) / (63); + } + ideWaitUntilNotBusy(hardDrive->channels, true); + if (accessMode == 0) { + // chs + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xA0 | (hardDrive->drive << 4)); + } else { + // lba + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xE0 | (hardDrive->drive << 4) | head); + } + ideWriteRegister(hardDrive->channels, IDE_SECTOR_COUNT_REGISTER, + sectorCount); + ideWriteRegister(hardDrive->channels, IDE_SECTOR_NUMBER_REGISTER, + lbaIo[3] << 8 | lbaIo[0]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_LOW_REGISTER, + lbaIo[4] << 8 | lbaIo[1]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_HIGH_REGISTER, + lbaIo[5] << 8 | lbaIo[2]); + uint8_t command = 0; + if (direction == 0) { + // read + if (accessMode == 2) { + command = 0x24; + } else { + command = 0x20; + } + } else { + // write + if (accessMode == 2) { + command = 0x34; + } else { + command = 0x30; + } + } + ideCommand(hardDrive->channels, command); + ideWaitUntilNotBusy(hardDrive->channels, true); + if (direction == 0) { + uint16_t status; + void *current = buffer; + for (uint8_t i = 0; i < sectorCount; i++) { + ideWaitUntilNotBusy(hardDrive->channels, true); + ideReadBuffer(hardDrive->channels, (void *)buffer); + } + } +} + +void initializeSATADrive(PciDevice *pciDevice) { + // todo +} + +void scanHardDrives() { + ListElement *drives = NULL; + for (ListElement *current = *getPciDevices(); current; + current = current->next) { + PciDevice *pciDevice = current->data; + if (pciDevice->class != 1) { + continue; + } + switch (pciDevice->subclass) { + case 1: + initializeIDEDrive(pciDevice, &drives); + break; + case 6: + printf("found a SATA-controller: %i:%i:%i\n", pciDevice->bus, + pciDevice->device, pciDevice->function); + initializeSATADrive(pciDevice); + break; + } + } + void *buffer = malloc(2000); + for (ListElement *current = drives; current; current = current->next) { + driveAccess(current->data, 0, buffer, 1, 0); + printf("data: %x %x %s\n", *(uint32_t *)buffer, + *((uint32_t *)buffer + 1), buffer); + } + free(buffer); +} diff --git a/src/kernel/drivers/pci/pci.c b/src/kernel/drivers/pci/pci.c index 9874077..96cbfc3 100644 --- a/src/kernel/drivers/pci/pci.c +++ b/src/kernel/drivers/pci/pci.c @@ -35,6 +35,8 @@ ListElement *pciDevices = NULL; +ListElement **getPciDevices() { return &pciDevices; } + uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset) { uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | @@ -46,6 +48,16 @@ return result; } +void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data) { + uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | + (offset & 0xFC) | 0x80000000); + asm("cli"); + outi(0xCF8, address); + outb(0xCFC, data); + asm("sti"); +} + uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) { return (uint16_t)pciConfigReadByte(bus, device, function, offset) | @@ -53,6 +65,13 @@ << 8); } +uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset) { + return (uint32_t)pciConfigReadWord(bus, device, function, offset) | + ((uint32_t)pciConfigReadWord(bus, device, function, offset + 2) + << 16); +} + uint8_t getHeaderType(uint8_t bus, uint8_t device, uint8_t function) { return pciConfigReadByte(bus, device, function, 0x0E); } @@ -74,6 +93,14 @@ pciDevice->subclass = subclass; pciDevice->vendorId = pciConfigReadWord(bus, device, function, 0x00); pciDevice->deviceId = pciConfigReadWord(bus, device, function, 0x02); + pciDevice->programmingInterface = + pciConfigReadByte(bus, device, function, 0x09); + pciDevice->bar0 = pciConfigReadInt(bus, device, function, 0x10); + pciDevice->bar1 = pciConfigReadInt(bus, device, function, 0x14); + pciDevice->bar2 = pciConfigReadInt(bus, device, function, 0x18); + pciDevice->bar3 = pciConfigReadInt(bus, device, function, 0x1C); + pciDevice->bar4 = pciConfigReadInt(bus, device, function, 0x20); + pciDevice->bar5 = pciConfigReadInt(bus, device, function, 0x24); listAdd(&pciDevices, pciDevice); if (class == 6 && subclass == 4) { checkBus(pciConfigReadByte(bus, device, function, 0x19)); @@ -87,7 +114,7 @@ } if (getHeaderType(bus, device, 0) & 0x80) { // multifunction device - for (uint16_t function = 0; function < 256; function++) { + for (uint16_t function = 0; function < 8; function++) { if (getVendorID(bus, device, function) != 0xFFFF) { checkFunction(bus, device, function); } @@ -102,7 +129,7 @@ return; } checkedBuses[bus] = true; - for (uint16_t device = 0; device < 256; device++) { + for (uint16_t device = 0; device < 32; device++) { checkDevice(bus, device); } } diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 15713cc..7375f67 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -17,18 +18,16 @@ 0x1000000); // initializing stacks after the kernel seems not to work :( // otherwise, _kernel_end should be passed here initOSTasks(); + getCurrentTask()->timerTicks = 1000; + getCurrentTask()->ticksLeft = 1000; drawLogo(); + yields(); setupDevices(); setupInterrupts(); printCPUData(); scanPCIDevices(); - yields(); - getCurrentTask()->timerTicks = 1000; - getCurrentTask()->ticksLeft = 1000; + scanHardDrives(); while (1) { - if (isTaskQueueEmpty()) { - asm volatile("hlt"); - } for (Message *message = popBeginning(&(getCurrentTask()->messages)); message; message = popBeginning(&getCurrentTask()->messages)) { switch (message->type) { @@ -44,6 +43,6 @@ } free(message); } - yields(); + yield(); } } diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/src/kernel/drivers/interrupts/irqs.c b/src/kernel/drivers/interrupts/irqs.c index 60d95f8..1cd8c79 100644 --- a/src/kernel/drivers/interrupts/irqs.c +++ b/src/kernel/drivers/interrupts/irqs.c @@ -61,7 +61,7 @@ return; } if (irqNumber == 7 || irqNumber == 2) { - // irq2 should not be fired, irq 7 is a spurious irq + // irq2 should not be fired, irq 7 indicates a spurious irq return; } printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber); diff --git a/src/kernel/drivers/interrupts/keyboard/keyboard.c b/src/kernel/drivers/interrupts/keyboard/keyboard.c index 94b3dad..99fdd04 100644 --- a/src/kernel/drivers/interrupts/keyboard/keyboard.c +++ b/src/kernel/drivers/interrupts/keyboard/keyboard.c @@ -77,6 +77,7 @@ message->type = KEYBOARD_STRING; message->size = strlen(message->data); listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); return; } if (scancode & 0x80) { @@ -96,15 +97,16 @@ } void *data = NULL; if (modifiers & MODIFIER_LEFT_SHIFT || modifiers & MODIFIER_RIGHT_SHIFT) { - data = capitalKeycodes[scancode]; + data = (void *)(uint32_t)capitalKeycodes[scancode]; } else { - data = keycodes[scancode]; + data = (void *)(uint32_t)keycodes[scancode]; } Message *message = malloc(sizeof(Message)); message->data = data; message->size = 1; message->type = KEYBOARD_CHAR; listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); } void setupKeyboard() { setIRQHandler(1, &keyboardHandler); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index e57a651..35addee 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -27,14 +27,20 @@ #define CMD_COUNTER0 0x00 #define CMD_COUNTER2 0x80 -void setTimerFreq(uint32_t hz) { +void sleep(uint16_t millis) { + uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + getCurrentTask()->ticksLeft = millis; + yield(); +} + +void setTimerFrequency(uint32_t hz) { int divisor = PIT_SCALE / hz; outb(PIT_CONTROL, CMD_BINARY | CMD_MODE3 | CMD_RW_BOTH | CMD_COUNTER0); outb(PIT_A, (uint8_t)divisor); outb(PIT_A, (uint8_t)(divisor >> 8)); } -uint64_t timerMillis = 0; +uint32_t timerMillis = 0; void timerHandler() { timerMillis++; @@ -59,7 +65,6 @@ } void setupTimer() { - printf("setting timer frequency to 1kHz\n"); - setTimerFreq(1000); + setTimerFrequency(1000); setIRQHandler(0, &timerHandler); } diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c new file mode 100644 index 0000000..ea36871 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -0,0 +1,291 @@ +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +#define IDE_DATA_REGISTER 0 +#define IDE_ERROR_REGISTER 1 +#define IDE_SECTOR_COUNT_REGISTER 2 +#define IDE_SECTOR_NUMBER_REGISTER 3 +#define IDE_CYLINDER_LOW_REGISTER 4 +#define IDE_CYLINDER_HIGH_REGISTER 5 +// sector size, drive, head +#define IDE_SDH_REGISTER 6 +#define IDE_STATUS_REGISTER 7 +#define IDE_COMMAND_REGISTER 7 +#define IDE_ALTERNATE_STATUS_CONTROL_REGISTER 0 +#define IDE_DRIVE_ADDRESS_CONTROL_REGISTER 1 + +#define IDE_STATUS_BUSY 0x80 +#define IDE_STATUS_READY 0x40 +#define IDE_STATUS_WRITE_FAULT 0x20 +#define IDE_STATUS_SEEK_COMPLETE 0x10 +#define IDE_STATUS_DATA_REQUEST 0x08 +#define IDE_STATUS_CORRECTED_DATA 0x04 +#define IDE_STATUS_INDEX 0x02 +#define IDE_STATUS_ERROR 0x01 + +#define IDE_IDENTIFY_COMMAND 0xEC + +char *driveTypes[] = { + "ISA Compatibility mode-only controller", + "PCI native mode-only controller", + "ISA Compatibility mode controller", + "PCI native mode controller", +}; + +void setupIDEChannels(IdeChannels *channels, PciDevice *pciDevice) { + if (pciDevice->programmingInterface & 0x01) { + channels->base = pciDevice->bar0; + channels->control = pciDevice->bar1; + } else { + channels->base = 0x1F0; + channels->control = 0x3F6; + } + if (pciDevice->programmingInterface & 0x04) { + channels[1].base = pciDevice->bar2; + channels[1].control = pciDevice->bar3; + } else { + channels[1].base = 0x170; + channels[1].control = 0x376; + } +} + +void ideWriteControlRegister(IdeChannels *channel, uint8_t reg, uint8_t data) { + outb(channel->control + reg, data); +} + +void ideWriteRegister(IdeChannels *channel, uint8_t reg, uint16_t data) { + outb(channel->base + reg, data); + if (data > 0xFF) { + // set higher half bit in the control register + outb(channel->control, 0x0A); + outb(channel->base + reg, data >> 8); + outb(channel->control, 0x02); + } +} + +uint8_t ideReadControlRegister(IdeChannels *channel, uint8_t reg) { + return inb(channel->control + reg); +} + +uint8_t ideReadRegister(IdeChannels *channel, uint16_t reg) { + return inw(channel->base + reg); +} + +void ideReadBuffer(IdeChannels *channel, uint32_t *data) { + for (uint16_t i = 0; i < 128; i++) { + data[i] = ini(channel->base + IDE_DATA_REGISTER); + } +} + +void printError(uint16_t); + +void ideWaitUntilNotBusy(IdeChannels *channel, bool checkErrors) { + for (uint8_t i = 0; i < 4; i++) { + ideReadControlRegister(channel, 0); + } + uint16_t status = ideReadRegister(channel, IDE_STATUS_REGISTER); + while (status & IDE_STATUS_BUSY) { + status = ideReadRegister(channel, IDE_STATUS_REGISTER); + } + if (checkErrors && status & IDE_STATUS_ERROR) { + printf("encountered an error\n"); + printError(ideReadRegister(channel, IDE_ERROR_REGISTER)); + } +} + +void ideCommand(IdeChannels *channel, uint8_t command) { + ideWaitUntilNotBusy(channel, false); + ideWriteRegister(channel, IDE_COMMAND_REGISTER, command); +} + +#define CHANNEL &channels[channel] + +void initializeIDEDrive(PciDevice *pciDevice, ListElement **drives) { + uint8_t *buffer = malloc(2048); + IdeChannels *channels = malloc(sizeof(IdeChannels) * 2); + setupIDEChannels(channels, pciDevice); + for (uint8_t channel = 0; channel < 2; channel++) { + if (ideReadRegister(CHANNEL, IDE_STATUS_REGISTER) == 0) { + // no device + continue; + } + ideWriteControlRegister(CHANNEL, IDE_ALTERNATE_STATUS_CONTROL_REGISTER, + 2); + for (uint8_t drive = 0; drive < 2; drive++) { + ideWaitUntilNotBusy(CHANNEL, true); + // set the drive + ideWriteRegister(CHANNEL, IDE_SDH_REGISTER, 0xA0 | (drive << 4)); + ideWriteRegister(CHANNEL, IDE_SECTOR_COUNT_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_SECTOR_NUMBER_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_LOW_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_HIGH_REGISTER, 0); + ideCommand(CHANNEL, IDE_IDENTIFY_COMMAND); + ideWaitUntilNotBusy(CHANNEL, true); + ideReadBuffer(CHANNEL, (void *)buffer); + if (*((uint16_t *)buffer) == 0) { + // any bit has to be set if it is a real device + continue; + } + char *model = malloc(41); + for (int i = 0; i < 40; i += 2) { + *((uint16_t *)&model[i]) = buffer[54 + i + 1]; + *((uint16_t *)&model[i + 1]) = buffer[54 + i]; + } + model[40] = 0; + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->model = model; + hardDrive->channels = CHANNEL; + hardDrive->channel = channel; + hardDrive->drive = drive; + hardDrive->type = *(uint16_t *)buffer; + hardDrive->cylinders = *(uint16_t *)buffer + 2; + hardDrive->heads = *(uint16_t *)buffer + 6; + hardDrive->sectors = *(uint16_t *)buffer + 12; + hardDrive->capabilities = *(uint16_t *)buffer + 98; + hardDrive->commandSets = *(uint32_t *)(buffer + 164); + if (hardDrive->commandSets + (1 << 26)) { + hardDrive->size = *(uint32_t *)buffer + 200; + } else { + hardDrive->size = *(uint32_t *)buffer + 120; + } + listAdd(drives, hardDrive); + printf("found a hard drive %i bytes, %i:%i, model: %s\n", + hardDrive->size, channel, drive, model); + } + } + free(buffer); +} + +void printError(uint16_t status) { + if (status & 0x01) { + printf("No address mark\n"); + } + if (status & 0x02) { + printf("Track 0 not found\n"); + } + if (status & 0x04) { + printf("command aborted\n"); + } + if (status & 0x08) { + printf("Media change request\n"); + } + if (status & 0x10) { + printf("ID mark not found\n"); + } + if (status & 0x20) { + printf("Media changed\n"); + } + if (status & 0x40) { + printf("uncorrectable data\n"); + } + if (status & 0x80) { + printf("bad block\n"); + } +} + +void driveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, + uint8_t sectorCount, uint8_t direction) { + uint8_t accessMode = 0, head = 0, sector = 0, cylinder = 0; + uint32_t lbaIo[6] = {0, 0, 0, 0, 0, 0}; + if (lba >= 0x10000000) { + accessMode = 2; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x0000FF00) >> 8; + lbaIo[2] = (lba & 0x00FF0000) >> 16; + lbaIo[3] = (lba & 0xFF000000) >> 24; + } else if (hardDrive->capabilities & 0x200) { + accessMode = 1; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x000FF00) >> 8; + lbaIo[2] = (lba & 0x0FF0000) >> 16; + head = (lba & 0xF000000) >> 24; + } else { + sector = (lba % 63) + 1; + cylinder = (lba + 1 - sector) / (16 * 63); + lbaIo[0] = sector; + lbaIo[1] = (uint8_t)cylinder; + lbaIo[2] = (cylinder >> 8) & 0xFF; + head = (lba + 1 - sector) % (16 * 63) / (63); + } + ideWaitUntilNotBusy(hardDrive->channels, true); + if (accessMode == 0) { + // chs + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xA0 | (hardDrive->drive << 4)); + } else { + // lba + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xE0 | (hardDrive->drive << 4) | head); + } + ideWriteRegister(hardDrive->channels, IDE_SECTOR_COUNT_REGISTER, + sectorCount); + ideWriteRegister(hardDrive->channels, IDE_SECTOR_NUMBER_REGISTER, + lbaIo[3] << 8 | lbaIo[0]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_LOW_REGISTER, + lbaIo[4] << 8 | lbaIo[1]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_HIGH_REGISTER, + lbaIo[5] << 8 | lbaIo[2]); + uint8_t command = 0; + if (direction == 0) { + // read + if (accessMode == 2) { + command = 0x24; + } else { + command = 0x20; + } + } else { + // write + if (accessMode == 2) { + command = 0x34; + } else { + command = 0x30; + } + } + ideCommand(hardDrive->channels, command); + ideWaitUntilNotBusy(hardDrive->channels, true); + if (direction == 0) { + uint16_t status; + void *current = buffer; + for (uint8_t i = 0; i < sectorCount; i++) { + ideWaitUntilNotBusy(hardDrive->channels, true); + ideReadBuffer(hardDrive->channels, (void *)buffer); + } + } +} + +void initializeSATADrive(PciDevice *pciDevice) { + // todo +} + +void scanHardDrives() { + ListElement *drives = NULL; + for (ListElement *current = *getPciDevices(); current; + current = current->next) { + PciDevice *pciDevice = current->data; + if (pciDevice->class != 1) { + continue; + } + switch (pciDevice->subclass) { + case 1: + initializeIDEDrive(pciDevice, &drives); + break; + case 6: + printf("found a SATA-controller: %i:%i:%i\n", pciDevice->bus, + pciDevice->device, pciDevice->function); + initializeSATADrive(pciDevice); + break; + } + } + void *buffer = malloc(2000); + for (ListElement *current = drives; current; current = current->next) { + driveAccess(current->data, 0, buffer, 1, 0); + printf("data: %x %x %s\n", *(uint32_t *)buffer, + *((uint32_t *)buffer + 1), buffer); + } + free(buffer); +} diff --git a/src/kernel/drivers/pci/pci.c b/src/kernel/drivers/pci/pci.c index 9874077..96cbfc3 100644 --- a/src/kernel/drivers/pci/pci.c +++ b/src/kernel/drivers/pci/pci.c @@ -35,6 +35,8 @@ ListElement *pciDevices = NULL; +ListElement **getPciDevices() { return &pciDevices; } + uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset) { uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | @@ -46,6 +48,16 @@ return result; } +void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data) { + uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | + (offset & 0xFC) | 0x80000000); + asm("cli"); + outi(0xCF8, address); + outb(0xCFC, data); + asm("sti"); +} + uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) { return (uint16_t)pciConfigReadByte(bus, device, function, offset) | @@ -53,6 +65,13 @@ << 8); } +uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset) { + return (uint32_t)pciConfigReadWord(bus, device, function, offset) | + ((uint32_t)pciConfigReadWord(bus, device, function, offset + 2) + << 16); +} + uint8_t getHeaderType(uint8_t bus, uint8_t device, uint8_t function) { return pciConfigReadByte(bus, device, function, 0x0E); } @@ -74,6 +93,14 @@ pciDevice->subclass = subclass; pciDevice->vendorId = pciConfigReadWord(bus, device, function, 0x00); pciDevice->deviceId = pciConfigReadWord(bus, device, function, 0x02); + pciDevice->programmingInterface = + pciConfigReadByte(bus, device, function, 0x09); + pciDevice->bar0 = pciConfigReadInt(bus, device, function, 0x10); + pciDevice->bar1 = pciConfigReadInt(bus, device, function, 0x14); + pciDevice->bar2 = pciConfigReadInt(bus, device, function, 0x18); + pciDevice->bar3 = pciConfigReadInt(bus, device, function, 0x1C); + pciDevice->bar4 = pciConfigReadInt(bus, device, function, 0x20); + pciDevice->bar5 = pciConfigReadInt(bus, device, function, 0x24); listAdd(&pciDevices, pciDevice); if (class == 6 && subclass == 4) { checkBus(pciConfigReadByte(bus, device, function, 0x19)); @@ -87,7 +114,7 @@ } if (getHeaderType(bus, device, 0) & 0x80) { // multifunction device - for (uint16_t function = 0; function < 256; function++) { + for (uint16_t function = 0; function < 8; function++) { if (getVendorID(bus, device, function) != 0xFFFF) { checkFunction(bus, device, function); } @@ -102,7 +129,7 @@ return; } checkedBuses[bus] = true; - for (uint16_t device = 0; device < 256; device++) { + for (uint16_t device = 0; device < 32; device++) { checkDevice(bus, device); } } diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 15713cc..7375f67 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -17,18 +18,16 @@ 0x1000000); // initializing stacks after the kernel seems not to work :( // otherwise, _kernel_end should be passed here initOSTasks(); + getCurrentTask()->timerTicks = 1000; + getCurrentTask()->ticksLeft = 1000; drawLogo(); + yields(); setupDevices(); setupInterrupts(); printCPUData(); scanPCIDevices(); - yields(); - getCurrentTask()->timerTicks = 1000; - getCurrentTask()->ticksLeft = 1000; + scanHardDrives(); while (1) { - if (isTaskQueueEmpty()) { - asm volatile("hlt"); - } for (Message *message = popBeginning(&(getCurrentTask()->messages)); message; message = popBeginning(&getCurrentTask()->messages)) { switch (message->type) { @@ -44,6 +43,6 @@ } free(message); } - yields(); + yield(); } } diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c index b968b61..868b8b6 100644 --- a/src/kernel/memory/alloc.c +++ b/src/kernel/memory/alloc.c @@ -37,6 +37,7 @@ current->next->state = FREE; current->next->next = next; next->last = current->next; + next = current->next; } else { current->next = next; } diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/src/kernel/drivers/interrupts/irqs.c b/src/kernel/drivers/interrupts/irqs.c index 60d95f8..1cd8c79 100644 --- a/src/kernel/drivers/interrupts/irqs.c +++ b/src/kernel/drivers/interrupts/irqs.c @@ -61,7 +61,7 @@ return; } if (irqNumber == 7 || irqNumber == 2) { - // irq2 should not be fired, irq 7 is a spurious irq + // irq2 should not be fired, irq 7 indicates a spurious irq return; } printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber); diff --git a/src/kernel/drivers/interrupts/keyboard/keyboard.c b/src/kernel/drivers/interrupts/keyboard/keyboard.c index 94b3dad..99fdd04 100644 --- a/src/kernel/drivers/interrupts/keyboard/keyboard.c +++ b/src/kernel/drivers/interrupts/keyboard/keyboard.c @@ -77,6 +77,7 @@ message->type = KEYBOARD_STRING; message->size = strlen(message->data); listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); return; } if (scancode & 0x80) { @@ -96,15 +97,16 @@ } void *data = NULL; if (modifiers & MODIFIER_LEFT_SHIFT || modifiers & MODIFIER_RIGHT_SHIFT) { - data = capitalKeycodes[scancode]; + data = (void *)(uint32_t)capitalKeycodes[scancode]; } else { - data = keycodes[scancode]; + data = (void *)(uint32_t)keycodes[scancode]; } Message *message = malloc(sizeof(Message)); message->data = data; message->size = 1; message->type = KEYBOARD_CHAR; listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); } void setupKeyboard() { setIRQHandler(1, &keyboardHandler); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index e57a651..35addee 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -27,14 +27,20 @@ #define CMD_COUNTER0 0x00 #define CMD_COUNTER2 0x80 -void setTimerFreq(uint32_t hz) { +void sleep(uint16_t millis) { + uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + getCurrentTask()->ticksLeft = millis; + yield(); +} + +void setTimerFrequency(uint32_t hz) { int divisor = PIT_SCALE / hz; outb(PIT_CONTROL, CMD_BINARY | CMD_MODE3 | CMD_RW_BOTH | CMD_COUNTER0); outb(PIT_A, (uint8_t)divisor); outb(PIT_A, (uint8_t)(divisor >> 8)); } -uint64_t timerMillis = 0; +uint32_t timerMillis = 0; void timerHandler() { timerMillis++; @@ -59,7 +65,6 @@ } void setupTimer() { - printf("setting timer frequency to 1kHz\n"); - setTimerFreq(1000); + setTimerFrequency(1000); setIRQHandler(0, &timerHandler); } diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c new file mode 100644 index 0000000..ea36871 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -0,0 +1,291 @@ +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +#define IDE_DATA_REGISTER 0 +#define IDE_ERROR_REGISTER 1 +#define IDE_SECTOR_COUNT_REGISTER 2 +#define IDE_SECTOR_NUMBER_REGISTER 3 +#define IDE_CYLINDER_LOW_REGISTER 4 +#define IDE_CYLINDER_HIGH_REGISTER 5 +// sector size, drive, head +#define IDE_SDH_REGISTER 6 +#define IDE_STATUS_REGISTER 7 +#define IDE_COMMAND_REGISTER 7 +#define IDE_ALTERNATE_STATUS_CONTROL_REGISTER 0 +#define IDE_DRIVE_ADDRESS_CONTROL_REGISTER 1 + +#define IDE_STATUS_BUSY 0x80 +#define IDE_STATUS_READY 0x40 +#define IDE_STATUS_WRITE_FAULT 0x20 +#define IDE_STATUS_SEEK_COMPLETE 0x10 +#define IDE_STATUS_DATA_REQUEST 0x08 +#define IDE_STATUS_CORRECTED_DATA 0x04 +#define IDE_STATUS_INDEX 0x02 +#define IDE_STATUS_ERROR 0x01 + +#define IDE_IDENTIFY_COMMAND 0xEC + +char *driveTypes[] = { + "ISA Compatibility mode-only controller", + "PCI native mode-only controller", + "ISA Compatibility mode controller", + "PCI native mode controller", +}; + +void setupIDEChannels(IdeChannels *channels, PciDevice *pciDevice) { + if (pciDevice->programmingInterface & 0x01) { + channels->base = pciDevice->bar0; + channels->control = pciDevice->bar1; + } else { + channels->base = 0x1F0; + channels->control = 0x3F6; + } + if (pciDevice->programmingInterface & 0x04) { + channels[1].base = pciDevice->bar2; + channels[1].control = pciDevice->bar3; + } else { + channels[1].base = 0x170; + channels[1].control = 0x376; + } +} + +void ideWriteControlRegister(IdeChannels *channel, uint8_t reg, uint8_t data) { + outb(channel->control + reg, data); +} + +void ideWriteRegister(IdeChannels *channel, uint8_t reg, uint16_t data) { + outb(channel->base + reg, data); + if (data > 0xFF) { + // set higher half bit in the control register + outb(channel->control, 0x0A); + outb(channel->base + reg, data >> 8); + outb(channel->control, 0x02); + } +} + +uint8_t ideReadControlRegister(IdeChannels *channel, uint8_t reg) { + return inb(channel->control + reg); +} + +uint8_t ideReadRegister(IdeChannels *channel, uint16_t reg) { + return inw(channel->base + reg); +} + +void ideReadBuffer(IdeChannels *channel, uint32_t *data) { + for (uint16_t i = 0; i < 128; i++) { + data[i] = ini(channel->base + IDE_DATA_REGISTER); + } +} + +void printError(uint16_t); + +void ideWaitUntilNotBusy(IdeChannels *channel, bool checkErrors) { + for (uint8_t i = 0; i < 4; i++) { + ideReadControlRegister(channel, 0); + } + uint16_t status = ideReadRegister(channel, IDE_STATUS_REGISTER); + while (status & IDE_STATUS_BUSY) { + status = ideReadRegister(channel, IDE_STATUS_REGISTER); + } + if (checkErrors && status & IDE_STATUS_ERROR) { + printf("encountered an error\n"); + printError(ideReadRegister(channel, IDE_ERROR_REGISTER)); + } +} + +void ideCommand(IdeChannels *channel, uint8_t command) { + ideWaitUntilNotBusy(channel, false); + ideWriteRegister(channel, IDE_COMMAND_REGISTER, command); +} + +#define CHANNEL &channels[channel] + +void initializeIDEDrive(PciDevice *pciDevice, ListElement **drives) { + uint8_t *buffer = malloc(2048); + IdeChannels *channels = malloc(sizeof(IdeChannels) * 2); + setupIDEChannels(channels, pciDevice); + for (uint8_t channel = 0; channel < 2; channel++) { + if (ideReadRegister(CHANNEL, IDE_STATUS_REGISTER) == 0) { + // no device + continue; + } + ideWriteControlRegister(CHANNEL, IDE_ALTERNATE_STATUS_CONTROL_REGISTER, + 2); + for (uint8_t drive = 0; drive < 2; drive++) { + ideWaitUntilNotBusy(CHANNEL, true); + // set the drive + ideWriteRegister(CHANNEL, IDE_SDH_REGISTER, 0xA0 | (drive << 4)); + ideWriteRegister(CHANNEL, IDE_SECTOR_COUNT_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_SECTOR_NUMBER_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_LOW_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_HIGH_REGISTER, 0); + ideCommand(CHANNEL, IDE_IDENTIFY_COMMAND); + ideWaitUntilNotBusy(CHANNEL, true); + ideReadBuffer(CHANNEL, (void *)buffer); + if (*((uint16_t *)buffer) == 0) { + // any bit has to be set if it is a real device + continue; + } + char *model = malloc(41); + for (int i = 0; i < 40; i += 2) { + *((uint16_t *)&model[i]) = buffer[54 + i + 1]; + *((uint16_t *)&model[i + 1]) = buffer[54 + i]; + } + model[40] = 0; + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->model = model; + hardDrive->channels = CHANNEL; + hardDrive->channel = channel; + hardDrive->drive = drive; + hardDrive->type = *(uint16_t *)buffer; + hardDrive->cylinders = *(uint16_t *)buffer + 2; + hardDrive->heads = *(uint16_t *)buffer + 6; + hardDrive->sectors = *(uint16_t *)buffer + 12; + hardDrive->capabilities = *(uint16_t *)buffer + 98; + hardDrive->commandSets = *(uint32_t *)(buffer + 164); + if (hardDrive->commandSets + (1 << 26)) { + hardDrive->size = *(uint32_t *)buffer + 200; + } else { + hardDrive->size = *(uint32_t *)buffer + 120; + } + listAdd(drives, hardDrive); + printf("found a hard drive %i bytes, %i:%i, model: %s\n", + hardDrive->size, channel, drive, model); + } + } + free(buffer); +} + +void printError(uint16_t status) { + if (status & 0x01) { + printf("No address mark\n"); + } + if (status & 0x02) { + printf("Track 0 not found\n"); + } + if (status & 0x04) { + printf("command aborted\n"); + } + if (status & 0x08) { + printf("Media change request\n"); + } + if (status & 0x10) { + printf("ID mark not found\n"); + } + if (status & 0x20) { + printf("Media changed\n"); + } + if (status & 0x40) { + printf("uncorrectable data\n"); + } + if (status & 0x80) { + printf("bad block\n"); + } +} + +void driveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, + uint8_t sectorCount, uint8_t direction) { + uint8_t accessMode = 0, head = 0, sector = 0, cylinder = 0; + uint32_t lbaIo[6] = {0, 0, 0, 0, 0, 0}; + if (lba >= 0x10000000) { + accessMode = 2; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x0000FF00) >> 8; + lbaIo[2] = (lba & 0x00FF0000) >> 16; + lbaIo[3] = (lba & 0xFF000000) >> 24; + } else if (hardDrive->capabilities & 0x200) { + accessMode = 1; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x000FF00) >> 8; + lbaIo[2] = (lba & 0x0FF0000) >> 16; + head = (lba & 0xF000000) >> 24; + } else { + sector = (lba % 63) + 1; + cylinder = (lba + 1 - sector) / (16 * 63); + lbaIo[0] = sector; + lbaIo[1] = (uint8_t)cylinder; + lbaIo[2] = (cylinder >> 8) & 0xFF; + head = (lba + 1 - sector) % (16 * 63) / (63); + } + ideWaitUntilNotBusy(hardDrive->channels, true); + if (accessMode == 0) { + // chs + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xA0 | (hardDrive->drive << 4)); + } else { + // lba + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xE0 | (hardDrive->drive << 4) | head); + } + ideWriteRegister(hardDrive->channels, IDE_SECTOR_COUNT_REGISTER, + sectorCount); + ideWriteRegister(hardDrive->channels, IDE_SECTOR_NUMBER_REGISTER, + lbaIo[3] << 8 | lbaIo[0]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_LOW_REGISTER, + lbaIo[4] << 8 | lbaIo[1]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_HIGH_REGISTER, + lbaIo[5] << 8 | lbaIo[2]); + uint8_t command = 0; + if (direction == 0) { + // read + if (accessMode == 2) { + command = 0x24; + } else { + command = 0x20; + } + } else { + // write + if (accessMode == 2) { + command = 0x34; + } else { + command = 0x30; + } + } + ideCommand(hardDrive->channels, command); + ideWaitUntilNotBusy(hardDrive->channels, true); + if (direction == 0) { + uint16_t status; + void *current = buffer; + for (uint8_t i = 0; i < sectorCount; i++) { + ideWaitUntilNotBusy(hardDrive->channels, true); + ideReadBuffer(hardDrive->channels, (void *)buffer); + } + } +} + +void initializeSATADrive(PciDevice *pciDevice) { + // todo +} + +void scanHardDrives() { + ListElement *drives = NULL; + for (ListElement *current = *getPciDevices(); current; + current = current->next) { + PciDevice *pciDevice = current->data; + if (pciDevice->class != 1) { + continue; + } + switch (pciDevice->subclass) { + case 1: + initializeIDEDrive(pciDevice, &drives); + break; + case 6: + printf("found a SATA-controller: %i:%i:%i\n", pciDevice->bus, + pciDevice->device, pciDevice->function); + initializeSATADrive(pciDevice); + break; + } + } + void *buffer = malloc(2000); + for (ListElement *current = drives; current; current = current->next) { + driveAccess(current->data, 0, buffer, 1, 0); + printf("data: %x %x %s\n", *(uint32_t *)buffer, + *((uint32_t *)buffer + 1), buffer); + } + free(buffer); +} diff --git a/src/kernel/drivers/pci/pci.c b/src/kernel/drivers/pci/pci.c index 9874077..96cbfc3 100644 --- a/src/kernel/drivers/pci/pci.c +++ b/src/kernel/drivers/pci/pci.c @@ -35,6 +35,8 @@ ListElement *pciDevices = NULL; +ListElement **getPciDevices() { return &pciDevices; } + uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset) { uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | @@ -46,6 +48,16 @@ return result; } +void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data) { + uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | + (offset & 0xFC) | 0x80000000); + asm("cli"); + outi(0xCF8, address); + outb(0xCFC, data); + asm("sti"); +} + uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) { return (uint16_t)pciConfigReadByte(bus, device, function, offset) | @@ -53,6 +65,13 @@ << 8); } +uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset) { + return (uint32_t)pciConfigReadWord(bus, device, function, offset) | + ((uint32_t)pciConfigReadWord(bus, device, function, offset + 2) + << 16); +} + uint8_t getHeaderType(uint8_t bus, uint8_t device, uint8_t function) { return pciConfigReadByte(bus, device, function, 0x0E); } @@ -74,6 +93,14 @@ pciDevice->subclass = subclass; pciDevice->vendorId = pciConfigReadWord(bus, device, function, 0x00); pciDevice->deviceId = pciConfigReadWord(bus, device, function, 0x02); + pciDevice->programmingInterface = + pciConfigReadByte(bus, device, function, 0x09); + pciDevice->bar0 = pciConfigReadInt(bus, device, function, 0x10); + pciDevice->bar1 = pciConfigReadInt(bus, device, function, 0x14); + pciDevice->bar2 = pciConfigReadInt(bus, device, function, 0x18); + pciDevice->bar3 = pciConfigReadInt(bus, device, function, 0x1C); + pciDevice->bar4 = pciConfigReadInt(bus, device, function, 0x20); + pciDevice->bar5 = pciConfigReadInt(bus, device, function, 0x24); listAdd(&pciDevices, pciDevice); if (class == 6 && subclass == 4) { checkBus(pciConfigReadByte(bus, device, function, 0x19)); @@ -87,7 +114,7 @@ } if (getHeaderType(bus, device, 0) & 0x80) { // multifunction device - for (uint16_t function = 0; function < 256; function++) { + for (uint16_t function = 0; function < 8; function++) { if (getVendorID(bus, device, function) != 0xFFFF) { checkFunction(bus, device, function); } @@ -102,7 +129,7 @@ return; } checkedBuses[bus] = true; - for (uint16_t device = 0; device < 256; device++) { + for (uint16_t device = 0; device < 32; device++) { checkDevice(bus, device); } } diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 15713cc..7375f67 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -17,18 +18,16 @@ 0x1000000); // initializing stacks after the kernel seems not to work :( // otherwise, _kernel_end should be passed here initOSTasks(); + getCurrentTask()->timerTicks = 1000; + getCurrentTask()->ticksLeft = 1000; drawLogo(); + yields(); setupDevices(); setupInterrupts(); printCPUData(); scanPCIDevices(); - yields(); - getCurrentTask()->timerTicks = 1000; - getCurrentTask()->ticksLeft = 1000; + scanHardDrives(); while (1) { - if (isTaskQueueEmpty()) { - asm volatile("hlt"); - } for (Message *message = popBeginning(&(getCurrentTask()->messages)); message; message = popBeginning(&getCurrentTask()->messages)) { switch (message->type) { @@ -44,6 +43,6 @@ } free(message); } - yields(); + yield(); } } diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c index b968b61..868b8b6 100644 --- a/src/kernel/memory/alloc.c +++ b/src/kernel/memory/alloc.c @@ -37,6 +37,7 @@ current->next->state = FREE; current->next->next = next; next->last = current->next; + next = current->next; } else { current->next = next; } diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c index 37ab866..7b0d6c9 100644 --- a/src/kernel/task/osTasks.c +++ b/src/kernel/task/osTasks.c @@ -26,13 +26,7 @@ void initOSTasks() { setRunningTask(&mainTask); - mainTask.ticksLeft = -1; - mainTask.timerTicks = -1; - keyboardConsumer = &mainTask; createTask(&printerTask, (uint32_t)printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); } inline Task *getPrinterTask() { return &printerTask; } diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/src/kernel/drivers/interrupts/irqs.c b/src/kernel/drivers/interrupts/irqs.c index 60d95f8..1cd8c79 100644 --- a/src/kernel/drivers/interrupts/irqs.c +++ b/src/kernel/drivers/interrupts/irqs.c @@ -61,7 +61,7 @@ return; } if (irqNumber == 7 || irqNumber == 2) { - // irq2 should not be fired, irq 7 is a spurious irq + // irq2 should not be fired, irq 7 indicates a spurious irq return; } printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber); diff --git a/src/kernel/drivers/interrupts/keyboard/keyboard.c b/src/kernel/drivers/interrupts/keyboard/keyboard.c index 94b3dad..99fdd04 100644 --- a/src/kernel/drivers/interrupts/keyboard/keyboard.c +++ b/src/kernel/drivers/interrupts/keyboard/keyboard.c @@ -77,6 +77,7 @@ message->type = KEYBOARD_STRING; message->size = strlen(message->data); listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); return; } if (scancode & 0x80) { @@ -96,15 +97,16 @@ } void *data = NULL; if (modifiers & MODIFIER_LEFT_SHIFT || modifiers & MODIFIER_RIGHT_SHIFT) { - data = capitalKeycodes[scancode]; + data = (void *)(uint32_t)capitalKeycodes[scancode]; } else { - data = keycodes[scancode]; + data = (void *)(uint32_t)keycodes[scancode]; } Message *message = malloc(sizeof(Message)); message->data = data; message->size = 1; message->type = KEYBOARD_CHAR; listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); } void setupKeyboard() { setIRQHandler(1, &keyboardHandler); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index e57a651..35addee 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -27,14 +27,20 @@ #define CMD_COUNTER0 0x00 #define CMD_COUNTER2 0x80 -void setTimerFreq(uint32_t hz) { +void sleep(uint16_t millis) { + uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + getCurrentTask()->ticksLeft = millis; + yield(); +} + +void setTimerFrequency(uint32_t hz) { int divisor = PIT_SCALE / hz; outb(PIT_CONTROL, CMD_BINARY | CMD_MODE3 | CMD_RW_BOTH | CMD_COUNTER0); outb(PIT_A, (uint8_t)divisor); outb(PIT_A, (uint8_t)(divisor >> 8)); } -uint64_t timerMillis = 0; +uint32_t timerMillis = 0; void timerHandler() { timerMillis++; @@ -59,7 +65,6 @@ } void setupTimer() { - printf("setting timer frequency to 1kHz\n"); - setTimerFreq(1000); + setTimerFrequency(1000); setIRQHandler(0, &timerHandler); } diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c new file mode 100644 index 0000000..ea36871 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -0,0 +1,291 @@ +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +#define IDE_DATA_REGISTER 0 +#define IDE_ERROR_REGISTER 1 +#define IDE_SECTOR_COUNT_REGISTER 2 +#define IDE_SECTOR_NUMBER_REGISTER 3 +#define IDE_CYLINDER_LOW_REGISTER 4 +#define IDE_CYLINDER_HIGH_REGISTER 5 +// sector size, drive, head +#define IDE_SDH_REGISTER 6 +#define IDE_STATUS_REGISTER 7 +#define IDE_COMMAND_REGISTER 7 +#define IDE_ALTERNATE_STATUS_CONTROL_REGISTER 0 +#define IDE_DRIVE_ADDRESS_CONTROL_REGISTER 1 + +#define IDE_STATUS_BUSY 0x80 +#define IDE_STATUS_READY 0x40 +#define IDE_STATUS_WRITE_FAULT 0x20 +#define IDE_STATUS_SEEK_COMPLETE 0x10 +#define IDE_STATUS_DATA_REQUEST 0x08 +#define IDE_STATUS_CORRECTED_DATA 0x04 +#define IDE_STATUS_INDEX 0x02 +#define IDE_STATUS_ERROR 0x01 + +#define IDE_IDENTIFY_COMMAND 0xEC + +char *driveTypes[] = { + "ISA Compatibility mode-only controller", + "PCI native mode-only controller", + "ISA Compatibility mode controller", + "PCI native mode controller", +}; + +void setupIDEChannels(IdeChannels *channels, PciDevice *pciDevice) { + if (pciDevice->programmingInterface & 0x01) { + channels->base = pciDevice->bar0; + channels->control = pciDevice->bar1; + } else { + channels->base = 0x1F0; + channels->control = 0x3F6; + } + if (pciDevice->programmingInterface & 0x04) { + channels[1].base = pciDevice->bar2; + channels[1].control = pciDevice->bar3; + } else { + channels[1].base = 0x170; + channels[1].control = 0x376; + } +} + +void ideWriteControlRegister(IdeChannels *channel, uint8_t reg, uint8_t data) { + outb(channel->control + reg, data); +} + +void ideWriteRegister(IdeChannels *channel, uint8_t reg, uint16_t data) { + outb(channel->base + reg, data); + if (data > 0xFF) { + // set higher half bit in the control register + outb(channel->control, 0x0A); + outb(channel->base + reg, data >> 8); + outb(channel->control, 0x02); + } +} + +uint8_t ideReadControlRegister(IdeChannels *channel, uint8_t reg) { + return inb(channel->control + reg); +} + +uint8_t ideReadRegister(IdeChannels *channel, uint16_t reg) { + return inw(channel->base + reg); +} + +void ideReadBuffer(IdeChannels *channel, uint32_t *data) { + for (uint16_t i = 0; i < 128; i++) { + data[i] = ini(channel->base + IDE_DATA_REGISTER); + } +} + +void printError(uint16_t); + +void ideWaitUntilNotBusy(IdeChannels *channel, bool checkErrors) { + for (uint8_t i = 0; i < 4; i++) { + ideReadControlRegister(channel, 0); + } + uint16_t status = ideReadRegister(channel, IDE_STATUS_REGISTER); + while (status & IDE_STATUS_BUSY) { + status = ideReadRegister(channel, IDE_STATUS_REGISTER); + } + if (checkErrors && status & IDE_STATUS_ERROR) { + printf("encountered an error\n"); + printError(ideReadRegister(channel, IDE_ERROR_REGISTER)); + } +} + +void ideCommand(IdeChannels *channel, uint8_t command) { + ideWaitUntilNotBusy(channel, false); + ideWriteRegister(channel, IDE_COMMAND_REGISTER, command); +} + +#define CHANNEL &channels[channel] + +void initializeIDEDrive(PciDevice *pciDevice, ListElement **drives) { + uint8_t *buffer = malloc(2048); + IdeChannels *channels = malloc(sizeof(IdeChannels) * 2); + setupIDEChannels(channels, pciDevice); + for (uint8_t channel = 0; channel < 2; channel++) { + if (ideReadRegister(CHANNEL, IDE_STATUS_REGISTER) == 0) { + // no device + continue; + } + ideWriteControlRegister(CHANNEL, IDE_ALTERNATE_STATUS_CONTROL_REGISTER, + 2); + for (uint8_t drive = 0; drive < 2; drive++) { + ideWaitUntilNotBusy(CHANNEL, true); + // set the drive + ideWriteRegister(CHANNEL, IDE_SDH_REGISTER, 0xA0 | (drive << 4)); + ideWriteRegister(CHANNEL, IDE_SECTOR_COUNT_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_SECTOR_NUMBER_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_LOW_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_HIGH_REGISTER, 0); + ideCommand(CHANNEL, IDE_IDENTIFY_COMMAND); + ideWaitUntilNotBusy(CHANNEL, true); + ideReadBuffer(CHANNEL, (void *)buffer); + if (*((uint16_t *)buffer) == 0) { + // any bit has to be set if it is a real device + continue; + } + char *model = malloc(41); + for (int i = 0; i < 40; i += 2) { + *((uint16_t *)&model[i]) = buffer[54 + i + 1]; + *((uint16_t *)&model[i + 1]) = buffer[54 + i]; + } + model[40] = 0; + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->model = model; + hardDrive->channels = CHANNEL; + hardDrive->channel = channel; + hardDrive->drive = drive; + hardDrive->type = *(uint16_t *)buffer; + hardDrive->cylinders = *(uint16_t *)buffer + 2; + hardDrive->heads = *(uint16_t *)buffer + 6; + hardDrive->sectors = *(uint16_t *)buffer + 12; + hardDrive->capabilities = *(uint16_t *)buffer + 98; + hardDrive->commandSets = *(uint32_t *)(buffer + 164); + if (hardDrive->commandSets + (1 << 26)) { + hardDrive->size = *(uint32_t *)buffer + 200; + } else { + hardDrive->size = *(uint32_t *)buffer + 120; + } + listAdd(drives, hardDrive); + printf("found a hard drive %i bytes, %i:%i, model: %s\n", + hardDrive->size, channel, drive, model); + } + } + free(buffer); +} + +void printError(uint16_t status) { + if (status & 0x01) { + printf("No address mark\n"); + } + if (status & 0x02) { + printf("Track 0 not found\n"); + } + if (status & 0x04) { + printf("command aborted\n"); + } + if (status & 0x08) { + printf("Media change request\n"); + } + if (status & 0x10) { + printf("ID mark not found\n"); + } + if (status & 0x20) { + printf("Media changed\n"); + } + if (status & 0x40) { + printf("uncorrectable data\n"); + } + if (status & 0x80) { + printf("bad block\n"); + } +} + +void driveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, + uint8_t sectorCount, uint8_t direction) { + uint8_t accessMode = 0, head = 0, sector = 0, cylinder = 0; + uint32_t lbaIo[6] = {0, 0, 0, 0, 0, 0}; + if (lba >= 0x10000000) { + accessMode = 2; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x0000FF00) >> 8; + lbaIo[2] = (lba & 0x00FF0000) >> 16; + lbaIo[3] = (lba & 0xFF000000) >> 24; + } else if (hardDrive->capabilities & 0x200) { + accessMode = 1; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x000FF00) >> 8; + lbaIo[2] = (lba & 0x0FF0000) >> 16; + head = (lba & 0xF000000) >> 24; + } else { + sector = (lba % 63) + 1; + cylinder = (lba + 1 - sector) / (16 * 63); + lbaIo[0] = sector; + lbaIo[1] = (uint8_t)cylinder; + lbaIo[2] = (cylinder >> 8) & 0xFF; + head = (lba + 1 - sector) % (16 * 63) / (63); + } + ideWaitUntilNotBusy(hardDrive->channels, true); + if (accessMode == 0) { + // chs + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xA0 | (hardDrive->drive << 4)); + } else { + // lba + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xE0 | (hardDrive->drive << 4) | head); + } + ideWriteRegister(hardDrive->channels, IDE_SECTOR_COUNT_REGISTER, + sectorCount); + ideWriteRegister(hardDrive->channels, IDE_SECTOR_NUMBER_REGISTER, + lbaIo[3] << 8 | lbaIo[0]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_LOW_REGISTER, + lbaIo[4] << 8 | lbaIo[1]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_HIGH_REGISTER, + lbaIo[5] << 8 | lbaIo[2]); + uint8_t command = 0; + if (direction == 0) { + // read + if (accessMode == 2) { + command = 0x24; + } else { + command = 0x20; + } + } else { + // write + if (accessMode == 2) { + command = 0x34; + } else { + command = 0x30; + } + } + ideCommand(hardDrive->channels, command); + ideWaitUntilNotBusy(hardDrive->channels, true); + if (direction == 0) { + uint16_t status; + void *current = buffer; + for (uint8_t i = 0; i < sectorCount; i++) { + ideWaitUntilNotBusy(hardDrive->channels, true); + ideReadBuffer(hardDrive->channels, (void *)buffer); + } + } +} + +void initializeSATADrive(PciDevice *pciDevice) { + // todo +} + +void scanHardDrives() { + ListElement *drives = NULL; + for (ListElement *current = *getPciDevices(); current; + current = current->next) { + PciDevice *pciDevice = current->data; + if (pciDevice->class != 1) { + continue; + } + switch (pciDevice->subclass) { + case 1: + initializeIDEDrive(pciDevice, &drives); + break; + case 6: + printf("found a SATA-controller: %i:%i:%i\n", pciDevice->bus, + pciDevice->device, pciDevice->function); + initializeSATADrive(pciDevice); + break; + } + } + void *buffer = malloc(2000); + for (ListElement *current = drives; current; current = current->next) { + driveAccess(current->data, 0, buffer, 1, 0); + printf("data: %x %x %s\n", *(uint32_t *)buffer, + *((uint32_t *)buffer + 1), buffer); + } + free(buffer); +} diff --git a/src/kernel/drivers/pci/pci.c b/src/kernel/drivers/pci/pci.c index 9874077..96cbfc3 100644 --- a/src/kernel/drivers/pci/pci.c +++ b/src/kernel/drivers/pci/pci.c @@ -35,6 +35,8 @@ ListElement *pciDevices = NULL; +ListElement **getPciDevices() { return &pciDevices; } + uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset) { uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | @@ -46,6 +48,16 @@ return result; } +void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data) { + uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | + (offset & 0xFC) | 0x80000000); + asm("cli"); + outi(0xCF8, address); + outb(0xCFC, data); + asm("sti"); +} + uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) { return (uint16_t)pciConfigReadByte(bus, device, function, offset) | @@ -53,6 +65,13 @@ << 8); } +uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset) { + return (uint32_t)pciConfigReadWord(bus, device, function, offset) | + ((uint32_t)pciConfigReadWord(bus, device, function, offset + 2) + << 16); +} + uint8_t getHeaderType(uint8_t bus, uint8_t device, uint8_t function) { return pciConfigReadByte(bus, device, function, 0x0E); } @@ -74,6 +93,14 @@ pciDevice->subclass = subclass; pciDevice->vendorId = pciConfigReadWord(bus, device, function, 0x00); pciDevice->deviceId = pciConfigReadWord(bus, device, function, 0x02); + pciDevice->programmingInterface = + pciConfigReadByte(bus, device, function, 0x09); + pciDevice->bar0 = pciConfigReadInt(bus, device, function, 0x10); + pciDevice->bar1 = pciConfigReadInt(bus, device, function, 0x14); + pciDevice->bar2 = pciConfigReadInt(bus, device, function, 0x18); + pciDevice->bar3 = pciConfigReadInt(bus, device, function, 0x1C); + pciDevice->bar4 = pciConfigReadInt(bus, device, function, 0x20); + pciDevice->bar5 = pciConfigReadInt(bus, device, function, 0x24); listAdd(&pciDevices, pciDevice); if (class == 6 && subclass == 4) { checkBus(pciConfigReadByte(bus, device, function, 0x19)); @@ -87,7 +114,7 @@ } if (getHeaderType(bus, device, 0) & 0x80) { // multifunction device - for (uint16_t function = 0; function < 256; function++) { + for (uint16_t function = 0; function < 8; function++) { if (getVendorID(bus, device, function) != 0xFFFF) { checkFunction(bus, device, function); } @@ -102,7 +129,7 @@ return; } checkedBuses[bus] = true; - for (uint16_t device = 0; device < 256; device++) { + for (uint16_t device = 0; device < 32; device++) { checkDevice(bus, device); } } diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 15713cc..7375f67 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -17,18 +18,16 @@ 0x1000000); // initializing stacks after the kernel seems not to work :( // otherwise, _kernel_end should be passed here initOSTasks(); + getCurrentTask()->timerTicks = 1000; + getCurrentTask()->ticksLeft = 1000; drawLogo(); + yields(); setupDevices(); setupInterrupts(); printCPUData(); scanPCIDevices(); - yields(); - getCurrentTask()->timerTicks = 1000; - getCurrentTask()->ticksLeft = 1000; + scanHardDrives(); while (1) { - if (isTaskQueueEmpty()) { - asm volatile("hlt"); - } for (Message *message = popBeginning(&(getCurrentTask()->messages)); message; message = popBeginning(&getCurrentTask()->messages)) { switch (message->type) { @@ -44,6 +43,6 @@ } free(message); } - yields(); + yield(); } } diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c index b968b61..868b8b6 100644 --- a/src/kernel/memory/alloc.c +++ b/src/kernel/memory/alloc.c @@ -37,6 +37,7 @@ current->next->state = FREE; current->next->next = next; next->last = current->next; + next = current->next; } else { current->next = next; } diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c index 37ab866..7b0d6c9 100644 --- a/src/kernel/task/osTasks.c +++ b/src/kernel/task/osTasks.c @@ -26,13 +26,7 @@ void initOSTasks() { setRunningTask(&mainTask); - mainTask.ticksLeft = -1; - mainTask.timerTicks = -1; - keyboardConsumer = &mainTask; createTask(&printerTask, (uint32_t)printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); } inline Task *getPrinterTask() { return &printerTask; } diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c index e001f9f..30d4d9f 100644 --- a/src/kernel/task/task.c +++ b/src/kernel/task/task.c @@ -11,7 +11,7 @@ void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - listAddSet(&allTasks, task); + listAdd(&allTasks, task); void *stack = mallocTask(STACK_SIZE, task); task->registers.eax = 0; task->registers.ebx = 0; @@ -32,9 +32,12 @@ void yield() { Task *last = currentTask; currentTask = popBeginning(&scheduledTasks); - if (currentTask == NULL) { - while (1) - ; + while (currentTask == 0) { + asm("sti"); + asm("hlt"); + currentTask = popBeginning(&scheduledTasks); + } + if (last == currentTask) { return; } switchTask(&(last->registers), &(currentTask->registers)); @@ -52,12 +55,11 @@ inline Task *getCurrentTask() { return currentTask; } -inline void schedule(Task *task) { listAddSet(&scheduledTasks, task); } +inline void schedule(Task *task) { listAdd(&scheduledTasks, task); } inline void setRunningTask(Task *task) { currentTask = task; listAddSet(&allTasks, task); } -inline bool isTaskQueueEmpty() { return scheduledTasks == NULL; } inline ListElement *getAllTasks() { return allTasks; } diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/src/kernel/drivers/interrupts/irqs.c b/src/kernel/drivers/interrupts/irqs.c index 60d95f8..1cd8c79 100644 --- a/src/kernel/drivers/interrupts/irqs.c +++ b/src/kernel/drivers/interrupts/irqs.c @@ -61,7 +61,7 @@ return; } if (irqNumber == 7 || irqNumber == 2) { - // irq2 should not be fired, irq 7 is a spurious irq + // irq2 should not be fired, irq 7 indicates a spurious irq return; } printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber); diff --git a/src/kernel/drivers/interrupts/keyboard/keyboard.c b/src/kernel/drivers/interrupts/keyboard/keyboard.c index 94b3dad..99fdd04 100644 --- a/src/kernel/drivers/interrupts/keyboard/keyboard.c +++ b/src/kernel/drivers/interrupts/keyboard/keyboard.c @@ -77,6 +77,7 @@ message->type = KEYBOARD_STRING; message->size = strlen(message->data); listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); return; } if (scancode & 0x80) { @@ -96,15 +97,16 @@ } void *data = NULL; if (modifiers & MODIFIER_LEFT_SHIFT || modifiers & MODIFIER_RIGHT_SHIFT) { - data = capitalKeycodes[scancode]; + data = (void *)(uint32_t)capitalKeycodes[scancode]; } else { - data = keycodes[scancode]; + data = (void *)(uint32_t)keycodes[scancode]; } Message *message = malloc(sizeof(Message)); message->data = data; message->size = 1; message->type = KEYBOARD_CHAR; listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); } void setupKeyboard() { setIRQHandler(1, &keyboardHandler); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index e57a651..35addee 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -27,14 +27,20 @@ #define CMD_COUNTER0 0x00 #define CMD_COUNTER2 0x80 -void setTimerFreq(uint32_t hz) { +void sleep(uint16_t millis) { + uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + getCurrentTask()->ticksLeft = millis; + yield(); +} + +void setTimerFrequency(uint32_t hz) { int divisor = PIT_SCALE / hz; outb(PIT_CONTROL, CMD_BINARY | CMD_MODE3 | CMD_RW_BOTH | CMD_COUNTER0); outb(PIT_A, (uint8_t)divisor); outb(PIT_A, (uint8_t)(divisor >> 8)); } -uint64_t timerMillis = 0; +uint32_t timerMillis = 0; void timerHandler() { timerMillis++; @@ -59,7 +65,6 @@ } void setupTimer() { - printf("setting timer frequency to 1kHz\n"); - setTimerFreq(1000); + setTimerFrequency(1000); setIRQHandler(0, &timerHandler); } diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c new file mode 100644 index 0000000..ea36871 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -0,0 +1,291 @@ +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +#define IDE_DATA_REGISTER 0 +#define IDE_ERROR_REGISTER 1 +#define IDE_SECTOR_COUNT_REGISTER 2 +#define IDE_SECTOR_NUMBER_REGISTER 3 +#define IDE_CYLINDER_LOW_REGISTER 4 +#define IDE_CYLINDER_HIGH_REGISTER 5 +// sector size, drive, head +#define IDE_SDH_REGISTER 6 +#define IDE_STATUS_REGISTER 7 +#define IDE_COMMAND_REGISTER 7 +#define IDE_ALTERNATE_STATUS_CONTROL_REGISTER 0 +#define IDE_DRIVE_ADDRESS_CONTROL_REGISTER 1 + +#define IDE_STATUS_BUSY 0x80 +#define IDE_STATUS_READY 0x40 +#define IDE_STATUS_WRITE_FAULT 0x20 +#define IDE_STATUS_SEEK_COMPLETE 0x10 +#define IDE_STATUS_DATA_REQUEST 0x08 +#define IDE_STATUS_CORRECTED_DATA 0x04 +#define IDE_STATUS_INDEX 0x02 +#define IDE_STATUS_ERROR 0x01 + +#define IDE_IDENTIFY_COMMAND 0xEC + +char *driveTypes[] = { + "ISA Compatibility mode-only controller", + "PCI native mode-only controller", + "ISA Compatibility mode controller", + "PCI native mode controller", +}; + +void setupIDEChannels(IdeChannels *channels, PciDevice *pciDevice) { + if (pciDevice->programmingInterface & 0x01) { + channels->base = pciDevice->bar0; + channels->control = pciDevice->bar1; + } else { + channels->base = 0x1F0; + channels->control = 0x3F6; + } + if (pciDevice->programmingInterface & 0x04) { + channels[1].base = pciDevice->bar2; + channels[1].control = pciDevice->bar3; + } else { + channels[1].base = 0x170; + channels[1].control = 0x376; + } +} + +void ideWriteControlRegister(IdeChannels *channel, uint8_t reg, uint8_t data) { + outb(channel->control + reg, data); +} + +void ideWriteRegister(IdeChannels *channel, uint8_t reg, uint16_t data) { + outb(channel->base + reg, data); + if (data > 0xFF) { + // set higher half bit in the control register + outb(channel->control, 0x0A); + outb(channel->base + reg, data >> 8); + outb(channel->control, 0x02); + } +} + +uint8_t ideReadControlRegister(IdeChannels *channel, uint8_t reg) { + return inb(channel->control + reg); +} + +uint8_t ideReadRegister(IdeChannels *channel, uint16_t reg) { + return inw(channel->base + reg); +} + +void ideReadBuffer(IdeChannels *channel, uint32_t *data) { + for (uint16_t i = 0; i < 128; i++) { + data[i] = ini(channel->base + IDE_DATA_REGISTER); + } +} + +void printError(uint16_t); + +void ideWaitUntilNotBusy(IdeChannels *channel, bool checkErrors) { + for (uint8_t i = 0; i < 4; i++) { + ideReadControlRegister(channel, 0); + } + uint16_t status = ideReadRegister(channel, IDE_STATUS_REGISTER); + while (status & IDE_STATUS_BUSY) { + status = ideReadRegister(channel, IDE_STATUS_REGISTER); + } + if (checkErrors && status & IDE_STATUS_ERROR) { + printf("encountered an error\n"); + printError(ideReadRegister(channel, IDE_ERROR_REGISTER)); + } +} + +void ideCommand(IdeChannels *channel, uint8_t command) { + ideWaitUntilNotBusy(channel, false); + ideWriteRegister(channel, IDE_COMMAND_REGISTER, command); +} + +#define CHANNEL &channels[channel] + +void initializeIDEDrive(PciDevice *pciDevice, ListElement **drives) { + uint8_t *buffer = malloc(2048); + IdeChannels *channels = malloc(sizeof(IdeChannels) * 2); + setupIDEChannels(channels, pciDevice); + for (uint8_t channel = 0; channel < 2; channel++) { + if (ideReadRegister(CHANNEL, IDE_STATUS_REGISTER) == 0) { + // no device + continue; + } + ideWriteControlRegister(CHANNEL, IDE_ALTERNATE_STATUS_CONTROL_REGISTER, + 2); + for (uint8_t drive = 0; drive < 2; drive++) { + ideWaitUntilNotBusy(CHANNEL, true); + // set the drive + ideWriteRegister(CHANNEL, IDE_SDH_REGISTER, 0xA0 | (drive << 4)); + ideWriteRegister(CHANNEL, IDE_SECTOR_COUNT_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_SECTOR_NUMBER_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_LOW_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_HIGH_REGISTER, 0); + ideCommand(CHANNEL, IDE_IDENTIFY_COMMAND); + ideWaitUntilNotBusy(CHANNEL, true); + ideReadBuffer(CHANNEL, (void *)buffer); + if (*((uint16_t *)buffer) == 0) { + // any bit has to be set if it is a real device + continue; + } + char *model = malloc(41); + for (int i = 0; i < 40; i += 2) { + *((uint16_t *)&model[i]) = buffer[54 + i + 1]; + *((uint16_t *)&model[i + 1]) = buffer[54 + i]; + } + model[40] = 0; + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->model = model; + hardDrive->channels = CHANNEL; + hardDrive->channel = channel; + hardDrive->drive = drive; + hardDrive->type = *(uint16_t *)buffer; + hardDrive->cylinders = *(uint16_t *)buffer + 2; + hardDrive->heads = *(uint16_t *)buffer + 6; + hardDrive->sectors = *(uint16_t *)buffer + 12; + hardDrive->capabilities = *(uint16_t *)buffer + 98; + hardDrive->commandSets = *(uint32_t *)(buffer + 164); + if (hardDrive->commandSets + (1 << 26)) { + hardDrive->size = *(uint32_t *)buffer + 200; + } else { + hardDrive->size = *(uint32_t *)buffer + 120; + } + listAdd(drives, hardDrive); + printf("found a hard drive %i bytes, %i:%i, model: %s\n", + hardDrive->size, channel, drive, model); + } + } + free(buffer); +} + +void printError(uint16_t status) { + if (status & 0x01) { + printf("No address mark\n"); + } + if (status & 0x02) { + printf("Track 0 not found\n"); + } + if (status & 0x04) { + printf("command aborted\n"); + } + if (status & 0x08) { + printf("Media change request\n"); + } + if (status & 0x10) { + printf("ID mark not found\n"); + } + if (status & 0x20) { + printf("Media changed\n"); + } + if (status & 0x40) { + printf("uncorrectable data\n"); + } + if (status & 0x80) { + printf("bad block\n"); + } +} + +void driveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, + uint8_t sectorCount, uint8_t direction) { + uint8_t accessMode = 0, head = 0, sector = 0, cylinder = 0; + uint32_t lbaIo[6] = {0, 0, 0, 0, 0, 0}; + if (lba >= 0x10000000) { + accessMode = 2; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x0000FF00) >> 8; + lbaIo[2] = (lba & 0x00FF0000) >> 16; + lbaIo[3] = (lba & 0xFF000000) >> 24; + } else if (hardDrive->capabilities & 0x200) { + accessMode = 1; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x000FF00) >> 8; + lbaIo[2] = (lba & 0x0FF0000) >> 16; + head = (lba & 0xF000000) >> 24; + } else { + sector = (lba % 63) + 1; + cylinder = (lba + 1 - sector) / (16 * 63); + lbaIo[0] = sector; + lbaIo[1] = (uint8_t)cylinder; + lbaIo[2] = (cylinder >> 8) & 0xFF; + head = (lba + 1 - sector) % (16 * 63) / (63); + } + ideWaitUntilNotBusy(hardDrive->channels, true); + if (accessMode == 0) { + // chs + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xA0 | (hardDrive->drive << 4)); + } else { + // lba + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xE0 | (hardDrive->drive << 4) | head); + } + ideWriteRegister(hardDrive->channels, IDE_SECTOR_COUNT_REGISTER, + sectorCount); + ideWriteRegister(hardDrive->channels, IDE_SECTOR_NUMBER_REGISTER, + lbaIo[3] << 8 | lbaIo[0]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_LOW_REGISTER, + lbaIo[4] << 8 | lbaIo[1]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_HIGH_REGISTER, + lbaIo[5] << 8 | lbaIo[2]); + uint8_t command = 0; + if (direction == 0) { + // read + if (accessMode == 2) { + command = 0x24; + } else { + command = 0x20; + } + } else { + // write + if (accessMode == 2) { + command = 0x34; + } else { + command = 0x30; + } + } + ideCommand(hardDrive->channels, command); + ideWaitUntilNotBusy(hardDrive->channels, true); + if (direction == 0) { + uint16_t status; + void *current = buffer; + for (uint8_t i = 0; i < sectorCount; i++) { + ideWaitUntilNotBusy(hardDrive->channels, true); + ideReadBuffer(hardDrive->channels, (void *)buffer); + } + } +} + +void initializeSATADrive(PciDevice *pciDevice) { + // todo +} + +void scanHardDrives() { + ListElement *drives = NULL; + for (ListElement *current = *getPciDevices(); current; + current = current->next) { + PciDevice *pciDevice = current->data; + if (pciDevice->class != 1) { + continue; + } + switch (pciDevice->subclass) { + case 1: + initializeIDEDrive(pciDevice, &drives); + break; + case 6: + printf("found a SATA-controller: %i:%i:%i\n", pciDevice->bus, + pciDevice->device, pciDevice->function); + initializeSATADrive(pciDevice); + break; + } + } + void *buffer = malloc(2000); + for (ListElement *current = drives; current; current = current->next) { + driveAccess(current->data, 0, buffer, 1, 0); + printf("data: %x %x %s\n", *(uint32_t *)buffer, + *((uint32_t *)buffer + 1), buffer); + } + free(buffer); +} diff --git a/src/kernel/drivers/pci/pci.c b/src/kernel/drivers/pci/pci.c index 9874077..96cbfc3 100644 --- a/src/kernel/drivers/pci/pci.c +++ b/src/kernel/drivers/pci/pci.c @@ -35,6 +35,8 @@ ListElement *pciDevices = NULL; +ListElement **getPciDevices() { return &pciDevices; } + uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset) { uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | @@ -46,6 +48,16 @@ return result; } +void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data) { + uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | + (offset & 0xFC) | 0x80000000); + asm("cli"); + outi(0xCF8, address); + outb(0xCFC, data); + asm("sti"); +} + uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) { return (uint16_t)pciConfigReadByte(bus, device, function, offset) | @@ -53,6 +65,13 @@ << 8); } +uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset) { + return (uint32_t)pciConfigReadWord(bus, device, function, offset) | + ((uint32_t)pciConfigReadWord(bus, device, function, offset + 2) + << 16); +} + uint8_t getHeaderType(uint8_t bus, uint8_t device, uint8_t function) { return pciConfigReadByte(bus, device, function, 0x0E); } @@ -74,6 +93,14 @@ pciDevice->subclass = subclass; pciDevice->vendorId = pciConfigReadWord(bus, device, function, 0x00); pciDevice->deviceId = pciConfigReadWord(bus, device, function, 0x02); + pciDevice->programmingInterface = + pciConfigReadByte(bus, device, function, 0x09); + pciDevice->bar0 = pciConfigReadInt(bus, device, function, 0x10); + pciDevice->bar1 = pciConfigReadInt(bus, device, function, 0x14); + pciDevice->bar2 = pciConfigReadInt(bus, device, function, 0x18); + pciDevice->bar3 = pciConfigReadInt(bus, device, function, 0x1C); + pciDevice->bar4 = pciConfigReadInt(bus, device, function, 0x20); + pciDevice->bar5 = pciConfigReadInt(bus, device, function, 0x24); listAdd(&pciDevices, pciDevice); if (class == 6 && subclass == 4) { checkBus(pciConfigReadByte(bus, device, function, 0x19)); @@ -87,7 +114,7 @@ } if (getHeaderType(bus, device, 0) & 0x80) { // multifunction device - for (uint16_t function = 0; function < 256; function++) { + for (uint16_t function = 0; function < 8; function++) { if (getVendorID(bus, device, function) != 0xFFFF) { checkFunction(bus, device, function); } @@ -102,7 +129,7 @@ return; } checkedBuses[bus] = true; - for (uint16_t device = 0; device < 256; device++) { + for (uint16_t device = 0; device < 32; device++) { checkDevice(bus, device); } } diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 15713cc..7375f67 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -17,18 +18,16 @@ 0x1000000); // initializing stacks after the kernel seems not to work :( // otherwise, _kernel_end should be passed here initOSTasks(); + getCurrentTask()->timerTicks = 1000; + getCurrentTask()->ticksLeft = 1000; drawLogo(); + yields(); setupDevices(); setupInterrupts(); printCPUData(); scanPCIDevices(); - yields(); - getCurrentTask()->timerTicks = 1000; - getCurrentTask()->ticksLeft = 1000; + scanHardDrives(); while (1) { - if (isTaskQueueEmpty()) { - asm volatile("hlt"); - } for (Message *message = popBeginning(&(getCurrentTask()->messages)); message; message = popBeginning(&getCurrentTask()->messages)) { switch (message->type) { @@ -44,6 +43,6 @@ } free(message); } - yields(); + yield(); } } diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c index b968b61..868b8b6 100644 --- a/src/kernel/memory/alloc.c +++ b/src/kernel/memory/alloc.c @@ -37,6 +37,7 @@ current->next->state = FREE; current->next->next = next; next->last = current->next; + next = current->next; } else { current->next = next; } diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c index 37ab866..7b0d6c9 100644 --- a/src/kernel/task/osTasks.c +++ b/src/kernel/task/osTasks.c @@ -26,13 +26,7 @@ void initOSTasks() { setRunningTask(&mainTask); - mainTask.ticksLeft = -1; - mainTask.timerTicks = -1; - keyboardConsumer = &mainTask; createTask(&printerTask, (uint32_t)printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); } inline Task *getPrinterTask() { return &printerTask; } diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c index e001f9f..30d4d9f 100644 --- a/src/kernel/task/task.c +++ b/src/kernel/task/task.c @@ -11,7 +11,7 @@ void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - listAddSet(&allTasks, task); + listAdd(&allTasks, task); void *stack = mallocTask(STACK_SIZE, task); task->registers.eax = 0; task->registers.ebx = 0; @@ -32,9 +32,12 @@ void yield() { Task *last = currentTask; currentTask = popBeginning(&scheduledTasks); - if (currentTask == NULL) { - while (1) - ; + while (currentTask == 0) { + asm("sti"); + asm("hlt"); + currentTask = popBeginning(&scheduledTasks); + } + if (last == currentTask) { return; } switchTask(&(last->registers), &(currentTask->registers)); @@ -52,12 +55,11 @@ inline Task *getCurrentTask() { return currentTask; } -inline void schedule(Task *task) { listAddSet(&scheduledTasks, task); } +inline void schedule(Task *task) { listAdd(&scheduledTasks, task); } inline void setRunningTask(Task *task) { currentTask = task; listAddSet(&allTasks, task); } -inline bool isTaskQueueEmpty() { return scheduledTasks == NULL; } inline ListElement *getAllTasks() { return allTasks; } diff --git a/src/kernel/util/list.c b/src/kernel/util/list.c index 2c29877..e5ee306 100644 --- a/src/kernel/util/list.c +++ b/src/kernel/util/list.c @@ -6,13 +6,13 @@ if (element == NULL) { *list = malloc(sizeof(ListElement)); element = *list; - element->next = NULL; } else { for (; element->next; element = element->next) { } element->next = malloc(sizeof(ListElement)); element = element->next; } + element->next = NULL; element->data = data; } @@ -21,7 +21,6 @@ if (element == NULL) { *list = malloc(sizeof(ListElement)); element = *list; - element->next = NULL; } else { for (; element->next; element = element->next) { if (element->data == data) { @@ -30,14 +29,14 @@ } element->next = malloc(sizeof(ListElement)); element = element->next; - element->next = NULL; } + element->next = NULL; element->data = data; } uint32_t listCount(ListElement *list) { int count = 0; - for (ListElement *current = list; current->next; current = current->next) { + for (ListElement *current = list; current; current = current->next) { count++; } return count; diff --git a/Makefile b/Makefile index 74dfe18..96dac6b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,38 +7,45 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -usb +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=image.raw + BUILD_FOLDER = build SOURCE_FILES := $(shell find src -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -default: run - run: tree-os.iso - $(EMU) $(EMUFLAGS) $^ + @echo "starting qemu" + @$(EMU) $(EMUFLAGS) tree-os.iso: iso/boot/tree-os.bin - grub-mkrescue -o $@ iso + @echo "creating the iso image" + @grub-mkrescue -o $@ iso iso/boot/tree-os.bin: linker.ld $(OBJS) - $(LD) $(LD_FLAGS) -o $@ $(OBJS) + @echo "linking" + @$(LD) $(LD_FLAGS) -o $@ $(OBJS) $(BUILD_FOLDER)/%.asm.o: %.asm - mkdir -p $(dir $@) - $(AS) $(ASFlAGS) $< -o $@ + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ $(BUILD_FOLDER)/%.c.o: %.c - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ $(BUILD_FOLDER)/%.s.o: %.s - mkdir -p $(dir $@) - $(CC) $(CCFLAGS) -r $< -o $@ + @echo "assembling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ clean: - rm -r $(BUILD_FOLDER) tree-os.iso iso/boot/tree-os.elf + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) tree-os.iso cleanELF: - rm iso/boot/tree-os.elf + @echo "clearing the elf file" + @rm iso/boot/tree-os.elf diff --git a/image.raw b/image.raw new file mode 100644 index 0000000..f120995 --- /dev/null +++ b/image.raw @@ -0,0 +1,2 @@ +Hello world this is a test image to see if the disk access will work! +If I can see this message everything seems to have worked :) diff --git a/src/include/_stdio.h b/src/include/_stdio.h index 164e21c..efd084f 100644 --- a/src/include/_stdio.h +++ b/src/include/_stdio.h @@ -6,5 +6,6 @@ extern void printf(const char *format, ...); extern uint32_t strlen(char *string); +extern void setTextStyle(uint8_t newFormat); #endif diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h new file mode 100644 index 0000000..819781d --- /dev/null +++ b/src/include/hardDrive.h @@ -0,0 +1,21 @@ +#ifndef HARD_DRIVE_H +#define HARD_DRIVE_H + +#include + +typedef struct { + uint16_t base, control, busMaster, noInterrupt; +} IdeChannels; + +typedef struct { + IdeChannels *channels; + char *model; + uint8_t channel, drive; + uint16_t capabilities, signature, type; + uint32_t commandSets, size; + uint16_t cylinders, heads, sectors; +} HardDrive; + +extern void scanHardDrives(); + +#endif diff --git a/src/include/pci.h b/src/include/pci.h index ec03a8e..9a16b66 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -1,14 +1,19 @@ #ifndef PCI_H #define PCI_H +#include #include typedef struct { uint8_t bus, device, function; uint8_t class, subclass; - uint16_t deviceId, vendorId; + uint16_t deviceId, vendorId, programmingInterface; + uint32_t bar0, bar1, bar2, bar3, bar4, bar5; } PciDevice; extern void scanPCIDevices(); +extern ListElement **getPciDevices(); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); #endif diff --git a/src/include/ports.h b/src/include/ports.h index 758d89e..465801a 100644 --- a/src/include/ports.h +++ b/src/include/ports.h @@ -6,6 +6,9 @@ extern void outb(uint16_t port, uint8_t val); extern uint8_t inb(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint16_t inw(uint16_t port); + extern void outi(uint16_t port, uint32_t val); extern uint32_t ini(uint16_t port); diff --git a/src/include/timer.h b/src/include/timer.h index e977777..559611e 100644 --- a/src/include/timer.h +++ b/src/include/timer.h @@ -1,6 +1,9 @@ #ifndef TIMER_H #define TIMER_H -extern void setupTimer(); +#include -#endif \ No newline at end of file +extern void setupTimer(); +extern void sleep(uint16_t millis); + +#endif diff --git a/src/kernel/drivers/interrupts/irqs.c b/src/kernel/drivers/interrupts/irqs.c index 60d95f8..1cd8c79 100644 --- a/src/kernel/drivers/interrupts/irqs.c +++ b/src/kernel/drivers/interrupts/irqs.c @@ -61,7 +61,7 @@ return; } if (irqNumber == 7 || irqNumber == 2) { - // irq2 should not be fired, irq 7 is a spurious irq + // irq2 should not be fired, irq 7 indicates a spurious irq return; } printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber); diff --git a/src/kernel/drivers/interrupts/keyboard/keyboard.c b/src/kernel/drivers/interrupts/keyboard/keyboard.c index 94b3dad..99fdd04 100644 --- a/src/kernel/drivers/interrupts/keyboard/keyboard.c +++ b/src/kernel/drivers/interrupts/keyboard/keyboard.c @@ -77,6 +77,7 @@ message->type = KEYBOARD_STRING; message->size = strlen(message->data); listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); return; } if (scancode & 0x80) { @@ -96,15 +97,16 @@ } void *data = NULL; if (modifiers & MODIFIER_LEFT_SHIFT || modifiers & MODIFIER_RIGHT_SHIFT) { - data = capitalKeycodes[scancode]; + data = (void *)(uint32_t)capitalKeycodes[scancode]; } else { - data = keycodes[scancode]; + data = (void *)(uint32_t)keycodes[scancode]; } Message *message = malloc(sizeof(Message)); message->data = data; message->size = 1; message->type = KEYBOARD_CHAR; listAdd(&(getKeyboardConsumer()->messages), message); + schedule(getKeyboardConsumer()); } void setupKeyboard() { setIRQHandler(1, &keyboardHandler); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index e57a651..35addee 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -27,14 +27,20 @@ #define CMD_COUNTER0 0x00 #define CMD_COUNTER2 0x80 -void setTimerFreq(uint32_t hz) { +void sleep(uint16_t millis) { + uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + getCurrentTask()->ticksLeft = millis; + yield(); +} + +void setTimerFrequency(uint32_t hz) { int divisor = PIT_SCALE / hz; outb(PIT_CONTROL, CMD_BINARY | CMD_MODE3 | CMD_RW_BOTH | CMD_COUNTER0); outb(PIT_A, (uint8_t)divisor); outb(PIT_A, (uint8_t)(divisor >> 8)); } -uint64_t timerMillis = 0; +uint32_t timerMillis = 0; void timerHandler() { timerMillis++; @@ -59,7 +65,6 @@ } void setupTimer() { - printf("setting timer frequency to 1kHz\n"); - setTimerFreq(1000); + setTimerFrequency(1000); setIRQHandler(0, &timerHandler); } diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c new file mode 100644 index 0000000..ea36871 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -0,0 +1,291 @@ +#include <_stdio.h> +#include +#include +#include +#include +#include +#include + +#define IDE_DATA_REGISTER 0 +#define IDE_ERROR_REGISTER 1 +#define IDE_SECTOR_COUNT_REGISTER 2 +#define IDE_SECTOR_NUMBER_REGISTER 3 +#define IDE_CYLINDER_LOW_REGISTER 4 +#define IDE_CYLINDER_HIGH_REGISTER 5 +// sector size, drive, head +#define IDE_SDH_REGISTER 6 +#define IDE_STATUS_REGISTER 7 +#define IDE_COMMAND_REGISTER 7 +#define IDE_ALTERNATE_STATUS_CONTROL_REGISTER 0 +#define IDE_DRIVE_ADDRESS_CONTROL_REGISTER 1 + +#define IDE_STATUS_BUSY 0x80 +#define IDE_STATUS_READY 0x40 +#define IDE_STATUS_WRITE_FAULT 0x20 +#define IDE_STATUS_SEEK_COMPLETE 0x10 +#define IDE_STATUS_DATA_REQUEST 0x08 +#define IDE_STATUS_CORRECTED_DATA 0x04 +#define IDE_STATUS_INDEX 0x02 +#define IDE_STATUS_ERROR 0x01 + +#define IDE_IDENTIFY_COMMAND 0xEC + +char *driveTypes[] = { + "ISA Compatibility mode-only controller", + "PCI native mode-only controller", + "ISA Compatibility mode controller", + "PCI native mode controller", +}; + +void setupIDEChannels(IdeChannels *channels, PciDevice *pciDevice) { + if (pciDevice->programmingInterface & 0x01) { + channels->base = pciDevice->bar0; + channels->control = pciDevice->bar1; + } else { + channels->base = 0x1F0; + channels->control = 0x3F6; + } + if (pciDevice->programmingInterface & 0x04) { + channels[1].base = pciDevice->bar2; + channels[1].control = pciDevice->bar3; + } else { + channels[1].base = 0x170; + channels[1].control = 0x376; + } +} + +void ideWriteControlRegister(IdeChannels *channel, uint8_t reg, uint8_t data) { + outb(channel->control + reg, data); +} + +void ideWriteRegister(IdeChannels *channel, uint8_t reg, uint16_t data) { + outb(channel->base + reg, data); + if (data > 0xFF) { + // set higher half bit in the control register + outb(channel->control, 0x0A); + outb(channel->base + reg, data >> 8); + outb(channel->control, 0x02); + } +} + +uint8_t ideReadControlRegister(IdeChannels *channel, uint8_t reg) { + return inb(channel->control + reg); +} + +uint8_t ideReadRegister(IdeChannels *channel, uint16_t reg) { + return inw(channel->base + reg); +} + +void ideReadBuffer(IdeChannels *channel, uint32_t *data) { + for (uint16_t i = 0; i < 128; i++) { + data[i] = ini(channel->base + IDE_DATA_REGISTER); + } +} + +void printError(uint16_t); + +void ideWaitUntilNotBusy(IdeChannels *channel, bool checkErrors) { + for (uint8_t i = 0; i < 4; i++) { + ideReadControlRegister(channel, 0); + } + uint16_t status = ideReadRegister(channel, IDE_STATUS_REGISTER); + while (status & IDE_STATUS_BUSY) { + status = ideReadRegister(channel, IDE_STATUS_REGISTER); + } + if (checkErrors && status & IDE_STATUS_ERROR) { + printf("encountered an error\n"); + printError(ideReadRegister(channel, IDE_ERROR_REGISTER)); + } +} + +void ideCommand(IdeChannels *channel, uint8_t command) { + ideWaitUntilNotBusy(channel, false); + ideWriteRegister(channel, IDE_COMMAND_REGISTER, command); +} + +#define CHANNEL &channels[channel] + +void initializeIDEDrive(PciDevice *pciDevice, ListElement **drives) { + uint8_t *buffer = malloc(2048); + IdeChannels *channels = malloc(sizeof(IdeChannels) * 2); + setupIDEChannels(channels, pciDevice); + for (uint8_t channel = 0; channel < 2; channel++) { + if (ideReadRegister(CHANNEL, IDE_STATUS_REGISTER) == 0) { + // no device + continue; + } + ideWriteControlRegister(CHANNEL, IDE_ALTERNATE_STATUS_CONTROL_REGISTER, + 2); + for (uint8_t drive = 0; drive < 2; drive++) { + ideWaitUntilNotBusy(CHANNEL, true); + // set the drive + ideWriteRegister(CHANNEL, IDE_SDH_REGISTER, 0xA0 | (drive << 4)); + ideWriteRegister(CHANNEL, IDE_SECTOR_COUNT_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_SECTOR_NUMBER_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_LOW_REGISTER, 0); + ideWriteRegister(CHANNEL, IDE_CYLINDER_HIGH_REGISTER, 0); + ideCommand(CHANNEL, IDE_IDENTIFY_COMMAND); + ideWaitUntilNotBusy(CHANNEL, true); + ideReadBuffer(CHANNEL, (void *)buffer); + if (*((uint16_t *)buffer) == 0) { + // any bit has to be set if it is a real device + continue; + } + char *model = malloc(41); + for (int i = 0; i < 40; i += 2) { + *((uint16_t *)&model[i]) = buffer[54 + i + 1]; + *((uint16_t *)&model[i + 1]) = buffer[54 + i]; + } + model[40] = 0; + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->model = model; + hardDrive->channels = CHANNEL; + hardDrive->channel = channel; + hardDrive->drive = drive; + hardDrive->type = *(uint16_t *)buffer; + hardDrive->cylinders = *(uint16_t *)buffer + 2; + hardDrive->heads = *(uint16_t *)buffer + 6; + hardDrive->sectors = *(uint16_t *)buffer + 12; + hardDrive->capabilities = *(uint16_t *)buffer + 98; + hardDrive->commandSets = *(uint32_t *)(buffer + 164); + if (hardDrive->commandSets + (1 << 26)) { + hardDrive->size = *(uint32_t *)buffer + 200; + } else { + hardDrive->size = *(uint32_t *)buffer + 120; + } + listAdd(drives, hardDrive); + printf("found a hard drive %i bytes, %i:%i, model: %s\n", + hardDrive->size, channel, drive, model); + } + } + free(buffer); +} + +void printError(uint16_t status) { + if (status & 0x01) { + printf("No address mark\n"); + } + if (status & 0x02) { + printf("Track 0 not found\n"); + } + if (status & 0x04) { + printf("command aborted\n"); + } + if (status & 0x08) { + printf("Media change request\n"); + } + if (status & 0x10) { + printf("ID mark not found\n"); + } + if (status & 0x20) { + printf("Media changed\n"); + } + if (status & 0x40) { + printf("uncorrectable data\n"); + } + if (status & 0x80) { + printf("bad block\n"); + } +} + +void driveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, + uint8_t sectorCount, uint8_t direction) { + uint8_t accessMode = 0, head = 0, sector = 0, cylinder = 0; + uint32_t lbaIo[6] = {0, 0, 0, 0, 0, 0}; + if (lba >= 0x10000000) { + accessMode = 2; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x0000FF00) >> 8; + lbaIo[2] = (lba & 0x00FF0000) >> 16; + lbaIo[3] = (lba & 0xFF000000) >> 24; + } else if (hardDrive->capabilities & 0x200) { + accessMode = 1; + lbaIo[0] = (uint8_t)lba; + lbaIo[1] = (lba & 0x000FF00) >> 8; + lbaIo[2] = (lba & 0x0FF0000) >> 16; + head = (lba & 0xF000000) >> 24; + } else { + sector = (lba % 63) + 1; + cylinder = (lba + 1 - sector) / (16 * 63); + lbaIo[0] = sector; + lbaIo[1] = (uint8_t)cylinder; + lbaIo[2] = (cylinder >> 8) & 0xFF; + head = (lba + 1 - sector) % (16 * 63) / (63); + } + ideWaitUntilNotBusy(hardDrive->channels, true); + if (accessMode == 0) { + // chs + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xA0 | (hardDrive->drive << 4)); + } else { + // lba + ideWriteRegister(hardDrive->channels, IDE_SDH_REGISTER, + 0xE0 | (hardDrive->drive << 4) | head); + } + ideWriteRegister(hardDrive->channels, IDE_SECTOR_COUNT_REGISTER, + sectorCount); + ideWriteRegister(hardDrive->channels, IDE_SECTOR_NUMBER_REGISTER, + lbaIo[3] << 8 | lbaIo[0]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_LOW_REGISTER, + lbaIo[4] << 8 | lbaIo[1]); + ideWriteRegister(hardDrive->channels, IDE_CYLINDER_HIGH_REGISTER, + lbaIo[5] << 8 | lbaIo[2]); + uint8_t command = 0; + if (direction == 0) { + // read + if (accessMode == 2) { + command = 0x24; + } else { + command = 0x20; + } + } else { + // write + if (accessMode == 2) { + command = 0x34; + } else { + command = 0x30; + } + } + ideCommand(hardDrive->channels, command); + ideWaitUntilNotBusy(hardDrive->channels, true); + if (direction == 0) { + uint16_t status; + void *current = buffer; + for (uint8_t i = 0; i < sectorCount; i++) { + ideWaitUntilNotBusy(hardDrive->channels, true); + ideReadBuffer(hardDrive->channels, (void *)buffer); + } + } +} + +void initializeSATADrive(PciDevice *pciDevice) { + // todo +} + +void scanHardDrives() { + ListElement *drives = NULL; + for (ListElement *current = *getPciDevices(); current; + current = current->next) { + PciDevice *pciDevice = current->data; + if (pciDevice->class != 1) { + continue; + } + switch (pciDevice->subclass) { + case 1: + initializeIDEDrive(pciDevice, &drives); + break; + case 6: + printf("found a SATA-controller: %i:%i:%i\n", pciDevice->bus, + pciDevice->device, pciDevice->function); + initializeSATADrive(pciDevice); + break; + } + } + void *buffer = malloc(2000); + for (ListElement *current = drives; current; current = current->next) { + driveAccess(current->data, 0, buffer, 1, 0); + printf("data: %x %x %s\n", *(uint32_t *)buffer, + *((uint32_t *)buffer + 1), buffer); + } + free(buffer); +} diff --git a/src/kernel/drivers/pci/pci.c b/src/kernel/drivers/pci/pci.c index 9874077..96cbfc3 100644 --- a/src/kernel/drivers/pci/pci.c +++ b/src/kernel/drivers/pci/pci.c @@ -35,6 +35,8 @@ ListElement *pciDevices = NULL; +ListElement **getPciDevices() { return &pciDevices; } + uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset) { uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | @@ -46,6 +48,16 @@ return result; } +void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data) { + uint32_t address = ((bus << 16) | (device << 11) | (function << 8) | + (offset & 0xFC) | 0x80000000); + asm("cli"); + outi(0xCF8, address); + outb(0xCFC, data); + asm("sti"); +} + uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) { return (uint16_t)pciConfigReadByte(bus, device, function, offset) | @@ -53,6 +65,13 @@ << 8); } +uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset) { + return (uint32_t)pciConfigReadWord(bus, device, function, offset) | + ((uint32_t)pciConfigReadWord(bus, device, function, offset + 2) + << 16); +} + uint8_t getHeaderType(uint8_t bus, uint8_t device, uint8_t function) { return pciConfigReadByte(bus, device, function, 0x0E); } @@ -74,6 +93,14 @@ pciDevice->subclass = subclass; pciDevice->vendorId = pciConfigReadWord(bus, device, function, 0x00); pciDevice->deviceId = pciConfigReadWord(bus, device, function, 0x02); + pciDevice->programmingInterface = + pciConfigReadByte(bus, device, function, 0x09); + pciDevice->bar0 = pciConfigReadInt(bus, device, function, 0x10); + pciDevice->bar1 = pciConfigReadInt(bus, device, function, 0x14); + pciDevice->bar2 = pciConfigReadInt(bus, device, function, 0x18); + pciDevice->bar3 = pciConfigReadInt(bus, device, function, 0x1C); + pciDevice->bar4 = pciConfigReadInt(bus, device, function, 0x20); + pciDevice->bar5 = pciConfigReadInt(bus, device, function, 0x24); listAdd(&pciDevices, pciDevice); if (class == 6 && subclass == 4) { checkBus(pciConfigReadByte(bus, device, function, 0x19)); @@ -87,7 +114,7 @@ } if (getHeaderType(bus, device, 0) & 0x80) { // multifunction device - for (uint16_t function = 0; function < 256; function++) { + for (uint16_t function = 0; function < 8; function++) { if (getVendorID(bus, device, function) != 0xFFFF) { checkFunction(bus, device, function); } @@ -102,7 +129,7 @@ return; } checkedBuses[bus] = true; - for (uint16_t device = 0; device < 256; device++) { + for (uint16_t device = 0; device < 32; device++) { checkDevice(bus, device); } } diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 15713cc..7375f67 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -17,18 +18,16 @@ 0x1000000); // initializing stacks after the kernel seems not to work :( // otherwise, _kernel_end should be passed here initOSTasks(); + getCurrentTask()->timerTicks = 1000; + getCurrentTask()->ticksLeft = 1000; drawLogo(); + yields(); setupDevices(); setupInterrupts(); printCPUData(); scanPCIDevices(); - yields(); - getCurrentTask()->timerTicks = 1000; - getCurrentTask()->ticksLeft = 1000; + scanHardDrives(); while (1) { - if (isTaskQueueEmpty()) { - asm volatile("hlt"); - } for (Message *message = popBeginning(&(getCurrentTask()->messages)); message; message = popBeginning(&getCurrentTask()->messages)) { switch (message->type) { @@ -44,6 +43,6 @@ } free(message); } - yields(); + yield(); } } diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c index b968b61..868b8b6 100644 --- a/src/kernel/memory/alloc.c +++ b/src/kernel/memory/alloc.c @@ -37,6 +37,7 @@ current->next->state = FREE; current->next->next = next; next->last = current->next; + next = current->next; } else { current->next = next; } diff --git a/src/kernel/task/osTasks.c b/src/kernel/task/osTasks.c index 37ab866..7b0d6c9 100644 --- a/src/kernel/task/osTasks.c +++ b/src/kernel/task/osTasks.c @@ -26,13 +26,7 @@ void initOSTasks() { setRunningTask(&mainTask); - mainTask.ticksLeft = -1; - mainTask.timerTicks = -1; - keyboardConsumer = &mainTask; createTask(&printerTask, (uint32_t)printLoop, 0x0, 0x0); - schedule(&printerTask); - // more tasks . . . - yields(); } inline Task *getPrinterTask() { return &printerTask; } diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c index e001f9f..30d4d9f 100644 --- a/src/kernel/task/task.c +++ b/src/kernel/task/task.c @@ -11,7 +11,7 @@ void createTask(Task *task, uint32_t mainFunction, uint32_t flags, uint32_t *pagedir) { - listAddSet(&allTasks, task); + listAdd(&allTasks, task); void *stack = mallocTask(STACK_SIZE, task); task->registers.eax = 0; task->registers.ebx = 0; @@ -32,9 +32,12 @@ void yield() { Task *last = currentTask; currentTask = popBeginning(&scheduledTasks); - if (currentTask == NULL) { - while (1) - ; + while (currentTask == 0) { + asm("sti"); + asm("hlt"); + currentTask = popBeginning(&scheduledTasks); + } + if (last == currentTask) { return; } switchTask(&(last->registers), &(currentTask->registers)); @@ -52,12 +55,11 @@ inline Task *getCurrentTask() { return currentTask; } -inline void schedule(Task *task) { listAddSet(&scheduledTasks, task); } +inline void schedule(Task *task) { listAdd(&scheduledTasks, task); } inline void setRunningTask(Task *task) { currentTask = task; listAddSet(&allTasks, task); } -inline bool isTaskQueueEmpty() { return scheduledTasks == NULL; } inline ListElement *getAllTasks() { return allTasks; } diff --git a/src/kernel/util/list.c b/src/kernel/util/list.c index 2c29877..e5ee306 100644 --- a/src/kernel/util/list.c +++ b/src/kernel/util/list.c @@ -6,13 +6,13 @@ if (element == NULL) { *list = malloc(sizeof(ListElement)); element = *list; - element->next = NULL; } else { for (; element->next; element = element->next) { } element->next = malloc(sizeof(ListElement)); element = element->next; } + element->next = NULL; element->data = data; } @@ -21,7 +21,6 @@ if (element == NULL) { *list = malloc(sizeof(ListElement)); element = *list; - element->next = NULL; } else { for (; element->next; element = element->next) { if (element->data == data) { @@ -30,14 +29,14 @@ } element->next = malloc(sizeof(ListElement)); element = element->next; - element->next = NULL; } + element->next = NULL; element->data = data; } uint32_t listCount(ListElement *list) { int count = 0; - for (ListElement *current = list; current->next; current = current->next) { + for (ListElement *current = list; current; current = current->next) { count++; } return count; diff --git a/src/kernel/util/ports.c b/src/kernel/util/ports.c index e5bbae8..6e01a56 100644 --- a/src/kernel/util/ports.c +++ b/src/kernel/util/ports.c @@ -11,6 +11,16 @@ return result; } +void outw(uint16_t port, uint16_t val) { + asm volatile("outw %0, %1" : : "a"(val), "Nd"(port)); +} + +uint16_t inw(uint16_t port) { + uint16_t result; + __asm__("in %%dx, %%al" : "=a"(result) : "d"(port)); + return result; +} + void outi(uint16_t port, uint32_t val) { asm volatile("outl %0, %1" : : "a"(val), "Nd"(port)); }