Browse Source

Merge Disk namespace into the IDEDiskDevice class.

Andreas Kling 6 years ago
parent
commit
b8264e7d47
10 changed files with 231 additions and 244 deletions
  1. 1 0
      AK/Lock.h
  2. 0 194
      Kernel/Disk.cpp
  3. 0 34
      Kernel/Disk.h
  4. 184 2
      Kernel/IDEDiskDevice.cpp
  5. 27 2
      Kernel/IDEDiskDevice.h
  6. 0 1
      Kernel/Makefile
  7. 9 0
      Kernel/PIC.cpp
  8. 1 0
      Kernel/PIC.h
  9. 9 8
      Kernel/i386.cpp
  10. 0 3
      Kernel/init.cpp

+ 1 - 0
AK/Lock.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include "Assertions.h"
 #include "Types.h"
 
 #ifdef SERENITY

+ 0 - 194
Kernel/Disk.cpp

@@ -1,194 +0,0 @@
-#include "types.h"
-#include "Process.h"
-#include "VGA.h"
-#include "Disk.h"
-#include "kmalloc.h"
-#include "StdLib.h"
-#include "IO.h"
-#include "i386.h"
-#include "PIC.h"
-#include <AK/Lock.h>
-
-//#define DISK_DEBUG
-
-extern "C" void handle_interrupt();
-
-namespace Disk {
-
-ide_drive_t drive[4];
-static volatile bool interrupted;
-
-#define IRQ_FIXED_DISK           14
-
-extern "C" void ide_ISR();
-
-asm(
-    ".globl ide_ISR \n"
-    "ide_ISR: \n"
-    "    pusha\n"
-    "    pushw %ds\n"
-    "    pushw %es\n"
-    "    pushw %ss\n"
-    "    pushw %ss\n"
-    "    popw %ds\n"
-    "    popw %es\n"
-    "    call handle_interrupt\n"
-    "    popw %es\n"
-    "    popw %ds\n"
-    "    popa\n"
-    "    iret\n"
-);
-
-static void enableIRQ()
-{
-    PIC::enable(IRQ_FIXED_DISK);
-}
-
-static void disableIRQ()
-{
-    PIC::disable(IRQ_FIXED_DISK);
-}
-
-static bool waitForInterrupt()
-{
-#ifdef DISK_DEBUG
-    kprintf("disk: waiting for interrupt...\n");
-#endif
-    // FIXME: Add timeout.
-    while (!interrupted) {
-        sched_yield();
-    }
-#ifdef DISK_DEBUG
-    kprintf("disk: got interrupt!\n");
-#endif
-    return true;
-}
-
-void interrupt()
-{
-    IRQHandlerScope scope(IRQ_FIXED_DISK);
-#ifdef DISK_DEBUG
-    BYTE status = IO::in8(0x1f7);
-    kprintf("disk:interrupt: DRQ=%u BUSY=%u DRDY=%u\n", (status & DRQ) != 0, (status & BUSY) != 0, (status & DRDY) != 0);
-#endif
-    interrupted = true;
-}
-
-static SpinLock* s_diskLock;
-
-void initialize()
-{
-    s_diskLock = new SpinLock;
-    disableIRQ();
-    interrupted = false;
-    registerInterruptHandler(IRQ_VECTOR_BASE + IRQ_FIXED_DISK, ide_ISR);
-
-    while (IO::in8(IDE0_STATUS) & BUSY);
-
-    IO::out8(0x1F6, 0xA0); // 0xB0 for 2nd device
-    IO::out8(IDE0_COMMAND, IDENTIFY_DRIVE);
-
-    enableIRQ();
-    waitForInterrupt();
-
-    ByteBuffer wbuf = ByteBuffer::createUninitialized(512);
-    ByteBuffer bbuf = ByteBuffer::createUninitialized(512);
-    BYTE* b = bbuf.pointer();
-    WORD* w = (WORD*)wbuf.pointer();
-    const WORD* wbufbase = (WORD*)wbuf.pointer();
-
-    for (DWORD i = 0; i < 256; ++i) {
-        WORD data = IO::in16(IDE0_DATA);
-        *(w++) = data;
-        *(b++) = MSB(data);
-        *(b++) = LSB(data);
-    }
-
-    // "Unpad" the device name string.
-    for (DWORD i = 93; i > 54 && bbuf[i] == ' '; --i)
-        bbuf[i] = 0;
-
-    drive[0].cylinders = wbufbase[1];
-    drive[0].heads = wbufbase[3];
-    drive[0].sectors_per_track = wbufbase[6];
-
-    kprintf(
-        "ide0: Master=\"%s\", C/H/Spt=%u/%u/%u\n",
-        bbuf.pointer() + 54,
-        drive[0].cylinders,
-        drive[0].heads,
-        drive[0].sectors_per_track
-    );
-}
-
-struct CHS {
-    DWORD cylinder;
-    WORD head;
-    WORD sector;
-};
-
-static CHS lba2chs(BYTE drive_index, DWORD lba)
-{
-    ide_drive_t& d = drive[drive_index];
-    CHS chs;
-    chs.cylinder = lba / (d.sectors_per_track * d.heads);
-    chs.head = (lba / d.sectors_per_track) % d.heads;
-    chs.sector = (lba % d.sectors_per_track) + 1;
-    return chs;
-}
-
-bool readSectors(DWORD startSector, WORD count, BYTE* outbuf)
-{
-    LOCKER(*s_diskLock);
-#ifdef DISK_DEBUG
-    kprintf("%s: Disk::readSectors request (%u sector(s) @ %u)\n",
-            current->name().characters(),
-            count,
-            startSector);
-#endif
-    disableIRQ();
-
-    CHS chs = lba2chs(IDE0_DISK0, startSector);
-
-    while (IO::in8(IDE0_STATUS) & BUSY);
-
-#ifdef DISK_DEBUG
-    kprintf("ide0: Reading %u sector(s) @ LBA %u (%u/%u/%u)\n", count, startSector, chs.cylinder, chs.head, chs.sector);
-#endif
-
-    IO::out8(0x1F2, count == 256 ? 0 : LSB(count));
-    IO::out8(0x1F3, chs.sector);
-    IO::out8(0x1F4, LSB(chs.cylinder));
-    IO::out8(0x1F5, MSB(chs.cylinder));
-
-    IO::out8(0x1F6, 0xA0 | chs.head); /* 0xB0 for 2nd device */
-
-    IO::out8(0x3F6, 0x08);
-    while (!(IO::in8(IDE0_STATUS) & DRDY));
-
-    IO::out8(IDE0_COMMAND, READ_SECTORS);
-    interrupted = false;
-    enableIRQ();
-    waitForInterrupt();
-
-    BYTE status = IO::in8(0x1f7);
-    if (status & DRQ) {
-#ifdef DISK_DEBUG
-        kprintf("Retrieving %u bytes (status=%b), outbuf=%p...\n", count * 512, status, outbuf);
-#endif
-        for (DWORD i = 0; i < (count * 512); i += 2) {
-            WORD w = IO::in16(IDE0_DATA);
-            outbuf[i] = LSB(w);
-            outbuf[i+1] = MSB(w);
-        }
-    }
-
-    return true;
-}
-
-}
-
-extern "C" void handle_interrupt()
-{
-    Disk::interrupt();
-}

