Sfoglia il codice sorgente

feat(ata): ata read sector by reading node 2,0

greatbridf 2 anni fa
parent
commit
1356bd2e63
4 ha cambiato i file con 115 aggiunte e 35 eliminazioni
  1. 6 1
      include/kernel/hw/ata.hpp
  2. 21 20
      include/kernel/hw/port.hpp
  3. 0 1
      include/kernel/vfs.h
  4. 88 13
      src/kernel/hw/ata.cpp

+ 6 - 1
include/kernel/hw/ata.hpp

@@ -1,8 +1,8 @@
 #pragma once
 
 #include <asm/port_io.h>
-#include <kernel/syscall.hpp>
 #include <kernel/hw/port.hpp>
+#include <kernel/syscall.hpp>
 #include <types/cplusplus.hpp>
 
 constexpr port_id_t ATA_PRIMARY_BUS_BASE = 0x1f0;
@@ -40,16 +40,21 @@ private:
     p8r stats;
     p8w comms;
 
+    uint8_t slave_flag;
+
 public:
     ata(port_id_t port_base);
 
     stat_t status(void) const;
 
     void identify(void) const;
+    int select(bool master);
 
     size_t read_data(char* buf, size_t n) const;
+    size_t write_data(const char* buf, size_t n) const;
 
     int read_sector(char* buf, uint32_t lba_low, uint16_t lba_high) const;
+    int write_sector(const char* buf, uint32_t lba_low, uint16_t lba_high) const;
 };
 
 void init_ata(void* data);

+ 21 - 20
include/kernel/hw/port.hpp

@@ -10,44 +10,41 @@ private:
     uint16_t mp;
 
 public:
-    port(uint16_t p)
+    explicit port(uint16_t p)
         : mp(p)
-    {}
+    {
+    }
 
     port_size_t operator*(void) const
     {
         static_assert(
-                types::is_same<port_size_t, uint8_t>::value ||
-                types::is_same<port_size_t, uint16_t>::value,
-                "this type is not implemented yet.");
+            types::is_same<port_size_t, uint8_t>::value || types::is_same<port_size_t, uint16_t>::value,
+            "this type is not implemented yet.");
         port_size_t ret;
         if constexpr (types::is_same<port_size_t, uint8_t>::value)
             asm("inb %1, %0"
                 : "=a"(ret)
-                : "d"(mp)
-                );
+                : "d"(mp));
         if constexpr (types::is_same<port_size_t, uint16_t>::value)
             asm("inw %1, %0"
                 : "=a"(ret)
-                : "d"(mp)
-                );
+                : "d"(mp));
         return ret;
     }
 
     port_size_t operator=(port_size_t n) const
     {
         static_assert(
-                types::is_same<port_size_t, uint8_t>::value ||
-                types::is_same<port_size_t, uint16_t>::value,
-                "this type is not implemented yet.");
+            types::is_same<port_size_t, uint8_t>::value || types::is_same<port_size_t, uint16_t>::value,
+            "this type is not implemented yet.");
         if constexpr (types::is_same<port_size_t, uint8_t>::value)
             asm("outb %1, %0"
-                : : "d"(mp), "a"(n)
-                );
+                :
+                : "d"(mp), "a"(n));
         if constexpr (types::is_same<port_size_t, uint16_t>::value)
             asm("outw %1, %0"
-                : : "d"(mp), "a"(n)
-                );
+                :
+                : "d"(mp), "a"(n));
         return n;
     }
 };
@@ -59,8 +56,12 @@ using p16 = port<uint16_t>;
 using p16r = port<uint16_t, true, false>;
 using p16w = port<uint16_t, false, true>;
 
-template <> uint8_t p8r::operator=(uint8_t n) const = delete;
-template <> uint8_t p8w::operator*(void) const = delete;
-template <> uint16_t p16r::operator=(uint16_t n) const = delete;
-template <> uint16_t p16w::operator*(void) const = delete;
+template <>
+uint8_t p8r::operator=(uint8_t n) const = delete;
+template <>
+uint8_t p8w::operator*(void) const = delete;
+template <>
+uint16_t p16r::operator=(uint16_t n) const = delete;
+template <>
+uint16_t p16w::operator*(void) const = delete;
 } // namespace hw

+ 0 - 1
include/kernel/vfs.h

@@ -1,6 +1,5 @@
 #pragma once
 
-#include "types/stdint.h"
 #include <types/types.h>
 
 #define INODE_FILE (1 << 0)

+ 88 - 13
src/kernel/hw/ata.cpp

@@ -1,8 +1,12 @@
 #include <asm/port_io.h>
+#include <kernel/hw/ata.hpp>
 #include <kernel/stdio.h>
 #include <kernel/syscall.hpp>
 #include <kernel/tty.h>
-#include <kernel/hw/ata.hpp>
+#include <kernel/vfs.h>
+#include <types/allocator.hpp>
+#include <types/status.h>
+#include <types/stdint.h>
 
 hw::ata::ata(port_id_t p)
     : data(p)
