From c7066d295039b833dd026e200a5aa735631bdf34 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sat, 28 Sep 2024 17:04:59 -0400 Subject: [PATCH] ata/atapi draft --- Makefile | 3 +- ata.cpp | 0 ata.hpp | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel.cpp | 27 +++++++++++ 4 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 ata.cpp create mode 100644 ata.hpp diff --git a/Makefile b/Makefile index 0480943..cb08991 100644 --- 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 index 0000000..e69de29 diff --git a/ata.hpp b/ata.hpp new file mode 100644 index 0000000..5394c31 --- /dev/null +++ b/ata.hpp @@ -0,0 +1,131 @@ +#ifndef ATA_HPP +#define ATA_HPP + +#include "portio.hpp" + +#include +#include + +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 + struct Bus + { + template + using BPort = Port; + + [[no_unique_address]] BPort data; + [[no_unique_address]] BPort errFeats; + [[no_unique_address]] BPort count; + [[no_unique_address]] BPort lba0; + [[no_unique_address]] BPort lba1; + [[no_unique_address]] BPort lba2; + [[no_unique_address]] BPort select; + [[no_unique_address]] BPort 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 + diff --git a/kernel.cpp b/kernel.cpp index 408a19e..cbeab58 100644 --- a/kernel.cpp +++ b/kernel.cpp @@ -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 bus0; + ATA::Bus 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)