+ 0 - 34
Kernel/Disk.h

@@ -1,34 +0,0 @@
-#pragma once
-
-#include "types.h"
-
-#define IDE0_DATA        0x1F0
-#define IDE0_STATUS      0x1F7
-#define IDE0_COMMAND     0x1F7
-#define BUSY             0x80
-#define DRDY             0x40
-#define DRQ              0x08
-#define IDENTIFY_DRIVE   0xEC
-#define READ_SECTORS     0x21
-
-#define IDE0_DISK0       0
-#define IDE0_DISK1       1
-#define IDE1_DISK0       2
-#define IDE1_DISK1       3
-
-typedef struct
-{
-    WORD cylinders;
-    WORD heads;
-    WORD sectors_per_track;
-} ide_drive_t;
-
-extern void ide_init();
-extern ide_drive_t drive[4];
-
-namespace Disk {
-
-void initialize();
-bool readSectors(DWORD sectorIndex, WORD count, BYTE* buffer);
-
-}

+ 184 - 2
Kernel/IDEDiskDevice.cpp

@@ -1,5 +1,35 @@
 #include "IDEDiskDevice.h"
-#include "Disk.h"
+#include "types.h"
+#include "Process.h"
+#include "StdLib.h"
+#include "IO.h"
+#include "Scheduler.h"
+#include "PIC.h"
+#include <AK/Lock.h>
+
+//#define DISK_DEBUG
+
+#define IRQ_FIXED_DISK 14
+
+#define IDE0_DATA        0x1F0
+#define IDE0_STATUS      0x1F7
+#define IDE0_COMMAND     0x1F7
+
+enum IDECommand : byte {
+    IDENTIFY_DRIVE = 0xEC,
+    READ_SECTORS = 0x21,
+};
+
+enum IDEStatus : byte {
+    BUSY = (1 << 7),
+    DRDY = (1 << 6),
+    DF   = (1 << 5),
+    SRV  = (1 << 4),
+    DRQ  = (1 << 3),
+    CORR = (1 << 2),
+    IDX  = (1 << 1),
+    ERR  = (1 << 0),
+};
 
 RetainPtr<IDEDiskDevice> IDEDiskDevice::create()
 {
@@ -7,7 +37,9 @@ RetainPtr<IDEDiskDevice> IDEDiskDevice::create()
 }
 
 IDEDiskDevice::IDEDiskDevice()
