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_msi_info(dev);
|
||||||
pci_read_msix_info(dev);
|
pci_read_msix_info(dev);
|
||||||
|
pci_read_ht_mapping_info(dev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
typedef struct pci_arch_info {
|
typedef struct pci_arch_info {
|
||||||
msi_info msi;
|
msi_info msi;
|
||||||
msix_info msix;
|
msix_info msix;
|
||||||
|
ht_mapping_info ht_mapping;
|
||||||
} pci_arch_info;
|
} pci_arch_info;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,60 @@
|
|||||||
extern PCI *gPCI;
|
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
|
uint8
|
||||||
pci_get_msi_count(uint8 virtualBus, uint8 _device, uint8 function)
|
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,
|
gPCI->WriteConfig(device, info->capability_offset + PCI_msi_control, 2,
|
||||||
info->control_value);
|
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",
|
dprintf("msi enabled: 0x%04" B_PRIx32 "\n",
|
||||||
gPCI->ReadConfig(device, info->capability_offset + PCI_msi_control, 2));
|
gPCI->ReadConfig(device, info->capability_offset + PCI_msi_control, 2));
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -193,6 +250,9 @@ pci_disable_msi(uint8 virtualBus, uint8 _device, uint8 function)
|
|||||||
if (info->configured_count == 0)
|
if (info->configured_count == 0)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
// disable HT msi mapping (if applicable)
|
||||||
|
pci_ht_msi_map(device, 0);
|
||||||
|
|
||||||
// disable msi generation
|
// disable msi generation
|
||||||
info->control_value &= ~PCI_msi_control_enable;
|
info->control_value &= ~PCI_msi_control_enable;
|
||||||
gPCI->WriteConfig(device, info->capability_offset + PCI_msi_control, 2,
|
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,
|
gPCI->WriteConfig(device, info->capability_offset + PCI_msix_control, 2,
|
||||||
info->control_value);
|
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",
|
dprintf("msi-x enabled: 0x%04" B_PRIx32 "\n",
|
||||||
gPCI->ReadConfig(device, info->capability_offset + PCI_msix_control, 2));
|
gPCI->ReadConfig(device, info->capability_offset + PCI_msix_control, 2));
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -452,6 +515,9 @@ pci_disable_msix(uint8 virtualBus, uint8 _device, uint8 function)
|
|||||||
if (info->configured_count == 0)
|
if (info->configured_count == 0)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
// disable HT msi mapping (if applicable)
|
||||||
|
pci_ht_msi_map(device, 0);
|
||||||
|
|
||||||
// disable msi-x generation
|
// disable msi-x generation
|
||||||
info->control_value &= ~PCI_msix_control_enable;
|
info->control_value &= ~PCI_msix_control_enable;
|
||||||
gPCI->WriteConfig(device, info->capability_offset + PCI_msix_control, 2,
|
gPCI->WriteConfig(device, info->capability_offset + PCI_msix_control, 2,
|
||||||
|
|||||||
@@ -10,9 +10,12 @@
|
|||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Message Signaled Interrupts
|
||||||
|
|
||||||
|
|
||||||
class PCIDev;
|
class PCIDev;
|
||||||
|
|
||||||
// Message Signaled Interrupts
|
// MSI
|
||||||
typedef struct msi_info {
|
typedef struct msi_info {
|
||||||
bool msi_capable;
|
bool msi_capable;
|
||||||
uint8 capability_offset;
|
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);
|
void pci_read_msi_info(PCIDev *device);
|
||||||
|
|
||||||
|
|
||||||
// Message Signaled Interrupts
|
// MSI-X
|
||||||
typedef struct msix_info {
|
typedef struct msix_info {
|
||||||
bool msix_capable;
|
bool msix_capable;
|
||||||
uint8 capability_offset;
|
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);
|
status_t pci_disable_msix(uint8 virtualBus, uint8 _device, uint8 function);
|
||||||
void pci_read_msix_info(PCIDev *device);
|
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
|
#endif // _PCI_x86_MSI_H
|
||||||
|
|||||||
Reference in New Issue
Block a user