aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2024-09-28 17:04:59 -0400
committerClyne Sullivan <clyne@bitgloo.com>2024-09-28 17:04:59 -0400
commitc7066d295039b833dd026e200a5aa735631bdf34 (patch)
tree33a6926f639b6063666c51014768fd600fc27a1a
parentb9d2cef90451fae9ab7e10f5f11b8840e9bfe67d (diff)
ata/atapi draft
-rw-r--r--Makefile3
-rw-r--r--ata.cpp0
-rw-r--r--ata.hpp131
-rw-r--r--kernel.cpp27
4 files changed, 160 insertions, 1 deletions
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
--- /dev/null
+++ b/ata.cpp
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 <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
+
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<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)