Ejemplo n.º 1
0
/**
 * \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;
}
Ejemplo n.º 2
0
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;
}