Explorar el Código

Kernel: Add a kernel boot parameter to force PIO mode

Also added an option in the run script to force PIO operation mode with
the IDE controller.
In addition, we're no longer limited to PIIX3 and PIIX4 chipsets for DMA
supercomputer7 hace 5 años
padre
commit
4fe2ee0221

+ 17 - 15
Kernel/Devices/PATAChannel.cpp

@@ -75,6 +75,8 @@
 #define ATA_CTL_ALTSTATUS 0x00
 #define ATA_CTL_ALTSTATUS 0x00
 #define ATA_CTL_DEVADDRESS 0x01
 #define ATA_CTL_DEVADDRESS 0x01
 
 
+#define PCI_Mass_Storage_Class 0x1
+#define PCI_IDE_Controller_Subclass 0x1
 static Lock& s_lock()
 static Lock& s_lock()
 {
 {
     static Lock* lock;
     static Lock* lock;
@@ -84,12 +86,12 @@ static Lock& s_lock()
     return *lock;
     return *lock;
 };
 };
 
 
-OwnPtr<PATAChannel> PATAChannel::create(ChannelType type)
+OwnPtr<PATAChannel> PATAChannel::create(ChannelType type, bool force_pio)
 {
 {
-    return make<PATAChannel>(type);
+    return make<PATAChannel>(type, force_pio);
 }
 }
 
 
-PATAChannel::PATAChannel(ChannelType type)
+PATAChannel::PATAChannel(ChannelType type, bool force_pio)
     : IRQHandler((type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ))
     : IRQHandler((type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ))
     , m_channel_number((type == ChannelType::Primary ? 0 : 1))
     , m_channel_number((type == ChannelType::Primary ? 0 : 1))
     , m_io_base((type == ChannelType::Primary ? 0x1F0 : 0x170))
     , m_io_base((type == ChannelType::Primary ? 0x1F0 : 0x170))
@@ -98,7 +100,7 @@ PATAChannel::PATAChannel(ChannelType type)
     m_dma_enabled.resource() = true;
     m_dma_enabled.resource() = true;
     ProcFS::add_sys_bool("ide_dma", m_dma_enabled);
     ProcFS::add_sys_bool("ide_dma", m_dma_enabled);
 
 
-    initialize();
+    initialize(force_pio);
     detect_disks();
     detect_disks();
 }
 }
 
 
@@ -106,26 +108,26 @@ PATAChannel::~PATAChannel()
 {
 {
 }
 }
 
 
-void PATAChannel::initialize()
+void PATAChannel::initialize(bool force_pio)
 {
 {
-    static const PCI::ID piix3_ide_id = { 0x8086, 0x7010 };
-    static const PCI::ID piix4_ide_id = { 0x8086, 0x7111 };
     PCI::enumerate_all([this](const PCI::Address& address, PCI::ID id) {
     PCI::enumerate_all([this](const PCI::Address& address, PCI::ID id) {
-        if (id == piix3_ide_id || id == piix4_ide_id) {
+        if (PCI::get_class(address) == PCI_Mass_Storage_Class && PCI::get_subclass(address) == PCI_IDE_Controller_Subclass) {
             m_pci_address = address;
             m_pci_address = address;
-            kprintf("PATAChannel: PIIX%u PATA Controller found!\n", id == piix3_ide_id ? 3 : 4);
+            kprintf("PATAChannel: PATA Controller found! id=%w:%w\n", id.vendor_id, id.device_id);
         }
         }
     });
     });
-
-    // Let's try to set up DMA transfers.
+    m_force_pio.resource() = false;
     if (!m_pci_address.is_null()) {
     if (!m_pci_address.is_null()) {
-        m_prdt.end_of_table = 0x8000;
+        // Let's try to set up DMA transfers.
         PCI::enable_bus_mastering(m_pci_address);
         PCI::enable_bus_mastering(m_pci_address);
+        m_prdt.end_of_table = 0x8000;
         m_bus_master_base = PCI::get_BAR4(m_pci_address) & 0xfffc;
         m_bus_master_base = PCI::get_BAR4(m_pci_address) & 0xfffc;
         m_dma_buffer_page = MM.allocate_supervisor_physical_page();
         m_dma_buffer_page = MM.allocate_supervisor_physical_page();
-        kprintf("PATAChannel: PIIX Bus master IDE: I/O @ %x\n", m_bus_master_base);
-    } else {
-        kprintf("PATAChannel: Unable to find valid PATAChannel controller! Falling back to PIO mode!\n");
+        kprintf("PATAChannel: Bus master IDE: I/O @ %x\n", m_bus_master_base);
+        if (force_pio) {
+            m_force_pio.resource() = true;
+            kprintf("PATAChannel: Requested to force PIO mode!\n");
+        }
     }
     }
 }
 }
 
 

+ 4 - 3
Kernel/Devices/PATAChannel.h

@@ -35,8 +35,8 @@ public:
     };
     };
 
 
 public:
 public:
