Skip to content

Commit 8bdb902

Browse files
committed
kernel/dev: Fix legacy pci irq support
1 parent d9f7725 commit 8bdb902

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

src/dev/pci.cpp

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ namespace pci {
4343

4444
namespace {
4545
Mcfg* GLOBAL_MCFG = nullptr;
46+
kstd::pair<u32, u32> ALLOCATED_IRQS[4] {};
4647
}
4748

4849
void resume_from_suspend() {
@@ -359,21 +360,44 @@ namespace pci {
359360
}
360361
}
361362
else {
362-
u32 irq = x86_alloc_irq(1, flags & IrqFlags::Shared);
363-
assert(irq);
364-
365363
u8 irq_pin = read(hdr0::IRQ_PIN);
366364

367365
auto legacy_irq = acpi::get_legacy_pci_irq(addr.seg, addr.bus, addr.dev, irq_pin);
368366
assert(legacy_irq);
367+
legacy_no_free = true;
369368

370-
IoApicIrqInfo info {
371-
.delivery = IoApicDelivery::Fixed,
372-
.polarity = legacy_irq->active_high ? IoApicPolarity::ActiveHigh : IoApicPolarity::ActiveLow,
373-
.trigger = legacy_irq->edge_triggered ? IoApicTrigger::Edge : IoApicTrigger::Level,
374-
.vec = static_cast<u8>(irq)
375-
};
376-
IO_APIC.register_irq(legacy_irq->gsi, info);
369+
u32 irq = 0;
370+
for (auto [gsi, alloc_irq] : ALLOCATED_IRQS) {
371+
if (gsi == legacy_irq->gsi) {
372+
irq = alloc_irq;
373+
break;
374+
}
375+
}
376+
377+
if (irq == 0) {
378+
irq = x86_alloc_irq(1, flags & IrqFlags::Shared);
379+
assert(irq);
380+
381+
IoApicIrqInfo info {
382+
.delivery = IoApicDelivery::Fixed,
383+
.polarity = legacy_irq->active_high ? IoApicPolarity::ActiveHigh : IoApicPolarity::ActiveLow,
384+
.trigger = legacy_irq->edge_triggered ? IoApicTrigger::Edge : IoApicTrigger::Level,
385+
.vec = static_cast<u8>(irq)
386+
};
387+
IO_APIC.register_irq(legacy_irq->gsi, info);
388+
389+
bool allocated = false;
390+
for (auto& alloc : ALLOCATED_IRQS) {
391+
if (!alloc.second) {
392+
alloc.first = legacy_irq->gsi;
393+
alloc.second = irq;
394+
allocated = true;
395+
break;
396+
}
397+
}
398+
399+
assert(allocated);
400+
}
377401

378402
enable_legacy_irq(false);
379403
irqs[0] = irq;
@@ -383,9 +407,12 @@ namespace pci {
383407
}
384408

385409
void Device::free_irqs() {
386-
for (u32 i = 0; i < irqs.size(); ++i) {
387-
x86_dealloc_irq(i, 1, _flags & IrqFlags::Shared);
410+
if (!legacy_no_free) {
411+
for (u32 i = 0; i < irqs.size(); ++i) {
412+
x86_dealloc_irq(i, 1, _flags & IrqFlags::Shared);
413+
}
388414
}
415+
389416
irqs.clear();
390417
irqs.shrink_to_fit();
391418
}

src/dev/pci.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,5 +320,6 @@ namespace pci {
320320
u32 power_cap_offset;
321321
kstd::vector<u32> irqs;
322322
IrqFlags _flags {};
323+
bool legacy_no_free {};
323324
};
324325
}

0 commit comments

Comments
 (0)