@@ -15,7 +19,9 @@ hw::ata::ata(port_id_t p)
     , drive(p + 6)
     , stats(p + 7)
     , comms(p + 7)
-{}
+    , slave_flag(0x00)
+{
+}
 
 hw::ata::stat_t hw::ata::status(void) const
 {
@@ -26,7 +32,7 @@ void hw::ata::identify(void) const
 {
     char buf[512] {};
 
-    drive = 0xa0;
+    drive = 0xa0 | slave_flag;
     count = 0;
     lbalo = 0;
     lbami = 0;
@@ -46,6 +52,17 @@ void hw::ata::identify(void) const
         syscall(0x03);
 }
 
+int hw::ata::select(bool master)
+{
+    if (master)
+        slave_flag = 0x00;
+    else
+        slave_flag = 0x10;
+
+    drive = 0xe0 | slave_flag;
+    return GB_OK;
+}
+
 size_t hw::ata::read_data(char* buf, size_t n) const
 {
     size_t orig_n = n;
@@ -57,18 +74,28 @@ size_t hw::ata::read_data(char* buf, size_t n) const
     return orig_n - n * 2;
 }
 
+size_t hw::ata::write_data(const char* buf, size_t n) const
+{
+    size_t orig_n = n;
+    n /= 2;
+    while (status().in.drq && n--) {
+        data = *(uint16_t*)buf;
+        buf += sizeof(uint16_t);
+    }
+    return orig_n - n * 2;
+}
+
 int hw::ata::read_sector(char* buf, uint32_t lba_low, uint16_t lba_high) const
 {
-    drive = 0x40;                   // SELECT MASTER DRIVE AND LBA48
-    count = 0x00;                   // HIGH BYTE
+    count = 0x00; // HIGH BYTE
     lbalo = (lba_low >> 24) & 0xff;
     lbami = lba_high & 0xff;
     lbahi = (lba_high >> 8) & 0xff;
-    count = 0x01;                   // LOW BYTE
+    count = 0x01; // LOW BYTE
     lbalo = lba_low & 0xff;
     lbami = (lba_low >> 8) & 0xff;
     lbahi = (lba_low >> 16) & 0xff;
-    comms = 0x24;                   // READ SECTORS EXT
+    comms = 0x24; // READ SECTORS EXT
 
     while (status().in.bsy)
         ;
@@ -77,16 +104,64 @@ int hw::ata::read_sector(char* buf, uint32_t lba_low, uint16_t lba_high) const
     return GB_OK;
 }
 
+int hw::ata::write_sector(const char* buf, uint32_t lba_low, uint16_t lba_high) const
+{
+    count = 0x00; // HIGH BYTE
+    lbalo = (lba_low >> 24) & 0xff;
+    lbami = lba_high & 0xff;
+    lbahi = (lba_high >> 8) & 0xff;
+    count = 0x01; // LOW BYTE
+    lbalo = lba_low & 0xff;
+    lbami = (lba_low >> 8) & 0xff;
+    lbahi = (lba_low >> 16) & 0xff;
+    comms = 0x24; // READ SECTORS EXT
+
+    while (status().in.bsy)
+        ;
+    if (status().in.drq)
+        write_data(buf, 512);
+    return GB_OK;
+}
+
+static hw::ata* ata_pri;
+
 void hw::init_ata(void* data)
 {
     if (data != nullptr)
         syscall(0x03);
 
-    ata ata_pri(ATA_PRIMARY_BUS_BASE);
-    ata_pri.identify();
+    ata_pri = types::kernel_allocator_new<ata>(ATA_PRIMARY_BUS_BASE);
+    ata_pri->identify();
+    ata_pri->select(true);
+
+    register_special_block(
+        2, 0,
+        [](char* buf, size_t buf_size, size_t offset, size_t n) -> size_t {
+            // TODO: check buf_size
+            char b[512] {};
+            char* orig_buf = buf;
+            size_t start = offset / 512;
+            size_t end = (offset + n + 511) / 512;
+            for (size_t i = start; i < end; ++i) {
+                ata_pri->read_sector(b, i, 0);
+                size_t to_copy = 0;
+                if (offset)
+                    to_copy = 512 - offset;
+                else
+                    to_copy = n > 512 ? 512 : n;
+                memcpy(buf, b + offset, to_copy);
+                offset = 0;
+                buf += to_copy;
+                n -= to_copy;
+            }
+            return buf - orig_buf;
+        },
+        [](const char* buf, size_t offset, size_t n) -> size_t {
+            syscall(0x03);
+            return n;
+        });
+    auto* hda = vfs_open("/dev/hda");
     char buf[512] {};
-    ata_pri.read_sector(buf, 0, 0);
-    tty_print(console, "sector 0 read\n");
-    ata_pri.read_sector(buf, 1, 0);
-    tty_print(console, "sector 1 read\n");
+    vfs_read(hda, buf, 512, 1, 512);
+    vfs_write(hda, buf, 1, 512);
 }