+    : IRQHandler(IRQ_FIXED_DISK)
 {
+    initialize();
 }
 
 IDEDiskDevice::~IDEDiskDevice()
@@ -26,7 +58,7 @@ unsigned IDEDiskDevice::blockSize() const
 
 bool IDEDiskDevice::readBlock(unsigned index, byte* out) const
 {
-    Disk::readSectors(index, 1, out);
+    const_cast<IDEDiskDevice&>(*this).read_sectors(index, 1, out);
     return true;
 }
 
@@ -39,3 +71,153 @@ bool IDEDiskDevice::writeBlock(unsigned index, const byte* data)
     return false;
 }
 
+#ifdef DISK_DEBUG
+static void print_ide_status(byte status)
+{
+    kprintf("DRQ=%u BUSY=%u DRDY=%u SRV=%u DF=%u CORR=%u IDX=%u ERR=%u\n",
+            (status & DRQ) != 0,
+            (status & BUSY) != 0,
+            (status & DRDY) != 0,
+            (status & SRV) != 0,
+            (status & DF) != 0,
+            (status & CORR) != 0,
+            (status & IDX) != 0,
+            (status & ERR) != 0);
+}
+#endif
+
+bool IDEDiskDevice::wait_for_irq()
+{
+#ifdef DISK_DEBUG
+    kprintf("disk: waiting for interrupt...\n");
+#endif
+    // FIXME: Add timeout.
+    while (!m_interrupted) {
+        // FIXME: Put this process into a Blocked state instead, it's stupid to wake up just to check a flag.
+        Scheduler::yield();
+    }
+#ifdef DISK_DEBUG
+    kprintf("disk: got interrupt!\n");
+#endif
+    return true;
+}
+
+void IDEDiskDevice::handleIRQ()
+{
+#ifdef DISK_DEBUG
+    byte status = IO::in8(0x1f7);
+    kprintf("disk:interrupt: DRQ=%u BUSY=%u DRDY=%u\n", (status & DRQ) != 0, (status & BUSY) != 0, (status & DRDY) != 0);
+#endif
+    m_interrupted = true;
+}
+
+void IDEDiskDevice::initialize()
+{
+    byte status;
+
+    status = IO::in8(IDE0_STATUS);
+#ifdef DISK_DEBUG
+    kprintf("initial status: ");
+    print_ide_status(status);
+#endif
+
+    m_interrupted = false;
+
+    while (IO::in8(IDE0_STATUS) & BUSY);
+
+    enableIRQ();
+
+    IO::out8(0x1F6, 0xA0); // 0xB0 for 2nd device
+    IO::out8(0x3F6, 0xA0); // 0xB0 for 2nd device
+    IO::out8(IDE0_COMMAND, IDENTIFY_DRIVE);
+
+    enableIRQ();
+    wait_for_irq();
+
+    ByteBuffer wbuf = ByteBuffer::createUninitialized(512);
+    ByteBuffer bbuf = ByteBuffer::createUninitialized(512);
+    byte* b = bbuf.pointer();
+    word* w = (word*)wbuf.pointer();
+    const word* wbufbase = (word*)wbuf.pointer();
+
+    for (dword i = 0; i < 256; ++i) {
+        word data = IO::in16(IDE0_DATA);
+        *(w++) = data;
+        *(b++) = MSB(data);
+        *(b++) = LSB(data);
+    }
+
+    // "Unpad" the device name string.
+    for (dword i = 93; i > 54 && bbuf[i] == ' '; --i)
+        bbuf[i] = 0;
+
+    m_cylinders = wbufbase[1];
+    m_heads = wbufbase[3];
+    m_sectors_per_track = wbufbase[6];
+
+    kprintf(
+        "ide0: Master=\"%s\", C/H/Spt=%u/%u/%u\n",
+        bbuf.pointer() + 54,
+        m_cylinders,
+        m_heads,
+        m_sectors_per_track
+    );
+}
+
+IDEDiskDevice::CHS IDEDiskDevice::lba_to_chs(dword lba) const
+{
+    CHS chs;
+    chs.cylinder = lba / (m_sectors_per_track * m_heads);
+    chs.head = (lba / m_sectors_per_track) % m_heads;
+    chs.sector = (lba % m_sectors_per_track) + 1;
+    return chs;
+}
+
+bool IDEDiskDevice::read_sectors(dword start_sector, word count, byte* outbuf)
+{
+    LOCKER(m_lock);
+#ifdef DISK_DEBUG
+    kprintf("%s: Disk::read_sectors request (%u sector(s) @ %u)\n",
+            current->name().characters(),
+            count,
+            start_sector);
+#endif
+    disableIRQ();
+
+    auto chs = lba_to_chs(start_sector);
+
+    while (IO::in8(IDE0_STATUS) & BUSY);
+
+#ifdef DISK_DEBUG
+    kprintf("ide0: Reading %u sector(s) @ LBA %u (%u/%u/%u)\n", count, start_sector, chs.cylinder, chs.head, chs.sector);
+#endif
+
+    IO::out8(0x1F2, count == 256 ? 0 : LSB(count));
+    IO::out8(0x1F3, chs.sector);
+    IO::out8(0x1F4, LSB(chs.cylinder));
+    IO::out8(0x1F5, MSB(chs.cylinder));
+
+    IO::out8(0x1F6, 0xA0 | chs.head); /* 0xB0 for 2nd device */
+
+    IO::out8(0x3F6, 0x08);
+    while (!(IO::in8(IDE0_STATUS) & DRDY));
+
+    IO::out8(IDE0_COMMAND, READ_SECTORS);
+    m_interrupted = false;
+    enableIRQ();
+    wait_for_irq();
+
+    byte status = IO::in8(0x1f7);
+    if (status & DRQ) {
+#ifdef DISK_DEBUG
+        kprintf("Retrieving %u bytes (status=%b), outbuf=%p...\n", count * 512, status, outbuf);
+#endif
+        for (dword i = 0; i < (count * 512); i += 2) {
+            word w = IO::in16(IDE0_DATA);
+            outbuf[i] = LSB(w);
+            outbuf[i+1] = MSB(w);
+        }
+    }
+
+    return true;
+}

