mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
Enable AHCI interrupts.
* Implement MSI style interrupts * Move interrupt handling to device_manager for IRQs * Give device_manager the ability to allocate IRQs * Move achi::port to an interrupt-based scheme
This commit is contained in:
@@ -3,6 +3,28 @@
|
||||
#include "interrupts.h"
|
||||
#include "pci.h"
|
||||
|
||||
struct pci_cap_msi :
|
||||
public pci_cap
|
||||
{
|
||||
uint16_t control;
|
||||
uint64_t address;
|
||||
uint16_t data;
|
||||
uint16_t reserved;
|
||||
uint32_t mask;
|
||||
uint32_t pending;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct pci_cap_msix :
|
||||
public pci_cap
|
||||
{
|
||||
uint16_t control;
|
||||
uint64_t address;
|
||||
uint16_t data;
|
||||
uint16_t reserved;
|
||||
uint32_t mask;
|
||||
uint32_t pending;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
pci_device::pci_device() :
|
||||
m_base(nullptr),
|
||||
@@ -20,6 +42,7 @@ pci_device::pci_device() :
|
||||
|
||||
pci_device::pci_device(pci_group &group, uint8_t bus, uint8_t device, uint8_t func) :
|
||||
m_base(group.base_for(bus, device, func)),
|
||||
m_msi(nullptr),
|
||||
m_bus_addr(bus_addr(bus, device, func)),
|
||||
m_irq(isr::isrIgnoreF)
|
||||
{
|
||||
@@ -34,8 +57,24 @@ pci_device::pci_device(pci_group &group, uint8_t bus, uint8_t device, uint8_t fu
|
||||
m_header_type = (m_base[3] >> 16) & 0x7f;
|
||||
m_multi = ((m_base[3] >> 16) & 0x80) == 0x80;
|
||||
|
||||
uint16_t *command = reinterpret_cast<uint16_t *>(&m_base[1]);
|
||||
*command |= 0x400; // Mask old INTx style interrupts
|
||||
|
||||
log::info(logs::device, "Found PCIe device at %02d:%02d:%d of type %d.%d id %04x:%04x",
|
||||
bus, device, func, m_class, m_subclass, m_vendor, m_device);
|
||||
|
||||
// Walk the extended capabilities list
|
||||
uint8_t next = m_base[13] & 0xff;
|
||||
while (next) {
|
||||
pci_cap *cap = reinterpret_cast<pci_cap *>(kutil::offset_pointer(m_base, next));
|
||||
next = cap->next;
|
||||
|
||||
if (cap->id == pci_cap::type::msi) {
|
||||
m_msi = cap;
|
||||
pci_cap_msi *mcap = reinterpret_cast<pci_cap_msi *>(cap);
|
||||
mcap->control |= ~0x1; // Mask interrupts
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -66,6 +105,19 @@ pci_device::set_bar(unsigned i, uint32_t val)
|
||||
m_base[4+i] = val;
|
||||
}
|
||||
|
||||
void
|
||||
pci_device::write_msi_regs(addr_t address, uint16_t data)
|
||||
{
|
||||
kassert(m_msi, "Tried to write MSI for a device without that cap");
|
||||
if (m_msi->id == pci_cap::type::msi) {
|
||||
pci_cap_msi *mcap = reinterpret_cast<pci_cap_msi *>(m_msi);
|
||||
mcap->address = address;
|
||||
mcap->data = data;
|
||||
mcap->control |= 1;
|
||||
} else {
|
||||
kassert(0, "MIS-X is NYI");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
pci_group::has_device(uint8_t bus, uint8_t device, uint8_t func)
|
||||
|
||||
Reference in New Issue
Block a user