Skip to content

Commit

Permalink
- ATA?
Browse files Browse the repository at this point in the history
  • Loading branch information
fgsoftware1 committed Oct 2, 2024
1 parent 456353d commit b28301d
Show file tree
Hide file tree
Showing 8 changed files with 257 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*.a
*.bin
*.iso
*.img
*.elf
/.dccache
/.ninja_deps
Expand Down
5 changes: 3 additions & 2 deletions build.ninja
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@ build ./build/i386/cmos.o: gcc ./src/arch/i386/kernel/drivers/cmos.c
build ./build/i386/keyboard.o: gcc ./src/arch/i386/kernel/drivers/keyboard.c
build ./build/i386/fpu.o: gcc ./src/arch/i386/kernel/drivers/fpu.c
build ./build/i386/pit.o: gcc ./src/arch/i386/kernel/drivers/pit.c
build ./build/i386/ata.o: gcc ./src/arch/i386/kernel/drivers/ata.c
build ./build/i386/console.o: gcc ./src/arch/i386/kernel/console.c
build ./build/i386/acpi.o: gcc ./src/arch/i386/kernel/acpi.c
build ./build/i386/madt.o: gcc ./src/arch/i386/kernel/madt.c
build ./build/i386/kernel.o: gcc ./src/arch/i386/kernel/kernel.c

build ./isodir/boot/piriquitOS-i386.bin: ld ./build/i386/acpi.o ./build/i386/madt.o ./build/libc/string.o ./build/i386/boot.o ./build/i386/gdt.asm.o ./build/i386/gdt.c.o ./build/i386/idt.c.o ./build/i386/idt.asm.o ./build/i386/irq.o ./build/i386/exceptions.o ./build/i386/isr.o ./build/i386/io.o ./build/i386/vga.o ./build/i386/pic.o ./build/i386/cmos.o ./build/i386/keyboard.o ./build/i386/pit.o ./build/i386/console.o ./build/i386/fpu.o ./build/i386/kernel.o
build ./isodir/boot/piriquitOS-i386.bin: ld ./build/i386/ata.o ./build/i386/acpi.o ./build/i386/madt.o ./build/libc/string.o ./build/i386/boot.o ./build/i386/gdt.asm.o ./build/i386/gdt.c.o ./build/i386/idt.c.o ./build/i386/idt.asm.o ./build/i386/irq.o ./build/i386/exceptions.o ./build/i386/isr.o ./build/i386/io.o ./build/i386/vga.o ./build/i386/pic.o ./build/i386/cmos.o ./build/i386/keyboard.o ./build/i386/pit.o ./build/i386/console.o ./build/i386/fpu.o ./build/i386/kernel.o
build ./build/piriquitOS-i386.iso: iso ./isodir

#phony
build libc: phony ./build/libc/string.o ./libs/libc.a
build i386: phony ./libs/libc.a ./build/i386/acpi.o ./build/i386/madt.o ./build/i386/boot.o ./build/i386/gdt.asm.o ./build/i386/idt.asm.o ./build/i386/irq.o ./build/i386/exceptions.o ./build/i386/isr.o ./build/i386/io.o ./build/i386/vga.o ./build/i386/pic.o ./build/i386/cmos.o ./build/i386/keyboard.o ./build/i386/console.o ./build/i386/fpu.o ./build/i386/pit.o ./build/i386/kernel.o ./isodir/boot/piriquitOS-i386.bin ./build/piriquitOS-i386.iso
build i386: phony ./libs/libc.a ./build/i386/ata.o ./build/i386/acpi.o ./build/i386/madt.o ./build/i386/boot.o ./build/i386/gdt.asm.o ./build/i386/idt.asm.o ./build/i386/irq.o ./build/i386/exceptions.o ./build/i386/isr.o ./build/i386/io.o ./build/i386/vga.o ./build/i386/pic.o ./build/i386/cmos.o ./build/i386/keyboard.o ./build/i386/console.o ./build/i386/fpu.o ./build/i386/pit.o ./build/i386/kernel.o ./isodir/boot/piriquitOS-i386.bin ./build/piriquitOS-i386.iso

default help
3 changes: 3 additions & 0 deletions src/arch/i386/kernel/acpi.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "include/acpi.h"
#include "libc/include/string.h"
#include "libc/include/stdio.h"
#include "include/isr.h"

static acpi_rsdp_t *rsdp = NULL;
static acpi_xsdt_t *xsdt = NULL;
Expand All @@ -14,6 +15,8 @@ static bool validate_table(acpi_sdt_header_t *table_header) {
}

