diff --git a/drivers/driver.cc b/drivers/driver.cc index f29a8ca9624ddcdeb23dda83720b35326ef9c59f..43daec46af3ccbcd606eb107b96aca9e0fffcd43 100644 --- a/drivers/driver.cc +++ b/drivers/driver.cc @@ -54,6 +54,17 @@ void Driver::setStatus(u16 s) { write_pci_config_word(_bus,_slot,_func,PCI_STATUS_OFFSET,s); } +u16 Driver::get_command(void) +{ + return (pci_readw(PCI_COMMAND_OFFSET)); +} + +void Driver::set_command(u16 c) +{ + pci_writew(PCI_COMMAND_OFFSET, c); +} + + u8 Driver::getRevision() { if (!_present) throw new InitException(); @@ -117,10 +128,16 @@ Driver::Init(Device* dev) { parse_pci_config(); - debug(fmt("Driver:Init %x:%x") % _vid % _id); - setBusMaster(true); + // Enable MSI-x + if (_have_msix) { + if (is_intx_enabled()) { + disable_intx(); + } + } + + debug(fmt("Driver initialized %x:%x") % _vid % _id); return true; } @@ -210,6 +227,26 @@ bool Driver::parse_pci_msix(u8 off) return true; } +bool Driver::is_intx_enabled(void) +{ + u16 command = get_command(); + return ( (command & PCI_COMMAND_INTX_DISABLE) == 0 ); +} + +void Driver::enable_intx(void) +{ + u16 command = get_command(); + command &= ~PCI_COMMAND_INTX_DISABLE; + set_command(command); +} + +void Driver::disable_intx(void) +{ + u16 command = get_command(); + command |= PCI_COMMAND_INTX_DISABLE; + set_command(command); +} + u8 Driver::pci_readb(u8 offset) { return read_pci_config_byte(_bus, _slot, _func, offset); diff --git a/drivers/driver.hh b/drivers/driver.hh index afa1f238f0391f11f321c79911410cb2d6ee2581..4013136373949be6f2af15983726858244f90e0f 100644 --- a/drivers/driver.hh +++ b/drivers/driver.hh @@ -50,6 +50,8 @@ public: u16 getStatus(); void setStatus(u16 s); + u16 get_command(void); + void set_command(u16 c); bool getBusMaster(); void setBusMaster(bool m); virtual void dumpConfig() const; @@ -88,6 +90,13 @@ protected: bool allocateBARs(); virtual bool earlyInitChecks(); + // Enable/Disable intx assertions + bool is_intx_enabled(void); + // Enable intx assertion + // intx assertions should be disabled in order to use MSI-x + void enable_intx(void); + void disable_intx(void); + // Parsing of extra capabilities virtual bool parse_pci_capabilities(void); virtual bool parse_pci_msix(u8 off); diff --git a/drivers/pci.hh b/drivers/pci.hh index 5f33fc74e64265288b2616f0a8809f9f4b27f2f6..6e108bec6a818d2f67a8bd32d6ff9fe0069bf7fc 100644 --- a/drivers/pci.hh +++ b/drivers/pci.hh @@ -63,6 +63,10 @@ using processor::outl; PCI_CAPABILITIES_PTR = 0x34, }; + enum pci_command_bits { + PCI_COMMAND_INTX_DISABLE = (1 << 10), + }; + // Capability Register Offsets enum pci_capabilities_offsets { PCI_CAP_OFF_ID = 0x0,