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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user