bool acpi_init(void) {
//TODO: ACPI IRQ/ISR

// Search for the RSDP
for (u8 *addr = (u8 *)0x000E0000; addr < (u8 *)0x00100000; addr += 16) {
if (memcmp(addr, "RSD PTR ", 8) == 0) {
Expand Down
182 changes: 182 additions & 0 deletions src/arch/i386/kernel/drivers/ata.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#include "../include/drivers/ata.h"
#include "../include/io.h"
#include "../include/drivers/pic.h"
#include "../include/console.h"

void ata_wait_bsy() {
while (inportb(ATA_PRIMARY_IO + ATA_REG_STATUS) & 0x80);
}

void ata_wait_drq() {
while (!(inportb(ATA_PRIMARY_IO + ATA_REG_STATUS) & 0x08));
}

bool ata_read_sector(u8 *buffer, u32 lba) {
ata_wait_bsy();

outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xE0 | ((lba >> 24) & 0x0F));
outportb(ATA_PRIMARY_IO + ATA_REG_FEATURES, 0);
outportb(ATA_PRIMARY_IO + ATA_REG_SECCOUNT0, 1);
outportb(ATA_PRIMARY_IO + ATA_REG_LBA0, (u8)lba);
outportb(ATA_PRIMARY_IO + ATA_REG_LBA1, (u8)(lba >> 8));
outportb(ATA_PRIMARY_IO + ATA_REG_LBA2, (u8)(lba >> 16));
outportb(ATA_PRIMARY_IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO);

ata_wait_bsy();
ata_wait_drq();

for (int i = 0; i < 256; i++) {
u16 data = *(u16*)(ATA_PRIMARY_IO + ATA_REG_DATA);
buffer[i*2] = (u8)data;
buffer[i*2+1] = (u8)(data >> 8);
}

ata_wait_bsy();

return true;
}

bool ata_write_sector(u8 *buffer, u32 lba) {
ata_wait_bsy();

outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xE0 | ((lba >> 24) & 0x0F));
outportb(ATA_PRIMARY_IO + ATA_REG_FEATURES, 0);
outportb(ATA_PRIMARY_IO + ATA_REG_SECCOUNT0, 1);
outportb(ATA_PRIMARY_IO + ATA_REG_LBA0, (u8)lba);
outportb(ATA_PRIMARY_IO + ATA_REG_LBA1, (u8)(lba >> 8));
outportb(ATA_PRIMARY_IO + ATA_REG_LBA2, (u8)(lba >> 16));
outportb(ATA_PRIMARY_IO + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);

ata_wait_bsy();
ata_wait_drq();

for (int i = 0; i < 256; i++) {
u16 data = buffer[i*2] | (buffer[i*2+1] << 8);
*(u16*)(ATA_PRIMARY_IO + ATA_REG_DATA) = data;
io_wait();
}

ata_wait_bsy();

return true;
}

void ata_read_identify(u16 io_port, ata_device_t* device) {
u16 identify_data[256];
for (int i = 0; i < 256; i++) {
identify_data[i] = *(u16*)(io_port + ATA_REG_DATA);
}

device->present = true;
device->signature = identify_data[0];
device->capabilities = identify_data[49];
device->command_sets = identify_data[82] | ((u32)identify_data[83] << 16);
device->size = identify_data[60] | ((u32)identify_data[61] << 16);

for (int i = 0; i < 20; i++) {
u16 data = identify_data[27 + i];
device->model[i*2] = (data >> 8) & 0xFF;
device->model[i*2 + 1] = data & 0xFF;
}
device->model[40] = '\0';

for (int i = 39; i >= 0 && device->model[i] == ' '; i--) {
device->model[i] = '\0';
}
}

int ata_software_reset(u16 io_base) {
outportb(io_base + ATA_REG_COMMAND, 4);
io_wait();
outportb(io_base + ATA_REG_COMMAND, 0);
io_wait();

for (int i = 0; i < 1000; i++) {
if ((inportb(io_base + ATA_REG_STATUS) & 0x80) == 0) {
return 0;
}
io_wait();
}

return -1;
}

void ata_probe_devices() {
outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xA0);
io_wait();
if (ata_software_reset(ATA_PRIMARY_IO) == 0) {
ata_read_identify(ATA_PRIMARY_IO, &ata_primary_master);
}

outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xB0);
io_wait();
if (ata_software_reset(ATA_PRIMARY_IO) == 0) {
ata_read_identify(ATA_PRIMARY_IO, &ata_primary_slave);
}

outportb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xA0);
io_wait();
if (ata_software_reset(ATA_SECONDARY_IO) == 0) {
ata_read_identify(ATA_SECONDARY_IO, &ata_secondary_master);
}

