-
Notifications
You must be signed in to change notification settings - Fork 392
Expand file tree
/
Copy pathpci_msi.cpp
More file actions
70 lines (63 loc) · 2.3 KB
/
Copy pathpci_msi.cpp
File metadata and controls
70 lines (63 loc) · 2.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <hw/pci_device.hpp>
#include <hw/pci.hpp>
#include <hw/msi.hpp>
// Message Signalled Interrupts registers
#define PCI_MSI_FLAGS_ENABLE 0x0001 /* MSI feature enabled */
#define PCI_MSI_FLAGS_QMASK 0x000e /* Maximum queue size available */
#define PCI_MSI_FLAGS_QSIZE 0x0070 /* Message queue size configured */
#define PCI_MSI_FLAGS_64BIT 0x0080 /* 64-bit addresses allowed */
#define PCI_MSI_FLAGS_MASKBIT 0x0100 /* Per-vector masking capable */
#define PCI_MSI_FLAGS 2 /* Message Control */
#define PCI_MSI_RFU 3 /* Rest of capability flags */
#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
#define PCI_MSI_MASK_32 12 /* Mask bits register for 32-bit devices */
#define PCI_MSI_PENDING_32 16 /* Pending intrs for 32-bit devices */
#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
#define PCI_MSI_MASK_64 16 /* Mask bits register for 64-bit devices */
#define PCI_MSI_PENDING_64 20 /* Pending intrs for 64-bit devices */
namespace hw
{
int PCI_Device::msi_cap()
{
return caps[static_cast<size_t>(PCI::cap_id::MSI)];
}
int PCI_Device::msix_cap()
{
return caps[static_cast<size_t>(PCI::cap_id::MSIX)];
}
void PCI_Device::init_msix()
{
assert(this->msix == nullptr);
// disable intx
auto cmd = read16(static_cast<uint8_t>(PCI::config_reg::CMD));
write16(static_cast<uint8_t>(PCI::config_reg::CMD), cmd | (1 << 10));
// enable MSI-X
this->msix = new msix_t(*this, msix_cap());
// deallocate if it failed
if (this->msix->vectors() == 0) {
delete this->msix;
}
}
int PCI_Device::setup_msix_vector(uint8_t cpu, uint8_t irq)
{
return msix->setup_vector(cpu, irq);
}
void PCI_Device::rebalance_msix_vector(uint16_t idx, uint8_t cpu, uint8_t irq)
{
msix->redirect_vector(idx, cpu, irq);
}
void PCI_Device::deactivate_msix()
{
for (size_t ent = 0; ent < msix->vectors(); ent++) {
msix->mask_entry(ent);
msix->zero_entry(ent);
}
}
uint8_t PCI_Device::get_msix_vectors()
{
if (this->msix == nullptr) return 0;
return msix->vectors();
}
}