From 4fe2ee0221ee8bf457fe2b20b095b1b1af520b86 Mon Sep 17 00:00:00 2001 From: supercomputer7 Date: Wed, 13 Nov 2019 19:29:16 +0200 Subject: 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 --- Kernel/Devices/PATAChannel.cpp | 32 +++++++++++++++++--------------- Kernel/Devices/PATAChannel.h | 7 ++++--- Kernel/Devices/PATADiskDevice.cpp | 2 +- Kernel/init.cpp | 3 ++- Kernel/run | 11 ++++++++--- 5 files changed, 32 insertions(+), 23 deletions(-) (limited to 'Kernel') 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 \ -- cgit v1.2.3