+ 27 - 2
Kernel/IDEDiskDevice.h

@@ -1,13 +1,16 @@
 #pragma once
 
+#include <AK/Lock.h>
 #include <AK/RetainPtr.h>
 #include <VirtualFileSystem/DiskDevice.h>
+#include "IRQHandler.h"
 
-class IDEDiskDevice final : public DiskDevice {
+class IDEDiskDevice final : public IRQHandler, public DiskDevice {
 public:
     static RetainPtr<IDEDiskDevice> create();
-    virtual ~IDEDiskDevice();
+    virtual ~IDEDiskDevice() override;
 
+    // ^DiskDevice
     virtual unsigned blockSize() const override;
     virtual bool readBlock(unsigned index, byte*) const override;
     virtual bool writeBlock(unsigned index, const byte*) override;
@@ -16,6 +19,28 @@ protected:
     IDEDiskDevice();
 
 private:
+    // ^IRQHandler
+    virtual void handleIRQ() override;
+
+    // ^DiskDevice
     virtual const char* className() const override;
+
+    struct CHS {
+        dword cylinder;
+        word head;
+        word sector;
+    };
+    CHS lba_to_chs(dword) const;
+
+    void initialize();
+    bool wait_for_irq();
+    bool read_sectors(dword start_sector, word count, byte* outbuf);
+
+    SpinLock m_lock;
+    word m_cylinders { 0 };
+    word m_heads { 0 };
+    word m_sectors_per_track { 0 };
+    mutable volatile bool m_interrupted { false };
+
 };
 

+ 0 - 1
Kernel/Makefile

@@ -11,7 +11,6 @@ KERNEL_OBJS = \
        CMOS.o \
        PIC.o \
        Syscall.o \
-       Disk.o \
        IDEDiskDevice.o \
        MemoryManager.o \
        Console.o \

+ 9 - 0
Kernel/PIC.cpp

@@ -100,4 +100,13 @@ word getISR()
     return (isr1 << 8) | isr0;
 }
 
