diff --git a/drivers/storage/ided/src/main.rs b/drivers/storage/ided/src/main.rs index 4632316a0b..10dbbcb0a5 100644 --- a/drivers/storage/ided/src/main.rs +++ b/drivers/storage/ided/src/main.rs @@ -44,13 +44,45 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! { let dma = pci_config.func.full_device_id.interface & 0x80 != 0; let busmaster_base = pci_config.func.bars[4].expect_port(); - let (primary, primary_irq) = if pci_config.func.full_device_id.interface & 1 != 0 { - panic!("TODO: IDE primary channel is PCI native"); + + // PCI IDE Programming Interface byte (PCI spec ยง3.1.1): + // bit 0: primary channel operates in native mode (else compatibility) + // bit 1: primary channel is switchable + // bit 2: secondary channel operates in native mode (else compatibility) + // bit 3: secondary channel is switchable + // + // In compatibility mode, the legacy I/O ports (0x1F0/0x3F6 primary, + // 0x170/0x376 secondary) and IRQs (14/15) are hardwired. In native mode, + // the I/O base and control base come from PCI BARs and the interrupt + // comes from the PCI interrupt pin (INTA#/INTB#). + let interface = pci_config.func.full_device_id.interface; + + let (primary, primary_irq) = if interface & 0x01 != 0 { + // Primary native: BAR0 = I/O base, BAR1 = control base + let io_base = pci_config.func.bars[0].expect_port(); + let ctrl_base = pci_config.func.bars[1].expect_port(); + let irq = pci_config + .func + .legacy_interrupt_line + .map(|l| l.irq) + .unwrap_or(14); + info!("IDE primary channel: native mode io={:#x} ctrl={:#x} irq={}", io_base, ctrl_base, irq); + (Channel::new(io_base, ctrl_base, busmaster_base).unwrap(), irq) } else { (Channel::primary_compat(busmaster_base).unwrap(), 14) }; - let (secondary, secondary_irq) = if pci_config.func.full_device_id.interface & 1 != 0 { - panic!("TODO: IDE secondary channel is PCI native"); + + let (secondary, secondary_irq) = if interface & 0x04 != 0 { + // Secondary native: BAR2 = I/O base, BAR3 = control base + let io_base = pci_config.func.bars[2].expect_port(); + let ctrl_base = pci_config.func.bars[3].expect_port(); + let irq = pci_config + .func + .legacy_interrupt_line + .map(|l| l.irq) + .unwrap_or(15); + info!("IDE secondary channel: native mode io={:#x} ctrl={:#x} irq={}", io_base, ctrl_base, irq); + (Channel::new(io_base, ctrl_base, busmaster_base + 8).unwrap(), irq) } else { (Channel::secondary_compat(busmaster_base + 8).unwrap(), 15) };