/** * \brief globally enables the interrupts for the given device * * \param dev IOAT DMA device * \param type the interrupt type to enable */ errval_t ioat_dma_device_irq_setup(struct ioat_dma_device *dev, dma_irq_t type) { errval_t err; ioat_dma_intrctrl_t intcrtl = 0; intcrtl = ioat_dma_intrctrl_intp_en_insert(intcrtl, 1); dev->common.irq_type = type; switch (type) { case DMA_IRQ_MSIX: /* The number of MSI-X vectors should equal the number of channels */ IOATDEV_DEBUG("MSI-X interrupt setup for device (%u, %u, %u)\n", dev->common.id, dev->pci_addr.bus, dev->pci_addr.device, dev->pci_addr.function); err = pci_msix_enable_addr(&dev->pci_addr, &dev->irq_msix_count); if (err_is_fail(err)) { return err; } assert(dev->irq_msix_count > 0); IOATDEV_DEBUG("MSI-X enabled #vecs=%d\n", dev->common.id, dev->irq_msix_count); err = pci_setup_inthandler(ioat_dma_device_irq_handler, dev, &dev->irq_msix_vector); assert(err_is_ok(err)); uint8_t dest = get_local_apic_id(); IOATDEV_DEBUG("MSI-X routing to apic=%u\n", dev->common.id, dest); err = pci_msix_vector_init_addr(&dev->pci_addr, 0, dest, dev->irq_msix_vector); assert(err_is_ok(err)); /* enable the interrupts */ intcrtl = ioat_dma_intrctrl_msix_vec_insert(intcrtl, 1); intcrtl = ioat_dma_intrctrl_intp_en_insert(intcrtl, 1); break; case DMA_IRQ_MSI: IOATDEV_DEBUG("Initializing MSI interrupts \n", dev->common.id); assert(!"NYI"); break; case DMA_IRQ_INTX: IOATDEV_DEBUG("Initializing INTx interrupts \n", dev->common.id); assert(!"NYI"); break; default: /* disabled */ intcrtl = 0; IOATDEV_DEBUG("Disabling interrupts \n", dev->common.id); break; } ioat_dma_intrctrl_wr(&dev->device, intcrtl); #if IOAT_DEBUG_INTR_ENABLED /* * check if interrupts are working. */ msix_intr_happened = 0; struct ioat_dma_channel *chan; chan = (struct ioat_dma_channel *)dev->common.channels.c[0]; ioat_dma_request_nop_chan(chan); err = ioat_dma_channel_issue_pending(chan); if (err_is_fail(err)) { return err; } while(msix_intr_happened == 0) { uint64_t status = ioat_dma_channel_get_status(chan); err = event_dispatch_non_block(get_default_waitset()); if (!ioat_dma_channel_is_active(status) && !ioat_dma_channel_is_idle(status)) { USER_PANIC("DMA request turned channel into erroneous state.") } switch(err_no(err)) { case LIB_ERR_NO_EVENT: thread_yield(); break; case SYS_ERR_OK: continue; default: USER_PANIC_ERR(err, "dispatching event"); } } #endif return SYS_ERR_OK; }
static int __local_apic_init(bool msgout) { uint32_t v; int i=0,l; apic_lvt_lint_t lvt_lint; apic_icr1_t icr1; if (msgout) { kprintf("APIC: Checking APIC is present ... "); if(__local_apic_check()<0) { kprintf("FAIL\n"); return -1; } else{ kprintf("OK\n"); } } enable_l_apic_in_msr(); v=get_apic_version(); if (msgout) kprintf("APIC: APIC version: %d apic id:%x\n",v,get_local_apic_id()); /* first we're need to clear APIC to avoid magical results */ __local_apic_clear(); __disable_apic(); set_apic_dfr_mode(0xf); kprintf(" APIC id:%d destination id :%d \n",get_local_apic_id(),(1 << (__apics_number & 7))); set_apic_ldr_logdest(1 << (__apics_number & 7)); __apics_number++; apic_set_task_priority(0); /* clear bits for interrupts - can be filled up to other os */ for(i=7;i>=0;i--){ v=local_apic->isr[i].bits; for(l=31;l>=0;l--) if(v & (1 << l)) local_apic_send_eoi(); } set_apic_spurious_vector(0xff); __enable_apic(); /* set nil vectors */ __set_lvt_lint_vector(0,0x34); __set_lvt_lint_vector(1,0x35); /*set mode#7 extINT for lint0*/ lvt_lint=local_apic->lvt_lint0; lvt_lint.tx_mode=0x7; lvt_lint.mask=1; lvt_lint.tx_status = 0x0; lvt_lint.polarity = LEVEL_DEASSERT; lvt_lint.trigger = TRIG_EDGE; local_apic->lvt_lint0.reg=lvt_lint.reg; /*set mode#4 NMI for lint1*/ lvt_lint=local_apic->lvt_lint1; lvt_lint.tx_mode=0x4; lvt_lint.mask=1; lvt_lint.tx_status = 0x0; lvt_lint.polarity = LEVEL_DEASSERT; lvt_lint.trigger = TRIG_EDGE; local_apic->lvt_lint1.reg=lvt_lint.reg; /* ok, now we're need to set esr vector to 0xfe */ local_apic->lvt_error.vector = 0xfe; /*enable to receive errors*/ if(__get_maxlvt()>3) local_apic->esr.tx_cs_err = 0x0; /* set icr1 registers*/ icr1=local_apic->icr1; icr1.tx_mode=TXMODE_INIT; icr1.rx_mode=DMODE_PHY; icr1.level=0x0; icr1.shorthand=0x2; icr1.trigger=0x1; local_apic->icr1.reg=icr1.reg; // set internal apic error interrupt vector *(uint32_t*)((uint64_t)local_apic + 0x370) = 200; return 0; }