PCI: added a HyperTransport mapping info for x86

* fill it with HT MSI mapping capability information.
* enable/disable mapping on the device accordingly in enable_msi(),
disable_msi(), enable_msix(), disable_msix().
* untested. The mapping could instead be enabled/disabled on the HT PCI bus,
aka the parent device of the device passed to enable_msi/disable_msix().
This commit is contained in:
Jérôme Duval
2013-07-10 22:19:30 +02:00
parent 8986cafc46
commit 5994a55ab9
4 changed files with 85 additions and 2 deletions
@@ -10,4 +10,5 @@ pci_read_arch_info(PCIDev *dev)
{
pci_read_msi_info(dev);
pci_read_msix_info(dev);
pci_read_ht_mapping_info(dev);
}
@@ -10,6 +10,7 @@
typedef struct pci_arch_info {
msi_info msi;
msix_info msix;
ht_mapping_info ht_mapping;
} pci_arch_info;
@@ -15,6 +15,60 @@
extern PCI *gPCI;
static void
pci_ht_msi_map(PCIDev *device, uint64 address)
{
ht_mapping_info *info = &device->arch_info.ht_mapping;
if (!info->ht_mapping_capable)
return;
bool enabled = (info->control_value & PCI_ht_command_msi_enable) != 0;
if ((address != 0) != enabled) {
if (enabled) {
info->control_value &= ~PCI_ht_command_msi_enable;
} else {
if ((address >> 20) != (info->address_value >> 20))
return;
dprintf("ht msi mapping enabled\n");
info->control_value |= PCI_ht_command_msi_enable;
}
gPCI->WriteConfig(device, info->capability_offset + PCI_ht_command,
info->control_value, 2);
}
}
void
pci_read_ht_mapping_info(PCIDev *device)
{
if (!msi_supported())
return;
ht_mapping_info *info = &device->arch_info.ht_mapping;
info->ht_mapping_capable = false;
uint8 offset = 0;
if (gPCI->FindHTCapability(device, PCI_ht_command_cap_msi_mapping,
&offset) == B_OK) {
info->control_value = gPCI->ReadConfig(device, offset + PCI_ht_command,
2);
info->capability_offset = offset;
info->ht_mapping_capable = true;
if ((info->control_value & PCI_ht_command_msi_fixed) != 0)
info->address_value = MSI_ADDRESS_BASE;
else {
info->address_value = gPCI->ReadConfig(device, offset
+ PCI_ht_msi_address_high, 4);
info->address_value <<= 32;
info->address_value |= gPCI->ReadConfig(device, offset
+ PCI_ht_msi_address_low, 4);
}
dprintf("found an ht msi mapping at %#" B_PRIx64 "\n",
info->address_value);
}
}
uint8
pci_get_msi_count(uint8 virtualBus, uint8 _device, uint8 function)
{
@@ -164,6 +218,9 @@ pci_enable_msi(uint8 virtualBus, uint8 _device, uint8 function)
gPCI->WriteConfig(device, info->capability_offset + PCI_msi_control, 2,
info->control_value);
// enable HT msi mapping (if applicable)
pci_ht_msi_map(device, info->address_value);
dprintf("msi enabled: 0x%04" B_PRIx32 "\n",
gPCI->ReadConfig(device, info->capability_offset + PCI_msi_control, 2));
return B_OK;
@@ -193,6 +250,9 @@ pci_disable_msi(uint8 virtualBus, uint8 _device, uint8 function)
if (info->configured_count == 0)
return B_NO_INIT;
// disable HT msi mapping (if applicable)
pci_ht_msi_map(device, 0);
// disable msi generation
info->control_value &= ~PCI_msi_control_enable;
gPCI->WriteConfig(device, info->capability_offset + PCI_msi_control, 2,
@@ -423,6 +483,9 @@ pci_enable_msix(uint8 virtualBus, uint8 _device, uint8 function)
gPCI->WriteConfig(device, info->capability_offset + PCI_msix_control, 2,
info->control_value);
// enable HT msi mapping (if applicable)
pci_ht_msi_map(device, info->address_value);
dprintf("msi-x enabled: 0x%04" B_PRIx32 "\n",
gPCI->ReadConfig(device, info->capability_offset + PCI_msix_control, 2));
return B_OK;
@@ -452,6 +515,9 @@ pci_disable_msix(uint8 virtualBus, uint8 _device, uint8 function)
if (info->configured_count == 0)
return B_NO_INIT;
// disable HT msi mapping (if applicable)
pci_ht_msi_map(device, 0);
// disable msi-x generation
info->control_value &= ~PCI_msix_control_enable;
gPCI->WriteConfig(device, info->capability_offset + PCI_msix_control, 2,
@@ -10,9 +10,12 @@
#include <SupportDefs.h>
// Message Signaled Interrupts
class PCIDev;
// Message Signaled Interrupts
// MSI
typedef struct msi_info {
bool msi_capable;
uint8 capability_offset;
@@ -34,7 +37,7 @@ status_t pci_disable_msi(uint8 virtualBus, uint8 device, uint8 function);
void pci_read_msi_info(PCIDev *device);
// Message Signaled Interrupts
// MSI-X
typedef struct msix_info {
bool msix_capable;
uint8 capability_offset;
@@ -63,4 +66,16 @@ status_t pci_enable_msix(uint8 virtualBus, uint8 _device, uint8 function);
status_t pci_disable_msix(uint8 virtualBus, uint8 _device, uint8 function);
void pci_read_msix_info(PCIDev *device);
// HyperTransport MSI mapping
typedef struct ht_mapping_info {
bool ht_mapping_capable;
uint8 capability_offset;
uint16 control_value;
uint64 address_value;
} ht_mapping_info;
void pci_read_ht_mapping_info(PCIDev *device);
#endif // _PCI_x86_MSI_H