diff --git a/Kernel/Devices/PATAChannel.cpp b/Kernel/Devices/PATAChannel.cpp index 8ba881d02f..5e2fb84cb2 100644 --- a/Kernel/Devices/PATAChannel.cpp +++ b/Kernel/Devices/PATAChannel.cpp @@ -75,6 +75,8 @@ #define ATA_CTL_ALTSTATUS 0x00 #define ATA_CTL_DEVADDRESS 0x01 +#define PCI_Mass_Storage_Class 0x1 +#define PCI_IDE_Controller_Subclass 0x1 static Lock& s_lock() { static Lock* lock; @@ -84,12 +86,12 @@ static Lock& s_lock() return *lock; }; -OwnPtr PATAChannel::create(ChannelType type) +OwnPtr PATAChannel::create(ChannelType type, bool force_pio) { - return make(type); + return make(type, force_pio); } -PATAChannel::PATAChannel(ChannelType type) +PATAChannel::PATAChannel(ChannelType type, bool force_pio) : IRQHandler((type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ)) , m_channel_number((type == ChannelType::Primary ? 0 : 1)) , m_io_base((type == ChannelType::Primary ? 0x1F0 : 0x170)) @@ -98,7 +100,7 @@ PATAChannel::PATAChannel(ChannelType type) m_dma_enabled.resource() = true; ProcFS::add_sys_bool("ide_dma", m_dma_enabled); - initialize(); + initialize(force_pio); 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) { - 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; - 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()) { - m_prdt.end_of_table = 0x8000; + // Let's try to set up DMA transfers. 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_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"); + } } } diff --git a/Kernel/Devices/PATAChannel.h b/Kernel/Devices/PATAChannel.h index f296b80516..0806c2fa8c 100644 --- a/Kernel/Devices/PATAChannel.h +++ b/Kernel/Devices/PATAChannel.h @@ -35,8 +35,8 @@ public: }; public: - static OwnPtr create(ChannelType type); - explicit PATAChannel(ChannelType); + static OwnPtr create(ChannelType type, bool force_pio); + PATAChannel(ChannelType type, bool force_pio); virtual ~PATAChannel() override; RefPtr master_device() { return m_master; }; @@ -46,7 +46,7 @@ private: //^ IRQHandler virtual void handle_irq() override; - void initialize(); + void initialize(bool force_pio); void detect_disks(); bool wait_for_irq(); @@ -67,6 +67,7 @@ private: RefPtr m_dma_buffer_page; u16 m_bus_master_base { 0 }; Lockable m_dma_enabled; + Lockable m_force_pio; RefPtr m_master; RefPtr m_slave; diff --git a/Kernel/Devices/PATADiskDevice.cpp b/Kernel/Devices/PATADiskDevice.cpp index 8c017e5d7a..eadbb1957d 100644 --- a/Kernel/Devices/PATADiskDevice.cpp +++ b/Kernel/Devices/PATADiskDevice.cpp @@ -24,7 +24,7 @@ const char* PATADiskDevice::class_name() const 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(index, count, out); } diff --git a/Kernel/init.cpp b/Kernel/init.cpp index ee00438879..9ec55e2e88 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -67,6 +67,7 @@ VFS* vfs; auto dev_ptmx = make(); bool text_debug = KParams::the().has("text_debug"); + bool force_pio = KParams::the().has("force_pio"); auto root = KParams::the().get("root"); if (root.is_empty()) { @@ -78,7 +79,7 @@ VFS* vfs; hang(); } - auto pata0 = PATAChannel::create(PATAChannel::ChannelType::Primary); + auto pata0 = PATAChannel::create(PATAChannel::ChannelType::Primary, force_pio); NonnullRefPtr root_dev = *pata0->master_device(); root = root.substring(strlen("/dev/hda"), root.length() - strlen("/dev/hda")); diff --git a/Kernel/run b/Kernel/run index dc02ed80dc..a245b28f92 100755 --- a/Kernel/run +++ b/Kernel/run @@ -51,13 +51,18 @@ elif [ "$1" = "qgrub" ]; then $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 \ -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_COMMON_QEMU_ARGS \ -device e1000 \ -kernel kernel \ - -append "${SERENITY_KERNEL_CMDLINE} text_debug" + -append "${SERENITY_KERNEL_CMDLINE}" else # ./run: qemu with user networking $SERENITY_QEMU_BIN \