瀏覽代碼

SB16: Map the DMA buffer in kernelspace so we can write to it

This broke with the >3GB paging overhaul. It's no longer possible to
write directly to physical addresses below the 8MB mark. Physical pages
need to be mapped into kernel VM by using a Region.

Fixes #1099.
Andreas Kling 5 年之前
父節點
當前提交
b52d0afecf
共有 2 個文件被更改,包括 9 次插入5 次删除
  1. 8 4
      Kernel/Devices/SB16.cpp
  2. 1 1
      Kernel/Devices/SB16.h

+ 8 - 4
Kernel/Devices/SB16.cpp

@@ -27,6 +27,7 @@
 #include <Kernel/Devices/SB16.h>
 #include <Kernel/IO.h>
 #include <Kernel/Thread.h>
+#include <Kernel/VM/AnonymousVMObject.h>
 #include <Kernel/VM/MemoryManager.h>
 
 //#define SB16_DEBUG
@@ -123,7 +124,7 @@ ssize_t SB16::read(FileDescription&, u8*, ssize_t)
 
 void SB16::dma_start(uint32_t length)
 {
-    const auto addr = m_dma_buffer_page->paddr().get();
+    const auto addr = m_dma_region->vmobject().physical_pages()[0]->paddr().get();
     const u8 channel = 5; // 16-bit samples use DMA channel 5 (on the master DMA controller)
     const u8 mode = 0;
 
@@ -174,8 +175,11 @@ void SB16::wait_for_irq()
 
 ssize_t SB16::write(FileDescription&, const u8* data, ssize_t length)
 {
-    if (!m_dma_buffer_page)
-        m_dma_buffer_page = MM.allocate_supervisor_physical_page();
+    if (!m_dma_region) {
+        auto page = MM.allocate_supervisor_physical_page();
+        auto vmobject = AnonymousVMObject::create_with_physical_page(*page);
+        m_dma_region = MM.allocate_kernel_region_with_vmobject(*vmobject, PAGE_SIZE, "SB16 DMA buffer", Region::Access::Write);
+    }
 
 #ifdef SB16_DEBUG
     kprintf("SB16: Writing buffer of %d bytes\n", length);
@@ -190,7 +194,7 @@ ssize_t SB16::write(FileDescription&, const u8* data, ssize_t length)
 
     const int sample_rate = 44100;
     set_sample_rate(sample_rate);
-    memcpy(m_dma_buffer_page->paddr().as_ptr(), data, length);
+    memcpy(m_dma_region->vaddr().as_ptr(), data, length);
     dma_start(length);
 
     // 16-bit single-cycle output.

+ 1 - 1
Kernel/Devices/SB16.h

@@ -63,7 +63,7 @@ private:
     void dsp_write(u8 value);
     u8 dsp_read();
 
-    RefPtr<PhysicalPage> m_dma_buffer_page;
+    OwnPtr<Region> m_dma_region;
     int m_major_version { 0 };
 
     WaitQueue m_irq_queue;