diff --git a/emul b/emul index 5becde2..ff8f063 100755 --- a/emul +++ b/emul @@ -58,7 +58,7 @@ function main() { make all || exit 1 util/build_iso.sh || exit 1 echo > serial.log - emulator="qemu-system-x86_64 -cdrom mittos64.iso -serial file:serial.log -smp 4 ${EMULPARAM[@]}" + emulator="qemu-system-x86_64 -hda image.img -cdrom mittos64.iso -boot order=d -serial file:serial.log -smp 4 ${EMULPARAM[@]}" debugger=$(which x86_64-elf-linux-gdb) if [[ (-n ${EMULVNC}) ]]; then diff --git a/init/init.c b/init/init.c index 5c64b58..7bc1a3c 100644 --- a/init/init.c +++ b/init/init.c @@ -8,29 +8,6 @@ int main(int argc, char **argv) (void) argv; - int fd[2]; - pipe(fd); - - pid_t childpid = fork(); - - if(childpid) - { - printf("I am parent!\n"); - close(fd[1]); - write(fd[0], "Hi, pipe!\n", 10); - close(fd[0]); - } - else - { - printf("I am child!\n"); - close(fd[0]); - char buffer[255]; - read(fd[1], buffer, 255); - printf("Received string: %s\n", buffer); - close(fd[1]); - } - - for(;;); return 0; } diff --git a/kernel/boot/kmain.c b/kernel/boot/kmain.c index d636122..29cabad 100644 --- a/kernel/boot/kmain.c +++ b/kernel/boot/kmain.c @@ -12,6 +12,7 @@ #include #include #include +#include int kernel_execve(process_t *p, void *image, char *argv[], char *envp[]); int kmain(uint64_t multiboot_magic, void *multiboot_data) @@ -30,10 +31,11 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data) debug_info("Syscall enabled:%d\n", CPUID_FEATURE_SYSCALL); - fs_mount(0, "/"); fs_mount(&debug_file, "/dev/debug"); + ata_init(); + fs_write(&debug_file, "TESTING DEBUG FILE", 18, 0); process_t *p1 = process_spawn(0); diff --git a/kernel/drivers/ata.c b/kernel/drivers/ata.c new file mode 100644 index 0000000..b6606d2 --- /dev/null +++ b/kernel/drivers/ata.c @@ -0,0 +1,155 @@ +#include +#include +#include + +ata_drive drives[4] = { + {.bus=ATA_PRIMARY, .ms=ATA_MASTER}, + {.bus=ATA_PRIMARY, .ms=ATA_SLAVE}, + {.bus=ATA_SECONDARY, .ms=ATA_MASTER}, + {.bus=ATA_SECONDARY, .ms=ATA_SLAVE} +}; + + +int ata_wait_status(int bus) +{ + inb(ATA_STATUS(bus)); + inb(ATA_STATUS(bus)); + inb(ATA_STATUS(bus)); + inb(ATA_STATUS(bus)); + return inb(ATA_STATUS(bus)); +} + +int ata_send_command(ata_cmd_t *cmd, int wait) +{ + (void)wait; + outb(ATA_DEVICE(cmd->bus), cmd->device | (cmd->lba_sep[3] & 0xF)); + ata_wait_status(cmd->bus); + + outb(ATA_COUNT(cmd->bus), cmd->count); + outb(ATA_LBAL(cmd->bus), cmd->lba_sep[0]); + outb(ATA_LBAM(cmd->bus), cmd->lba_sep[1]); + outb(ATA_LBAH(cmd->bus), cmd->lba_sep[2]); + while(inb(ATA_STATUS(cmd->bus)) & ATA_BSY); + outb(ATA_COMMAND(cmd->bus), cmd->command); + + if(!inb(ATA_STATUS(cmd->bus))) + return 0; + + cmd->status = ata_wait_status(cmd->bus); + while((cmd->status = inb(ATA_STATUS(cmd->bus))) & ATA_BSY); + if(cmd->wait_status) while(!(cmd->status = inb(ATA_STATUS(cmd->bus)) & (cmd->wait_status | ATA_ERR))); + cmd->error = inb(ATA_ERROR(cmd->bus)); + cmd->count = inb(ATA_COUNT(cmd->bus)); + cmd->device = inb(ATA_DEVICE(cmd->bus)); + cmd->lba_sep[0] = inb(ATA_LBAL(cmd->bus)); + cmd->lba_sep[1] = inb(ATA_LBAM(cmd->bus)); + cmd->lba_sep[2] = inb(ATA_LBAH(cmd->bus)); + cmd->lba_sep[3] = 0; + + return cmd->status; +} + +void init_drive(ata_drive *drive) +{ + int bus = drive->bus; + // Check if the controller exists + // by writing a value to it and check + // that the same one is returned + int v1 = inb(ATA_LBAL(bus)); + outb(ATA_LBAL(bus), (~v1)&0xFF); + int v2 = inb(ATA_LBAL(bus)); + if(v2 != ((~v1)&0xFF)) + return; + + // Check if the drive exists + // by selecting the drive + outb(ATA_DEVICE(bus), 0xA0 | drive->ms); + if(!(ata_wait_status(bus) & ATA_RDY)) + return; + + outb(ATA_CONTROL(bus), ATA_SRST); + outb(ATA_CONTROL(bus), 0); + uint64_t lba = inb(ATA_LBAH(bus))<<16 | inb(ATA_LBAM(bus)) << 8 | inb(ATA_LBAL(bus)); + + ata_cmd_t command = { + .bus = bus, + .device=0xA0 | drive->ms, + .command = ATA_CMD_IDENTIFY, + .wait_status = ATA_DRQ, + }; + if(lba == ATAPI_LBA_MAGIC) + { + drive->atapi = 1; + command.command = ATA_CMD_IDENTIFY_PACKET; + } + if(!ata_send_command(&command, 1)) + return; + + // Read IDENTIFY information + uint16_t *buf = (void *)&drive->id; + for(int i=0; i<256; i++) + { + buf[i] = inw(ATA_DATA(drive->bus)); + } + + drive->exists = 1; + +} + +int ata_read_block(ata_drive *drive, uint64_t lba, void *buffer) +{ + int retries = 5; + while(retries) + { + ata_cmd_t command = { + .bus = drive->bus, + .count = 1, + .lba = lba & 0xFFFFFF, + .device = 0xE0 | drive->ms | ((lba >> 24) & 0xF), + .command = ATA_CMD_READ_SECTORS, + }; + + int status = ata_send_command(&command,0); + if(status & (ATA_DF | ATA_ERR) || !(status & ATA_DRQ)) + { + retries--; + continue; + } + + uint16_t *buf = buffer; + for(int i=0; i<256; i++) + { + buf[i] = inw(ATA_DATA(drive->bus)); + } + return 0; + } + debug_error("Reading disk failed\n"); + return -1; +} + +int ata_write_block(ata_drive *drive, uint64_t lba, void *buffer) +{ + ata_cmd_t command = { + .bus = drive->bus, + .count = 1, + .lba = lba & 0xFFFFFF, + .device = 0xE0 | drive->ms | ((lba >> 24) & 0xF), + .command = ATA_CMD_WRITE_SECTORS, + }; + ata_send_command(&command, 0); + uint16_t *buf = buffer; + for(int i=0; i<256; i++) + { + outw(ATA_DATA(drive->bus), buf[i]); + } + + return 0; +} + +void ata_init() +{ + init_drive(&drives[0]); + init_drive(&drives[1]); + init_drive(&drives[2]); + init_drive(&drives[3]); +} diff --git a/kernel/include/ata.h b/kernel/include/ata.h new file mode 100644 index 0000000..e7513d9 --- /dev/null +++ b/kernel/include/ata.h @@ -0,0 +1,101 @@ +#pragma once +#include + +#define ATA_PRIMARY 0x1F0 +#define ATA_SECONDARY 0x170 +#define ATA_MASTER 0x00 +#define ATA_SLAVE 0x10 + +// Input to controller +#define ATA_FEATURE(x) (x + 1) +#define ATA_COUNT(x) (x + 2) +#define ATA_LBAL(x) (x + 3) +#define ATA_LBAM(x) (x + 4) +#define ATA_LBAH(x) (x + 5) +#define ATA_DEVICE(x) (x + 6) +#define ATA_COMMAND(x) (x + 7) +#define ATA_CONTROL(x) (x + 0x206) + +// Output from controller +#define ATA_DATA(x) (x + 0) +#define ATA_ERROR(x) (x + 1) +// COUNT +// LBAL +// LBAM +// LBAH +// DEVICE +#define ATA_STATUS(x) (x + 7) + +#define ATA_ERR (1<<0) +#define ATA_DRQ (1<<3) +#define ATA_SRV (1<<4) +#define ATA_DF (1<<5) +#define ATA_RDY (1<<6) +#define ATA_BSY (1<<7) + +#define ATA_nIEN (1<<1) +#define ATA_SRST (1<<2) + +#define ATA_CMD_IDENTIFY 0xEC +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_READ_SECTORS 0x20 +#define ATA_CMD_WRITE_SECTORS 0x30 +#define ATA_CMD_PACKET 0xA0 + +#define ATAPI_LBA_MAGIC 0xEB1401 + +typedef struct ata_drive +{ + int exists; + int bus; + int ms; + int atapi; + struct { + uint16_t config; + uint16_t unused1[9]; + char serial[20]; + uint16_t unused2[3]; + char firmware[8]; + char model[40]; + uint8_t unused3; + uint8_t sectors_per_interrupt; + uint16_t unused4; + uint16_t capabilities[2]; + uint16_t unused5[2]; + uint16_t validity; + uint16_t unused6[3]; + uint32_t capacity_sectors; + uint16_t sectors_per_command; + uint32_t capacity_lba28; + uint16_t unused7[38]; + uint64_t capcity_lba48; + uint16_t unused8[152]; + }__attribute__((packed)) id; +} ata_drive; + +ata_drive drives[4]; + +typedef struct ata_cmd_st +{ + uint16_t bus; + union { + uint8_t feature; + uint8_t error; + }; + uint8_t count; + union { + uint64_t lba; + uint8_t lba_sep[4]; + }; + uint8_t device; + union { + uint8_t command; + uint8_t status; + }; + uint8_t wait_status; +} ata_cmd_t; + +int ata_read_block(struct ata_drive *drive, uint64_t lba, void *buffer); +int ata_write_block(struct ata_drive *drive, uint64_t lba, void *buffer); + +void ata_init();