-    static OwnPtr<PATAChannel> create(ChannelType type);
-    explicit PATAChannel(ChannelType);
+    static OwnPtr<PATAChannel> create(ChannelType type, bool force_pio);
+    PATAChannel(ChannelType type, bool force_pio);
     virtual ~PATAChannel() override;
     virtual ~PATAChannel() override;
 
 
     RefPtr<PATADiskDevice> master_device() { return m_master; };
     RefPtr<PATADiskDevice> master_device() { return m_master; };
@@ -46,7 +46,7 @@ private:
     //^ IRQHandler
     //^ IRQHandler
     virtual void handle_irq() override;
     virtual void handle_irq() override;
 
 
-    void initialize();
+    void initialize(bool force_pio);
     void detect_disks();
     void detect_disks();
 
 
     bool wait_for_irq();
     bool wait_for_irq();
@@ -67,6 +67,7 @@ private:
     RefPtr<PhysicalPage> m_dma_buffer_page;
     RefPtr<PhysicalPage> m_dma_buffer_page;
     u16 m_bus_master_base { 0 };
     u16 m_bus_master_base { 0 };
     Lockable<bool> m_dma_enabled;
     Lockable<bool> m_dma_enabled;
+    Lockable<bool> m_force_pio;
 
 
     RefPtr<PATADiskDevice> m_master;
     RefPtr<PATADiskDevice> m_master;
     RefPtr<PATADiskDevice> m_slave;
     RefPtr<PATADiskDevice> m_slave;

+ 1 - 1
Kernel/Devices/PATADiskDevice.cpp

@@ -24,7 +24,7 @@ const char* PATADiskDevice::class_name() const
 
 
 bool PATADiskDevice::read_blocks(unsigned index, u16 count, u8* out)
 bool PATADiskDevice::read_blocks(unsigned index, u16 count, u8* out)
 {
 {
-    if (m_channel.m_bus_master_base && m_channel.m_dma_enabled.resource())
+    if (m_channel.m_bus_master_base && m_channel.m_dma_enabled.resource() && !m_channel.m_force_pio.resource())
         return read_sectors_with_dma(index, count, out);
         return read_sectors_with_dma(index, count, out);
     return read_sectors(index, count, out);
     return read_sectors(index, count, out);
 }
 }

+ 2 - 1
Kernel/init.cpp

@@ -67,6 +67,7 @@ VFS* vfs;
     auto dev_ptmx = make<PTYMultiplexer>();
     auto dev_ptmx = make<PTYMultiplexer>();
 
 
     bool text_debug = KParams::the().has("text_debug");
     bool text_debug = KParams::the().has("text_debug");
+    bool force_pio = KParams::the().has("force_pio");
 
 
     auto root = KParams::the().get("root");
     auto root = KParams::the().get("root");
     if (root.is_empty()) {
     if (root.is_empty()) {
@@ -78,7 +79,7 @@ VFS* vfs;
         hang();
         hang();
     }
     }
 
 
-    auto pata0 = PATAChannel::create(PATAChannel::ChannelType::Primary);
+    auto pata0 = PATAChannel::create(PATAChannel::ChannelType::Primary, force_pio);
     NonnullRefPtr<DiskDevice> root_dev = *pata0->master_device();
     NonnullRefPtr<DiskDevice> root_dev = *pata0->master_device();
 
 
     root = root.substring(strlen("/dev/hda"), root.length() - strlen("/dev/hda"));
     root = root.substring(strlen("/dev/hda"), root.length() - strlen("/dev/hda"));

+ 8 - 3
Kernel/run

@@ -51,13 +51,18 @@ elif [ "$1" = "qgrub" ]; then
         $SERENITY_PACKET_LOGGING_ARG \
         $SERENITY_PACKET_LOGGING_ARG \
         -netdev user,id=breh,hostfwd=tcp:127.0.0.1:8888-10.0.2.15:8888,hostfwd=tcp:127.0.0.1:8823-10.0.2.15:23 \
         -netdev user,id=breh,hostfwd=tcp:127.0.0.1:8888-10.0.2.15:8888,hostfwd=tcp:127.0.0.1:8823-10.0.2.15:23 \
         -device e1000,netdev=breh
         -device e1000,netdev=breh
-elif [ "$1" = "qtext" ]; then
-    # ./run: qemu with serenity in text mode
+elif [ "$1" = "qcmd" ]; then
+    SERENITY_KERNEL_CMDLINE=""
+    for (( i=2; i<=$#; i++)); do
+        SERENITY_KERNEL_CMDLINE+="${!i} "
+    done
+    echo "Starting SerenityOS, Commandline: ${SERENITY_KERNEL_CMDLINE}"
+    # ./run: qemu with serenity with custom commandline
     $SERENITY_QEMU_BIN \
     $SERENITY_QEMU_BIN \
         $SERENITY_COMMON_QEMU_ARGS \
         $SERENITY_COMMON_QEMU_ARGS \
         -device e1000 \
         -device e1000 \
         -kernel kernel \
         -kernel kernel \
-        -append "${SERENITY_KERNEL_CMDLINE} text_debug"
+        -append "${SERENITY_KERNEL_CMDLINE}"
 else
 else
     # ./run: qemu with user networking
     # ./run: qemu with user networking
     $SERENITY_QEMU_BIN \
     $SERENITY_QEMU_BIN \