diff --git a/headers/os/drivers/PCI.h b/headers/os/drivers/PCI.h index d76a69b5a6..98a1dc90aa 100644 --- a/headers/os/drivers/PCI.h +++ b/headers/os/drivers/PCI.h @@ -155,6 +155,7 @@ struct pci_module_info { uchar cap_id, uchar *offset ); + status_t (*reserve_device) ( uchar bus, uchar device, @@ -167,6 +168,12 @@ struct pci_module_info { uchar function, const char *driver_name, void *cookie); + + status_t (*update_interrupt_line) ( + uchar bus, + uchar device, + uchar function, + uchar newInterruptLineValue); }; #define B_PCI_MODULE_NAME "bus_managers/pci/v1" diff --git a/src/add-ons/kernel/bus_managers/pci/pci.cpp b/src/add-ons/kernel/bus_managers/pci/pci.cpp index 3ef74d9fd9..54306f25be 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci.cpp @@ -277,6 +277,20 @@ err0: } +status_t +pci_update_interrupt_line(uchar virtualBus, uchar device, uchar function, + uchar newInterruptLineValue) +{ + uint8 bus; + int domain; + if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) + return B_ERROR; + + return gPCI->UpdateInterruptLine(domain, bus, device, function, + newInterruptLineValue); +} + + // used by pci_info.cpp print_info_basic() void __pci_resolve_virtual_bus(uint8 virtualBus, int *domain, uint8 *bus) @@ -1540,3 +1554,29 @@ PCI::_FindDevice(PCIBus *current, int domain, uint8 bus, uint8 device, return NULL; } + + +status_t +PCI::UpdateInterruptLine(int domain, uint8 bus, uint8 _device, uint8 function, + uint8 newInterruptLineValue) +{ + PCIDev *device = FindDevice(domain, bus, _device, function); + if (device == NULL) + return B_ERROR; + + pci_info &info = device->info; + switch (info.header_type & PCI_header_type_mask) { + case PCI_header_type_generic: + info.u.h0.interrupt_line = newInterruptLineValue; + break; + + case PCI_header_type_PCI_to_PCI_bridge: + info.u.h1.interrupt_line = newInterruptLineValue; + break; + + default: + return B_ERROR; + } + + return WriteConfig(device, PCI_interrupt_line, 1, newInterruptLineValue); +} diff --git a/src/add-ons/kernel/bus_managers/pci/pci.h b/src/add-ons/kernel/bus_managers/pci/pci.h index 670c88d4ef..626ed79030 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.h +++ b/src/add-ons/kernel/bus_managers/pci/pci.h @@ -105,6 +105,10 @@ public: void RefreshDeviceInfo(); + status_t UpdateInterruptLine(int domain, uint8 bus, + uint8 device, uint8 function, + uint8 newInterruptLineValue); + private: void _EnumerateBus(int domain, uint8 bus, uint8 *subordinateBus = NULL); diff --git a/src/add-ons/kernel/bus_managers/pci/pci_module.cpp b/src/add-ons/kernel/bus_managers/pci/pci_module.cpp index 03e983230d..8685fdbb38 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_module.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci_module.cpp @@ -66,7 +66,8 @@ static struct pci_module_info sOldPCIModule = { &pci_ram_address, &pci_find_capability, &pci_reserve_device, - &pci_unreserve_device + &pci_unreserve_device, + &pci_update_interrupt_line }; module_dependency module_dependencies[] = { diff --git a/src/add-ons/kernel/bus_managers/pci/pci_private.h b/src/add-ons/kernel/bus_managers/pci/pci_private.h index 5fe87098c8..973dc417b8 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_private.h +++ b/src/add-ons/kernel/bus_managers/pci/pci_private.h @@ -53,6 +53,9 @@ status_t pci_reserve_device(uchar virtualBus, uchar device, uchar function, status_t pci_unreserve_device(uchar virtualBus, uchar device, uchar function, const char *driverName, void *nodeCookie); +status_t pci_update_interrupt_line(uchar virtualBus, uchar device, + uchar function, uchar newInterruptLineValue); + status_t pci_io_init(void); uint8 pci_read_io_8(int mapped_io_addr); void pci_write_io_8(int mapped_io_addr, uint8 value);