diff --git a/.cache/clangd/index/kmain.c.9B04FE5F8A3537CE.idx b/.cache/clangd/index/kmain.c.9B04FE5F8A3537CE.idx index d0e39c9..b59c42c 100644 Binary files a/.cache/clangd/index/kmain.c.9B04FE5F8A3537CE.idx and b/.cache/clangd/index/kmain.c.9B04FE5F8A3537CE.idx differ diff --git a/Makefile b/Makefile index ae19953..5622e1a 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,6 @@ KERNELIMG := $(BUILDDIR)/kernel.bin QEMUFLAGS = -d int -s \ -kernel $(KERNELIMG) \ - -machine q35 \ -device piix3-ide,id=ide -drive id=disk,file=image.img,format=raw,if=none -device ide-hd,drive=disk,bus=ide.0 \ .PHONY: all kernel qemu clean docs diff --git a/bochsrc b/bochsrc index 24e096b..d318a04 100644 --- a/bochsrc +++ b/bochsrc @@ -1,3 +1,6 @@ +ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata0-master: type=disk, path="image.img" + ata0-slave: type=cdrom, path=./build/andewOS.iso, status=inserted magic_break: enabled=1 boot: cdrom diff --git a/ide.c b/ide.c new file mode 100644 index 0000000..789598c --- /dev/null +++ b/ide.c @@ -0,0 +1,109 @@ +#include +#include +#include + +uint16_t ide_select_drive(uint8_t bus, uint8_t drive) { + if (bus == ATA_PRIMARY) { + if (drive == ATA_MASTER) + outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xA0); + else + outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xB0); + + return ATA_PRIMARY_IO; + } else { + if (drive == ATA_MASTER) + outportb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xA0); + else + outportb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xB0); + + return ATA_SECONDARY_IO; + } +} + +uint8_t ide_identify(uint8_t bus, uint8_t drive, uint16_t *ide_buf) { + asm volatile ("cli" ::); + + uint16_t io = ide_select_drive(bus, drive); + // Must zero these registers before sending IDENTIFY command + outportb(io + ATA_REG_SECCOUNT0, 0); + outportb(io + ATA_REG_LBA0, 0); + outportb(io + ATA_REG_LBA1, 0); + outportb(io + ATA_REG_LBA2, 0); + + for (int i = 0; i < 14; i++) + inportb(io + ATA_REG_STATUS); + uint8_t status = inportb(io + ATA_REG_STATUS); + + // Send IDENTIFY command + outportb(io + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + + status = inportb(io + ATA_REG_STATUS); + // Make sure there are no errors + if (!status) { + printf("Drive does not exist\n"); + asm volatile ("sti" ::); + return 0; + } + + // Poll the drive until it's not busy + while (inportb(io + ATA_REG_STATUS) & ATA_SR_BSY) + asm volatile ("pause" ::); + + if (inportb(io + ATA_REG_LBA1) || inportb(io + ATA_REG_LBA1)) { + printf("Drive is not ATA. wtf?"); + asm volatile ("sti" ::); + return 0; + } + + // Poll until drive is ready for data requests or until an error occurs + status = inportb(io + ATA_REG_STATUS); + while (!(status & ATA_SR_DRQ) && !(status & ATA_SR_ERR)) { + status = inportb(io + ATA_REG_STATUS); + } + + if (status & ATA_SR_ERR) { + printf("DRIVE ERROR\n"); + asm volatile ("sti" ::); + return 0; + } + + printf("%s %s is online. Status: %X\n", bus==ATA_PRIMARY?"Primary":"Secondary", drive==ATA_PRIMARY?"master":"slave", status); + // Read identification space of the device + for (int i = 0; i < 256; i++) { + *(ide_buf + i*2) = inportw(io + ATA_REG_DATA); + } + + asm volatile ("sti" ::); + return 0; +} + +uint8_t ata_read_sector(uint8_t bus, uint8_t drive, uint32_t lba, uint8_t *buf) { + asm volatile ("cli" ::); + uint16_t io = 0; + if (bus == ATA_PRIMARY) { + io = ATA_PRIMARY_IO; + } else { + io = ATA_SECONDARY_IO; + } + + uint8_t cmd = (drive==ATA_MASTER?0xE0:0xF0); + outportb(io + ATA_REG_HDDEVSEL, cmd | (uint8_t)(lba >> 24 & 0x0f)); + outportb(io + 1, 0x00); + outportb(io + ATA_REG_SECCOUNT0, 1); + outportb(io + ATA_REG_LBA0, (uint8_t)((lba))); + outportb(io + ATA_REG_LBA1, (uint8_t)((lba) >> 8)); + outportb(io + ATA_REG_LBA2, (uint8_t)((lba) >> 16)); + outportb(io + ATA_REG_COMMAND, ATA_CMD_READ_PIO); + + + uint8_t status = inportb(io + ATA_REG_STATUS); + while (!(status & ATA_SR_DRQ) && !(status & ATA_SR_ERR)) { + status = inportb(io + ATA_REG_STATUS); + } + + for (int i = 0; i < 256; i++) + *(uint16_t *)(buf + i*2) = inportw(io + ATA_REG_DATA); + + asm volatile ("sti" ::); + return 1; +} diff --git a/image.img b/image.img index 45b983b..0172adc 100644 --- a/image.img +++ b/image.img @@ -1 +1 @@ -hi +SKIBIDI ANDEW PINGAS BALLS ANDEW diff --git a/include/ide.h b/include/ide.h index 603c746..a9f0cad 100644 --- a/include/ide.h +++ b/include/ide.h @@ -1,6 +1,8 @@ #ifndef RK_IDE_H_ #define RK_IDE_H_ +#include + enum IDE_MODE { ISA_ONLY = 0x00, PCI_ONLY = 0x05, @@ -12,6 +14,75 @@ enum IDE_MODE { PCI_CAN_SWITCH_BUS_MASTERING = 0x8f, }; +#define ATA_PRIMARY 0 +#define ATA_SECONDARY 1 +#define ATA_MASTER 0 +#define ATA_SLAVE 1 +#define ATA_PRIMARY_IO 0x1F0 +#define ATA_SECONDARY_IO 0x170 + +#define ATA_PRIMARY_DCR_AS 0x3F6 +#define ATA_SECONDARY_DCR_AS 0x376 + +#define ATA_PRIMARY_IRQ 14 +#define ATA_SECONDARY_IRQ 15 + +#define ATA_REG_DATA 0x00 +#define ATA_REG_ERROR 0x01 +#define ATA_REG_FEATURES 0x01 +#define ATA_REG_SECCOUNT0 0x02 +#define ATA_REG_LBA0 0x03 +#define ATA_REG_LBA1 0x04 +#define ATA_REG_LBA2 0x05 +#define ATA_REG_HDDEVSEL 0x06 +#define ATA_REG_COMMAND 0x07 +#define ATA_REG_STATUS 0x07 +#define ATA_REG_SECCOUNT1 0x08 +#define ATA_REG_LBA3 0x09 +#define ATA_REG_LBA4 0x0A +#define ATA_REG_LBA5 0x0B +#define ATA_REG_CONTROL 0x0C +#define ATA_REG_ALTSTATUS 0x0C +#define ATA_REG_DEVADDRESS 0x0D + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +#define ATA_SR_BSY 0x80 // Busy +#define ATA_SR_DRDY 0x40 // Drive ready +#define ATA_SR_DF 0x20 // Drive write fault +#define ATA_SR_DSC 0x10 // Drive seek complete +#define ATA_SR_DRQ 0x08 // Data request ready +#define ATA_SR_CORR 0x04 // Corrected data +#define ATA_SR_IDX 0x02 // Index +#define ATA_SR_ERR 0x01 // Error + +#define ATA_IDENT_DEVICETYPE 0 +#define ATA_IDENT_CYLINDERS 2 +#define ATA_IDENT_HEADS 6 +#define ATA_IDENT_SECTORS 12 +#define ATA_IDENT_SERIAL 20 +#define ATA_IDENT_MODEL 54 +#define ATA_IDENT_CAPABILITIES 98 +#define ATA_IDENT_FIELDVALID 106 +#define ATA_IDENT_MAX_LBA 120 +#define ATA_IDENT_COMMANDSETS 164 +#define ATA_IDENT_MAX_LBA_EXT 200 + +uint16_t ide_select_drive(uint8_t bus, uint8_t drive); +uint8_t ide_identify(uint8_t bus, uint8_t drive, uint16_t *ide_buf); +uint8_t ata_read_sector(uint8_t bus, uint8_t drive, uint32_t lba, uint8_t *buf); #endif diff --git a/include/io.h b/include/io.h index 27ac7f2..ea0e883 100644 --- a/include/io.h +++ b/include/io.h @@ -6,4 +6,6 @@ uint8_t inportb(uint16_t port); void outportb(uint16_t port, uint8_t byte); +uint16_t inportw(uint16_t port); + #endif diff --git a/io.c b/io.c index e3dc4ad..207ee25 100644 --- a/io.c +++ b/io.c @@ -15,3 +15,13 @@ void outportb(uint16_t port, uint8_t byte) { : // no output : "a" (byte), "d" (port)); } + +uint16_t inportw(uint16_t port) { + uint16_t result; + + asm volatile ("in %%dx, %%ax" + : "=a" (result) + : "d" (port)); + + return result; +} diff --git a/kmain.c b/kmain.c index 2b0a890..0340b55 100644 --- a/kmain.c +++ b/kmain.c @@ -1,3 +1,4 @@ +#include "ide.h" #include #include #include @@ -42,7 +43,6 @@ void kmain(struct multiboot_info *info) { asm volatile ("lidt %0" :: "m"(g_idtr)); - struct rsdp *found_rsdp = acpi_locate_rsdp(); if (!found_rsdp) { set_color(VGA_COLOR_RED); @@ -89,9 +89,11 @@ void kmain(struct multiboot_info *info) { if (fadt->Flags & 1) printf("Legacy devices are supported\n"); else { + /* set_color(VGA_COLOR_RED); printf("Legacy devices are not supported. I'm too lazy to support modern devices, bye bye.\n"); goto halt; + */ } pic_remap(PIC_1_START, PIC_2_START); // ACPI version 1.0 is so old that we assume that our PC supports the 8042 ps/2 controller @@ -108,11 +110,16 @@ void kmain(struct multiboot_info *info) { printf("Looks like you are using PCIe- Found MCFG at 0x%x\n", mcfg); struct pci_config_space *ide = pcie_find_device(mcfg, MASS_STORAGE_CONTROLLER, IDE_INTERFACE); - if (ide) printf("IDE controller detected. Program Interface: %X\n", ide->program_interface); + if (ide) { + printf("IDE controller detected. Program Interface: %X\n", ide->program_interface); + + uint16_t ide_buf[256] = {0}; + ide_identify(ATA_PRIMARY, ATA_MASTER, ide_buf); + } } set_color(VGA_COLOR_WHITE); - printf("You are now being dropped into a kernel shell\n$ "); + printf("\nYou are now being dropped into a kernel shell\n$ "); halt: for (;;) {} } diff --git a/multiboot.asm b/multiboot.asm index 9eb1e4f..0d9d1a3 100644 --- a/multiboot.asm +++ b/multiboot.asm @@ -1,5 +1,5 @@ %define MAGIC 0x1BADB002 -%define FLAGS 0 +%define FLAGS 0b100 ; Multiboot v1 Specification ; https://www.gnu.org/software/grub/manual/multiboot/multiboot.html @@ -9,6 +9,17 @@ dd MAGIC dd FLAGS dd -(MAGIC + FLAGS) +dd 0 +dd 0 +dd 0 +dd 0 +dd 0 + +dd 1 +dd 80 +dd 25 +dd 0 + section .text global _start _start: diff --git a/ps2.c b/ps2.c index ed62678..2f0b990 100644 --- a/ps2.c +++ b/ps2.c @@ -4,6 +4,7 @@ #include #include #include +#include #define cpu_relax asm volatile ("pause" ::); @@ -171,6 +172,12 @@ void ps2_handler() { printf("andew pingas detected"); } else if (strcmp(shell_buffer, "HELLO") == 0) { printf("hi"); + } else if (strcmp(shell_buffer, "READ") == 0) { + uint8_t sector[512] = {0}; + ata_read_sector(ATA_PRIMARY, ATA_MASTER, 0, sector); + for (int i = 0; i < 512; i++) { + _putchar(sector[i]); + } } else { printf("unknown command '%s' idiot", shell_buffer); }