+word get_irr()
+{
+    IO::out8(PIC0_CTL, 0x0a);
+    IO::out8(PIC1_CTL, 0x0a);
+    byte irr0 = IO::in8(PIC0_CTL);
+    byte irr1 = IO::in8(PIC1_CTL);
+    return (irr1 << 8) | irr0;
+}
+
 }

+ 1 - 0
Kernel/PIC.h

@@ -9,6 +9,7 @@ void disable(BYTE number);
 void eoi(BYTE number);
 void initialize();
 word getISR();
+word get_irr();
 
 }
 

+ 9 - 8
Kernel/i386.cpp

@@ -38,12 +38,12 @@ void gdt_free_entry(word entry)
     s_gdt_freelist->append(entry);
 }
 
-extern "C" void handleIRQ();
-extern "C" void commonIRQEntry();
+extern "C" void handle_irq();
+extern "C" void asm_irq_entry();
 
 asm(
-    ".globl commonIRQEntry\n"
-    "commonIRQEntry: \n"
+    ".globl asm_irq_entry\n"
+    "asm_irq_entry: \n"
     "    pusha\n"
     "    pushw %ds\n"
     "    pushw %es\n"
@@ -51,7 +51,7 @@ asm(
     "    pushw %ss\n"
     "    popw %ds\n"
     "    popw %es\n"
-    "    call handleIRQ\n"
+    "    call handle_irq\n"
     "    popw %es\n"
     "    popw %ds\n"
     "    popa\n"
@@ -349,8 +349,7 @@ void registerIRQHandler(byte irq, IRQHandler& handler)
 {
     ASSERT(!s_irqHandler[irq]);
     s_irqHandler[irq] = &handler;
-    kprintf("irq handler for %u: %p\n", irq, &handler);
-    registerInterruptHandler(IRQ_VECTOR_BASE + irq, commonIRQEntry);
+    registerInterruptHandler(IRQ_VECTOR_BASE + irq, asm_irq_entry);
 }
 
 void unregisterIRQHandler(byte irq, IRQHandler& handler)
@@ -433,7 +432,7 @@ void load_task_register(WORD selector)
     asm("ltr %0"::"r"(selector));
 }
 
-void handleIRQ()
+void handle_irq()
 {
     WORD isr = PIC::getISR();
     if (!isr) {
@@ -443,6 +442,8 @@ void handleIRQ()
 
     byte irq = 0;
     for (byte i = 0; i < 16; ++i) {
+        if (i == 2)
+            continue;
         if (isr & (1 << i)) {
             irq = i;
             break;

+ 0 - 3
Kernel/init.cpp

@@ -6,7 +6,6 @@
 #include "Keyboard.h"
 #include "Process.h"
 #include "system.h"
-#include "Disk.h"
 #include "PIC.h"
 #include "StdLib.h"
 #include "Syscall.h"
@@ -176,8 +175,6 @@ static void init_stage2()
 {
     Syscall::initialize();
 
-    Disk::initialize();
-
 #ifdef TEST_VFS
     auto vfs = make<VirtualFileSystem>();