From 0f84acde302a1f01e52a9d504a188b14ed4819a2 Mon Sep 17 00:00:00 2001 From: slinky55 Date: Sat, 20 Jun 2026 21:02:59 -0500 Subject: [PATCH] more ata stuff --- compile_commands.json | 25 +----- kernel/drivers/atapi/ata.c | 42 +++++++++ kernel/drivers/atapi/ata.h | 73 ++++++++++----- kernel/drivers/atapi/ata_stubs.S | 147 ++++++++++++++++++++++++++++++- kernel/kmain.c | 6 +- 5 files changed, 248 insertions(+), 45 deletions(-) diff --git a/compile_commands.json b/compile_commands.json index 41a18a7..e19f5ec 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -9,28 +9,11 @@ "-Wextra", "-Ikernel", "-o", - "obj/kernel/kmain.o", - "kernel/kmain.c" + "obj/kernel/drivers/atapi/ata.o", + "kernel/drivers/atapi/ata.c" ], "directory": "/home/slinky/source/RockOS", - "file": "/home/slinky/source/RockOS/kernel/kmain.c", - "output": "/home/slinky/source/RockOS/obj/kernel/kmain.o" - }, - { - "arguments": [ - "/home/slinky/opt/cross/bin/i686-elf-gcc", - "-c", - "-ffreestanding", - "-O2", - "-Wall", - "-Wextra", - "-Ikernel", - "-o", - "obj/kernel/common_stubs.o", - "kernel/common_stubs.S" - ], - "directory": "/home/slinky/source/RockOS", - "file": "/home/slinky/source/RockOS/kernel/common_stubs.S", - "output": "/home/slinky/source/RockOS/obj/kernel/common_stubs.o" + "file": "/home/slinky/source/RockOS/kernel/drivers/atapi/ata.c", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/atapi/ata.o" } ] diff --git a/kernel/drivers/atapi/ata.c b/kernel/drivers/atapi/ata.c index e69de29..c72f802 100644 --- a/kernel/drivers/atapi/ata.c +++ b/kernel/drivers/atapi/ata.c @@ -0,0 +1,42 @@ +#include "drivers/atapi/ata.h" + +#include "lib/print.h" + +#include + +uint8_t selected_drive_primary = 0; +uint8_t selected_drive_secondary = 0; + +uint8_t primary_master_info_buffer[512]; +uint8_t primary_slave_info_buffer[512]; +uint8_t secondary_master_info_buffer[512]; +uint8_t secondary_slave_info_buffer[512]; + +ide_device_t ide_devices[4]; + +void fix_ata_string(char* buf, size_t sz) { + if ((sz % 2) != 0) return; + for (size_t i = 0; i < sz; i += 2) { + char tmp = buf[i]; + buf[i] = buf[i + 1]; + buf[i + 1] = tmp; + } + buf[sz-1] = '\0'; +} + +void scan_drives() { + uint8_t type = ident_device(IDE_SECONDARY_IO_BASE, IDE_DRIVE_MASTER, secondary_master_info_buffer); + if (type == 2) { + ide_devices[0].bus = IDE_SECONDARY_IO_BASE; + ide_devices[0].device = IDE_DRIVE_MASTER; + ide_devices->type = type; + + atapi_identify_data_t* ident_result = (atapi_identify_data_t*)secondary_master_info_buffer; + ide_devices->ident_info_struct = (void*)ident_result; + + kprintf("Detected ATAPI master device on secondary bus\n"); + + fix_ata_string(ident_result->model_num, 40); + kprintf("Model Number: %s\n", ident_result->model_num); + } +} \ No newline at end of file diff --git a/kernel/drivers/atapi/ata.h b/kernel/drivers/atapi/ata.h index abaa7c6..0170f10 100644 --- a/kernel/drivers/atapi/ata.h +++ b/kernel/drivers/atapi/ata.h @@ -1,27 +1,32 @@ #ifndef KATA_H #define KATA_H +#ifndef __ASSEMBLER__ #include +#endif -#define IDE_PRIMARY_IO_BASE 0x1F0 -#define IDE_PRIMARY_CRTL_BASE 0x3F6 +#define IDE_PRIMARY_IO_BASE 0x01F0 +#define IDE_PRIMARY_CRTL_BASE 0x03F6 -#define IDE_SECONDARY_IO_BASE 0x170 -#define IDE_SECONDARY_CRTL_BASE 0x376 +#define IDE_SECONDARY_IO_BASE 0x0170 +#define IDE_SECONDARY_CRTL_BASE 0x0376 -#define IO_DATA_REG 0x00 -#define IO_ERROR_REG 0x01 -#define IO_FEATURE_REG 0x01 -#define IO_SECTOR_COUNT_REG 0x02 -#define IO_SECTOR_NUM_REG 0x03 -#define IO_LBA_LO_REG 0x03 -#define IO_CYL_LO_REG 0x04 -#define IO_LBA_MID_REG 0x04 -#define IO_LBA_HI_REG 0x05 -#define IO_CYL_HI_REG 0x05 -#define IO_DRIVE_SELECT_REG 0x06 -#define IO_STATUS_REG 0x07 -#define IO_CMD_REG 0x07 +#define IDE_DRIVE_MASTER 0xA0 +#define IDE_DRIVE_SLAVE 0xB0 + +#define IO_DATA_REG 0x0000 +#define IO_ERROR_REG 0x0001 +#define IO_FEATURE_REG 0x0001 +#define IO_SECTOR_COUNT_REG 0x0002 +#define IO_SECTOR_NUM_REG 0x0003 +#define IO_LBA_LO_REG 0x0003 +#define IO_CYL_LO_REG 0x0004 +#define IO_LBA_MID_REG 0x0004 +#define IO_LBA_HI_REG 0x0005 +#define IO_CYL_HI_REG 0x0005 +#define IO_DRIVE_SELECT_REG 0x0006 +#define IO_STATUS_REG 0x0007 +#define IO_CMD_REG 0x0007 #define CTRL_ALT_STATUS_REG 0x00 #define CTRL_DEV_CTRL_REG 0x00 @@ -53,8 +58,36 @@ #define DEV_CTRL_REG_SRST 0b00000010 #define DEV_CTRL_REG_HOB 0b10000000 -#define DRIVE_ADDR_REG_DS0 0b00000001 -#define DRIVE_ADDR_REG_DS1 0b00000010 -#define DRIVE_ADDR_REG 0b00111100 +#define DRIVE_ADDR_REG_DS0 0b00000001 +#define DRIVE_ADDR_REG_DS1 0b00000010 +#define DRIVE_ADDR_REG_HEAD 0b00111100 +#define DRIVE_ADDR_REG_WTG 0b01000000 + +#define ATAPI_CMD_IDENTIFY_PACKET 0xA1 + +#ifndef __ASSEMBLER__ +uint8_t ident_device(uint16_t bus, uint8_t drive_select, uint8_t* buffer); + +typedef struct __attribute__((packed)) { + uint16_t bus; + uint8_t device; + uint8_t type; + void* ident_info_struct; +} ide_device_t; + +typedef struct __attribute__((packed)) { + uint16_t gen_config; + uint16_t reserved_1[9]; + char serial_number[20]; + uint16_t vendor_1[3]; + char firmware_v[8]; + char model_num[40]; + uint16_t vendor_2[2]; + uint16_t capabilities; + uint16_t reserved_2; + uint16_t pio_dma_timing; +} atapi_identify_data_t; + +#endif #endif \ No newline at end of file diff --git a/kernel/drivers/atapi/ata_stubs.S b/kernel/drivers/atapi/ata_stubs.S index fab91c8..56de6d2 100644 --- a/kernel/drivers/atapi/ata_stubs.S +++ b/kernel/drivers/atapi/ata_stubs.S @@ -2,6 +2,149 @@ .code32 -.global ident_drives -ident_drives: +.extern selected_drive_primary +.extern selected_drive_secondary + +.global ident_device +ident_device: + push %ebp + mov %esp, %ebp + + push %ebx + push %ecx + push %edx + push $0 + + mov 8(%ebp), %ebx # ebx = bus base address + mov 12(%ebp), %ecx # ecx = drive select mask + + # drive select + mov %ebx, %edx + add $IO_DRIVE_SELECT_REG, %edx + mov %cl, %al + outb %al, (%dx) + + xor %eax, %eax + # clear sector count and LBA + mov %ebx, %edx + add $IO_SECTOR_COUNT_REG, %edx + outb %al, (%dx) + + mov %ebx, %edx + add $IO_LBA_LO_REG, %edx + outb %al, (%dx) + + mov %ebx, %edx + add $IO_LBA_MID_REG, %edx + outb %al, (%dx) + + mov %ebx, %edx + add $IO_LBA_HI_REG, %edx + outb %al, (%dx) + + # send ident + mov %ebx, %edx + add $IO_CMD_REG, %edx + mov $0xEC, %al + outb %al, (%dx) + + mov %ebx, %edx + add $IO_STATUS_REG, %edx + inb (%dx), %al + inb (%dx), %al + inb (%dx), %al + inb (%dx), %al + + cmp $0xFF, %al + je not_found + test %al, %al + jz not_found + +poll_status: + inb (%dx), %al + test $STATUS_REG_BSY, %al + jnz poll_status + +check_ata: + mov %ebx, %edx + add $IO_LBA_MID_REG, %edx + inb (%dx), %al + test %al, %al + jnz check_atapi + + mov %ebx, %edx + add $IO_LBA_HI_REG, %edx + inb (%dx), %al + test %al, %al + jnz check_atapi + + mov $0x01, (%esp) + jmp poll_drq + +check_atapi: + # check if atapi device + mov %ebx, %edx + add $IO_LBA_MID_REG, %edx + inb (%dx), %al + cmp $0x14, %al + jne not_found + + mov %ebx, %edx + add $IO_LBA_HI_REG, %edx + inb (%dx), %al + cmp $0xEB, %al + jne not_found +is_atapi: + mov $0x02, (%esp) + mov %ebx, %edx + add $IO_CMD_REG, %edx + mov $(ATAPI_CMD_IDENTIFY_PACKET), %al + outb %al, (%dx) + + mov %ebx, %edx + add $IO_STATUS_REG, %edx + inb (%dx), %al + inb (%dx), %al + inb (%dx), %al + inb (%dx), %al +1: + inb (%dx), %al + test $STATUS_REG_BSY, %al + jnz 1b + + +poll_drq: + mov %ebx, %edx + add $IO_STATUS_REG, %edx + inb (%dx), %al + + test $STATUS_REG_ERR, %al + jnz error + + test $STATUS_REG_DRQ, %al + jz poll_drq + +drq_set: + mov %ebx, %edx + add $IO_DATA_REG, %edx + + mov 16(%ebp), %edi + mov $256, %ecx +read_data: + inw (%dx), %ax + mov %ax, (%edi) + add $2, %edi + loop read_data + + jmp done + +not_found: +error: + mov $0x0, (%esp) +done: + pop %eax + pop %edx + pop %ecx + pop %ebx + leave ret \ No newline at end of file diff --git a/kernel/kmain.c b/kernel/kmain.c index 07fa931..aca1f3d 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -137,12 +137,14 @@ void kmain(uint32_t magic, multiboot_info* mbi) { // kprintf("PS2 init failed\n"); // return; // } - // kprintf("PS2 initialized\n"); + // kprintf("PS2 initialized\n"); init_page_tables(); kprintf("Page tables initialized\n"); - load_origin_program(mbi); + kprintf("scanning for drives\n"); + extern void scan_drives(); + scan_drives(); while(1); }