From 63cffb7ee364813e37e50b40444a2c071952f92d Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 7 May 2011 16:40:32 +0000 Subject: [PATCH] Add a way to store a new interrupt_line value to the PCI module. It both updates the cached pci_info and writes the new value into PCI config space. Drivers using either mechanism to enumerate devices will therefore get the updated value. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41364 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/drivers/PCI.h | 7 ++++ src/add-ons/kernel/bus_managers/pci/pci.cpp | 40 +++++++++++++++++++ src/add-ons/kernel/bus_managers/pci/pci.h | 4 ++ .../kernel/bus_managers/pci/pci_module.cpp | 3 +- .../kernel/bus_managers/pci/pci_private.h | 3 ++ 5 files changed, 56 insertions(+), 1 deletion(-) 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);