oxytoxin

unix-like kernel
git clone git://git.evenfri.xyz/oxytoxin.git
Log | Files | Refs | README | LICENSE

commit 112af79a793ae23ec9e2b4ed1f72b0173ede4bf3
parent e39888461ddc472ef26c1e88957b569bc4030417
Author: evenfri <evenfri256@gmail.com>
Date:   Sun,  6 Sep 2026 00:17:24 +0800

add ata driver

Diffstat:
Aata/ata.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Aata/ata.h | 18++++++++++++++++++
Aata/ata_entry.asm | 8++++++++
Aata/mkfile | 15+++++++++++++++
Adisk.img | 2++
Mfns.h | 16+++++-----------
Midt.c | 2+-
Minit.c | 12++++++++++++
Aio.asm | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dkeyboard/built-in.a | 0
Mmkfile | 5+++--
Moxytoxin.h | 1+
Mqemu.sh | 2++
13 files changed, 173 insertions(+), 14 deletions(-)

diff --git a/ata/ata.c b/ata/ata.c @@ -0,0 +1,52 @@ +#include "oxytoxin.h" + +extern void ata_entry(void); + +static void ata_io_wait(void) { + inb(0x1f7); + inb(0x1f7); + inb(0x1f7); + inb(0x1f7); +} + +static int ata_wait_drq(void) { + while (1) { + uint8_t status = inb(0x1f7); + if (status & ata_drive_err) return -1; + if (!(status & ata_drive_busy) && (status & ata_drive_req_ready)) return 0; + } +} + +void ata_read_sectors(void *trg, unsigned int lba, unsigned char size) { + outb(0x1f6, 0xe0 | ((lba >> 24) & 0x0f)); + outb(0x1f2, size); + outb(0x1f3, (unsigned char) lba); + outb(0x1f4, (unsigned char) (lba >> 8)); + outb(0x1f5, (unsigned char) (lba >> 16)); + outb(0x3f6, 0x02); + outb(0x1f7, ata_cmd_read); + + ata_io_wait(); + + uint16_t *target = (uint16_t *) trg; + int count = (size == 0) ? 256 : size; + + for (int i = 0; i < count; i++) { + if (ata_wait_drq() != 0) return; /* read error */ + + for (int j = 0; j < 256; j++) { + target[j] = inw(0x1f0); + } + target += 256; + } +} + +void ata_handler(void) { + inb(0x1f7); /* reset IRQ */ + outb(0x20, 0x20); /* EOI для master pic1 */ + outb(0xa0, 0x20); /* EOI для slave pic2 */ +} + +void ata_init(void) { + idt_register(0x2e, ata_entry); +} diff --git a/ata/ata.h b/ata/ata.h @@ -0,0 +1,18 @@ +#ifndef ata_h +#define ata_h + +#define ata_base 1 +#define ata_master 0xa0 +#define ata_slave 0xb0 +#define ata_drive_busy 0x80 +#define ata_drive_ready 0x40 +#define ata_drive_req_ready 0x08 +#define ata_drive_write_fault 0x20 +#define ata_drive_err 0x01 +#define ata_cmd_read 0x20 + +void ata_init(void); +void ata_read_sectors(void *trg, unsigned int lba, unsigned char size); + +#endif /* ata_h */ + diff --git a/ata/ata_entry.asm b/ata/ata_entry.asm @@ -0,0 +1,8 @@ +global ata_entry +extern ata_handler + +ata_entry: + pusha + call ata_handler + popa + iret diff --git a/ata/mkfile b/ata/mkfile @@ -0,0 +1,15 @@ +<$kernel/build/mkhdr + +as = ../build/as +cc = ../build/cc +ar = ../build/ar + +ofiles = ata_entry.$o \ + ata.$o + +hfiles = ata.h + +lib = built-in.a + +<$kernel/build/mklib +<$kernel/build/mkcommon diff --git a/disk.img b/disk.img @@ -0,0 +1 @@ +hello disk and ata driver +\ No newline at end of file diff --git a/fns.h b/fns.h @@ -4,19 +4,13 @@ #include "oxytoxin.h" /* input/output ports */ -static inline void io_wait() { - asm volatile ("outb %%al, $0x80" : : "a"(0)); -} +extern void outb(uint16_t port, uint8_t val); +extern void outw(uint16_t port, uint16_t val); -static inline void outb(uint16_t port, uint8_t val) { - asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); -} +extern uint8_t inb(uint16_t port); +extern uint16_t inw(uint16_t port); -static inline uint8_t inb(uint16_t port) { - uint8_t ret; - asm volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port)); - return ret; -} +extern void io_wait(void); /* vga */ static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) { diff --git a/idt.c b/idt.c @@ -20,7 +20,7 @@ void pic_remap() { outb(pic_1_data, 0x01); io_wait(); outb(pic_2_data, 0x01); io_wait(); - outb(pic_1_data, 0xfd); io_wait(); + outb(pic_1_data, 0b11111101); io_wait(); outb(pic_2_data, 0xff); io_wait(); } diff --git a/init.c b/init.c @@ -23,9 +23,21 @@ void start_kernel(uint32_t magic, multiboot_info_t *mbi) { idt_init(); pit_init(1000); keyboard_init(); + ata_init(); asm volatile ("sti"); + uint8_t ata_buf[512] = {}; + ata_read_sectors(ata_buf, 0, 1); + + for (int i = 0; i < 512; i++) { + char c = ata_buf[i]; + if ((c > 32 && c < 127) || + c == ' ') { + tty_write(&c, 1); + } + } + while (1) { char c; size_t bytes; diff --git a/io.asm b/io.asm @@ -0,0 +1,54 @@ +global outb +global outw +global inb +global inw +global io_wait + +section .text + +outb: + push ebp + mov ebp, esp + ; [ebp+8] = port (16-bit) + ; [ebp+12] = byte (8-bit) + mov dx, WORD [ebp+8] + mov al, BYTE [ebp+12] + out dx, al + pop ebp + ret + +outw: + push ebp + mov ebp, esp + mov dx, WORD [ebp+8] + mov ax, WORD [ebp+12] + out dx, ax + pop ebp + ret + +inb: + push ebp + mov ebp, esp + mov dx, WORD [ebp+8] + xor eax, eax + in al, dx + pop ebp + ret + +inw: + push ebp + mov ebp, esp + mov dx, WORD [ebp+8] + xor eax, eax + in ax, dx + pop ebp + ret + +io_wait: + push ebp + mov ebp, esp + mov dx, 0x80 + xor al, al + out dx, al + pop ebp + ret diff --git a/keyboard/built-in.a b/keyboard/built-in.a Binary files differ. diff --git a/mkfile b/mkfile @@ -7,10 +7,11 @@ cc = ./build/cc ld = ./build/ld ar = ./build/ar -ldflags = keyboard/built-in.a -dirs = keyboard +ldflags = keyboard/built-in.a ata/built-in.a +dirs = keyboard ata ofiles = boot.$o \ + io.$o \ vga.$o \ tty.$o \ gdt.$o \ diff --git a/oxytoxin.h b/oxytoxin.h @@ -9,5 +9,6 @@ #include "fns.h" #include "keyboard/keyboard.h" +#include "ata/ata.h" #endif /* oxytoxin_h */ diff --git a/qemu.sh b/qemu.sh @@ -2,8 +2,10 @@ set -e kernel_bin="./o.oxytoxin" +disk="./disk.img" mem="16M" exec qemu-system-i386 \ -m "$mem" \ -kernel "$kernel_bin" \ + -hda "$disk"