outportb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xB0);
io_wait();
if (ata_software_reset(ATA_SECONDARY_IO) == 0) {
ata_read_identify(ATA_SECONDARY_IO, &ata_secondary_slave);
}
}

ata_status_t ata_read_status(u16 io_base) {
u8 status = inportb(io_base + ATA_REG_STATUS);
return (ata_status_t) {
.busy = (status & 0x80) != 0,
.data_ready = (status & 0x08) != 0,
.error = (status & 0x01) != 0
};
}

void ata_interrupt_handler(registers_t *regs) {
ata_status_t primary_status = ata_read_status(ATA_PRIMARY_IO);
ata_status_t secondary_status = ata_read_status(ATA_SECONDARY_IO);

if (!primary_status.busy) {
ata_primary_status = primary_status;
if (primary_status.error) {
u8 error = inportb(ATA_PRIMARY_IO + ATA_REG_ERROR);
} else if (primary_status.data_ready) {
}
}

if (!secondary_status.busy) {
ata_secondary_status = secondary_status;
if (secondary_status.error) {
u8 error = inportb(ATA_SECONDARY_IO + ATA_REG_ERROR);
} else if (secondary_status.data_ready) {
}
}

inportb(ATA_PRIMARY_IO + ATA_REG_STATUS);
inportb(ATA_SECONDARY_IO + ATA_REG_STATUS);
}

bool ata_init() {
printf("Initializing ATA...\n");
isr_register_interrupt_handler(IRQ_ATA1, ata_interrupt_handler);
isr_register_interrupt_handler(IRQ_ATA2, ata_interrupt_handler);

ata_primary_status = (ata_status_t){0};
ata_secondary_status = (ata_status_t){0};

ata_probe_devices();

ata_software_reset(ATA_PRIMARY_IO);
ata_software_reset(ATA_SECONDARY_IO);

ata_probe_devices();

unmask(IRQ_ATA1 - IRQ_BASE);
unmask(IRQ_ATA2 - IRQ_BASE);

return true;
}
59 changes: 59 additions & 0 deletions src/arch/i386/kernel/include/drivers/ata.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#ifndef ATA_H
#define ATA_H

#include "../libc/include/types.h"
#include "../isr.h"

#define ATA_PRIMARY_IO 0x1F0
#define ATA_SECONDARY_IO 0x170

#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_CONTROL 0x0C

#define ATA_CMD_READ_PIO 0x20
#define ATA_CMD_WRITE_PIO 0x30

typedef struct {
bool present;
bool is_atapi;
u16 signature;
u16 capabilities;
u32 command_sets;
u32 size;
char model[41];
} ata_device_t;

typedef struct {
bool busy;
bool data_ready;
bool error;
} ata_status_t;

static ata_device_t ata_primary_master;
static ata_device_t ata_primary_slave;
static ata_device_t ata_secondary_master;
static ata_device_t ata_secondary_slave;
static ata_status_t ata_primary_status;
static ata_status_t ata_secondary_status;

void ata_wait_bsy();
void ata_wait_drq();
bool ata_read_sector(u8 *buf, u32 sector);
bool ata_write_sector(u8 *buf, u32 sector);
void ata_read_identify(u16 io_port, ata_device_t* device);
int ata_software_reset(u16 io_base);
void ata_probe_devices();
ata_status_t ata_read_status(u16 io_base);
void ata_interrupt_handler(registers_t *regs);
bool ata_init();

#endif // !ATA_H
2 changes: 2 additions & 0 deletions src/arch/i386/kernel/include/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ void outportb(u16 port, u8 data);
void outportw(u16 port, u16 data);
void outportl(u16 port, u32 data);

void io_wait();

#endif
4 changes: 4 additions & 0 deletions src/arch/i386/kernel/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ u32 inportl(u16 port) {
void outportl(u16 port, u32 data) {
asmv("outl %%eax, %%dx" : : "dN"(port), "a"(data));
}

void io_wait(){
outportb(0x80, 0);
}
4 changes: 3 additions & 1 deletion src/arch/i386/kernel/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
#include "include/console.h"
#include "include/drivers/vga.h"
#include "include/gdt.h"
#include "include/madt.h"
#include "include/drivers/pic.h"
#include "include/drivers/keyboard.h"
#include "include/drivers/cmos.h"
#include "include/drivers/fpu.h"
#include "include/drivers/pit.h"
#include "include/madt.h"
#include "include/drivers/ata.h"

void cpuid(u32 type, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
{
Expand Down Expand Up @@ -76,6 +77,7 @@ void kmain()
init_pit();
init_keyboard();
init_cmos();
ata_init();

while (1)
{
Expand Down

0 comments on commit b28301d

Please sign in to comment.