@@ -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 }
0 commit comments