]> code.bitgloo.com Git - clyne/osdev.git/commitdiff
ata/atapi draft
authorClyne Sullivan <clyne@bitgloo.com>
Sat, 28 Sep 2024 21:04:59 +0000 (17:04 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Sat, 28 Sep 2024 21:04:59 +0000 (17:04 -0400)
Makefile
ata.cpp [new file with mode: 0644]
ata.hpp [new file with mode: 0644]
kernel.cpp

index 048094329657c74b73d624b535c71c97a8a9a45a..cb089919eb0c7023fc8fce7d525f81b5cc1e5a87 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,7 @@ CXXFLAGS := -m32 -ggdb -g3 -O0 -fno-pic -fno-rtti -fno-exceptions -std=c++23
 LDFLAGS := $(CXXFLAGS) -T link.ld -static -nostdlib -fno-use-cxa-atexit
 
 CXXFILES := acpi.cpp \
+        ata.cpp \
         boot.cpp \
         gdt.cpp \
         idt.cpp \
@@ -38,5 +39,5 @@ clean:
 
 run: myos.iso
        @echo "  QEMU"
-       @qemu-system-i386 -cdrom $< -monitor stdio -no-reboot #-s -S #-d int
+       @qemu-system-i386 -drive file=$<,index=2,media=cdrom -monitor stdio -no-reboot #-s -S #-d int
 
diff --git a/ata.cpp b/ata.cpp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ata.hpp b/ata.hpp
new file mode 100644 (file)
index 0000000..5394c31
--- /dev/null
+++ b/ata.hpp
@@ -0,0 +1,131 @@
+#ifndef ATA_HPP
+#define ATA_HPP
+
+#include "portio.hpp"
+
+#include <cstdint>
+#include <utility>
+
+namespace ATA
+{
+    enum class Type {
+        None,
+        ATA,
+        ATAPI
+    };
+
+    enum class Base : std::uint16_t {
+        Primary = 0x01F0,
+        Secondary = 0x0170
+    };
+
+    enum class Drive : std::uint8_t {
+        Master = 0xA0,
+        Slave = 0xB0
+    };
+
+    enum class Command : std::uint8_t {
+        Identify = 0xEC,
+        IdentifyPacketDevice = 0xA1
+    };
+
+    namespace Status {
+        static constexpr std::uint8_t Busy  = 0x80;
+        static constexpr std::uint8_t Ready = 0x40;
+        static constexpr std::uint8_t DF    = 0x20;
+        static constexpr std::uint8_t DSC   = 0x10;
+        static constexpr std::uint8_t DRQ   = 0x08;
+        static constexpr std::uint8_t CORR  = 0x04;
+        static constexpr std::uint8_t Index = 0x02;
+        static constexpr std::uint8_t Error = 0x01;
+    }
+
+    static constexpr std::uint8_t ATAPIIdentify0 = 0x14;
+    static constexpr std::uint8_t ATAPIIdentify1 = 0xEB;
+
+    using enum Base;
+    using enum Drive;
+
+    template<Base PBase>
+    struct Bus
+    {
+        template<Base b, unsigned offs>
+        using BPort = Port<std::to_underlying(b) + offs>;
+
+        [[no_unique_address]] BPort<PBase, 0> data;
+        [[no_unique_address]] BPort<PBase, 1> errFeats;
+        [[no_unique_address]] BPort<PBase, 2> count;
+        [[no_unique_address]] BPort<PBase, 3> lba0;
+        [[no_unique_address]] BPort<PBase, 4> lba1;
+        [[no_unique_address]] BPort<PBase, 5> lba2;
+        [[no_unique_address]] BPort<PBase, 6> select;
+        [[no_unique_address]] BPort<PBase, 7> cmdStat;
+
+        Type identify(Drive drv) {
+            auto type = Type::None;
+
+            data = std::to_underlying(drv);
+            count = '\0';
+            lba0 = '\0';
+            lba1 = '\0';
+            lba2 = '\0';
+            cmdStat = std::to_underlying(Command::Identify);
+    
+            if (cmdStat == '\0')
+                return type;
+
+            type = Type::ATA;
+            while (cmdStat & Status::Busy);
+
+            std::uint8_t stat;
+            do {
+                stat = cmdStat;
+
+                if (stat & Status::Error) {
+                    if (lba1 == ATAPIIdentify0 && lba2 == ATAPIIdentify1) {
+                        type = identifyAtapi(drv);
+                        break;
+                    } else {
+                        return type;
+                    }
+                }
+            } while (!(stat & Status::DRQ));
+
+            if (type != Type::None) {
+                for (int i = 0; i < 256; ++i) {
+                    volatile std::uint16_t w = data;
+                    (void)w;
+                }
+            }
+
+            return type;
+        }
+
+        Type identifyAtapi(Drive drv) {
+            data = std::to_underlying(drv);
+            count = '\0';
+            lba0 = '\0';
+            lba1 = '\0';
+            lba2 = '\0';
+            cmdStat = std::to_underlying(Command::IdentifyPacketDevice);
+    
+            if (cmdStat == '\0')
+                return Type::None;
+
+            while (cmdStat & Status::Busy);
+
+            std::uint8_t stat;
+            do {
+                stat = cmdStat;
+
+                if (stat & Status::Error)
+                    return Type::None;
+            } while (!(stat & Status::DRQ));
+
+            return Type::ATAPI;
+        }
+    };
+} // ATA
+
+#endif // ATA_HPP
+
index 408a19ed20846db2b1c5217aa781e550263f5b22..cbeab58658275146f6dd88f8d5b3a9f477ef23bc 100644 (file)
@@ -1,4 +1,5 @@
 #include "acpi.hpp"
+#include "ata.hpp"
 #include "gdt.hpp"
 #include "idt.hpp"
 #include "keyboard.hpp"
@@ -15,6 +16,24 @@ TextOutput& term = vga;
 
 static volatile bool termBusy = false;
 
+void ata_probe(auto bus, ATA::Drive drv, const char *name)
+{
+    switch (bus.identify(drv)) {
+    case ATA::Type::ATA:
+        term.write("ata:");
+        term.write(name);
+        term.write(": ATA drive detected.\n");
+        break;
+    case ATA::Type::ATAPI:
+        term.write("ata:");
+        term.write(name);
+        term.write(": ATAPI drive detected.\n");
+        break;
+    default:
+        break;
+    }
+}
+
 void kernel_main(void) 
 {
     term.write("Clyne's kernel, v2024\n\n");
@@ -40,6 +59,14 @@ void kernel_main(void)
     tasking_initialize();
     term.write("Tasking enabled.\n");
 
+    ATA::Bus<ATA::Primary> bus0;
+    ATA::Bus<ATA::Secondary> bus1;
+
+    ata_probe(bus0, ATA::Master, "0:0");
+    ata_probe(bus0, ATA::Slave,  "0:1");
+    ata_probe(bus1, ATA::Master, "1:0");
+    ata_probe(bus1, ATA::Slave,  "1:1");
+
     for (;;) {
         const auto ch = keyboard_read();
         if (ch)