commit 112af79a793ae23ec9e2b4ed1f72b0173ede4bf3
parent e39888461ddc472ef26c1e88957b569bc4030417
Author: evenfri <evenfri256@gmail.com>
Date: Sun, 6 Sep 2026 00:17:24 +0800
add ata driver
Diffstat:
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"