示例#1
0
文件: pit.c 项目: BwRy/seL4_libs
seL4_timer_t *
sel4platsupport_get_pit(vka_t *vka, simple_t *simple, ps_io_port_ops_t *ops, seL4_CPtr notification)
{

    seL4_pit_data_t *data = malloc(sizeof(seL4_pit_data_t));
    if (data == NULL) {
        ZF_LOGE("Failed to allocate object of size %zu\n", sizeof(*data));
        goto error;
    }


    seL4_timer_t *pit = calloc(1, sizeof(*pit));
    if (pit == NULL) {
        ZF_LOGE("Failed to malloc object of size %zu\n", sizeof(*pit));
        goto error;
    }
    
    pit->destroy = pit_destroyer;
    pit->handle_irq = pit_handle_irq;
    pit->data = data;

    /* set up irq */
    cspacepath_t dest;
    if (sel4platsupport_copy_irq_cap(vka, simple, PIT_INTERRUPT, &dest) != seL4_NoError) {
        goto error;
    }
    data->irq = dest.capPtr;

    /* bind to endpoint */
    if (seL4_IRQHandler_SetNotification(data->irq, notification) != seL4_NoError) {
        ZF_LOGE("seL4_IRQHandler_SetEndpoint failed\n");
        goto error;
    }

    /* ack (api hack) */
    seL4_IRQHandler_Ack(data->irq);

    /* finally set up the actual timer */
    pit->timer = pit_get_timer(ops);
    if (pit->timer == NULL) {
        goto error;
    }

    /* sucess */
    return pit;

error:
    if (data != NULL) {
        free(data);
    }
    if (data->irq != 0) {
        timer_common_cleanup_irq(vka, data->irq);
    }

    return NULL;
}
示例#2
0
文件: device_irq.c 项目: seL4/refos
int dev_handle_irq(dev_irq_state_t *irqState, uint32_t irq,
                   dev_irq_callback_fn_t callback, void *cookie)
{
    assert(irqState && irqState->magic == DEVICE_IRQ_MAGIC);

    if (irq >= DEVICE_MAX_IRQ) {
        ROS_ERROR("dev_handle_irq IRQ num too high. Try raising DEVICE_MAX_IRQ.");
        assert(!"Try raising DEVICE_MAX_IRQ.");
        return EINVALIDPARAM;
    }

    /* Retrieve the handler, if necessary. */
    if (!irqState->handler[irq].handler) {
        assert(irqState->cfg.getIRQHandlerEndpoint);
        irqState->handler[irq].handler = irqState->cfg.getIRQHandlerEndpoint(
            irqState->cfg.getIRQHandlerEndpointCookie, irq
        );
        if (!irqState->handler[irq].handler) {
            ROS_WARNING("dev_handle_irq : could not get IRQ handler for irq %u.\n", irq);
            return EINVALID;
        }
    }

    /* Determine next round-robin channel to go in. */
    uint32_t nextChannel = irqState->cfg.badgeBaseBit + irqState->nextIRQChannel;
    cvector_add(&irqState->channel[irqState->nextIRQChannel], (cvector_item_t) irq);
    irqState->nextIRQChannel = (irqState->nextIRQChannel + 1) % irqState->cfg.numIRQChannels;

    /* Mint the badged AEP. */
    assert(irqState->cfg.notifyAsyncEP);
    seL4_CPtr irqBadge = srv_mint((1 << nextChannel) | irqState->cfg.badgeMaskBits,
                                  irqState->cfg.notifyAsyncEP);
    if (!irqBadge) {
        ROS_WARNING("dev_handle_irq : could not mint badged aep for irq %u.\n", irq);
        return EINVALID;
    }

    /* Assign AEP to the IRQ handler. */
    int error = seL4_IRQHandler_SetNotification(irqState->handler[irq].handler, irqBadge);
    if (error) {
        ROS_WARNING("dev_handle_irq : could not set notify aep for irq %u.\n", irq);
        csfree_delete(irqBadge);
        return EINVALID;
    }
    seL4_IRQHandler_Ack(irqState->handler[irq].handler);

    /* Set callback function and cookie. */
    irqState->handler[irq].callback = callback;
    irqState->handler[irq].cookie = cookie;

    csfree_delete(irqBadge);
    return ESUCCESS;
}
示例#3
0
/* Binds and IRQ to an endpoint */
static seL4_CPtr
irq_bind(irq_t irq, seL4_CPtr notification_cap, int idx, vka_t* vka, simple_t *simple)
{
    seL4_CPtr irq_cap, bnotification_cap;
    cspacepath_t irq_path, notification_path, bnotification_path;
    seL4_CapData_t badge;
    int err;

    /* Create an IRQ cap */
    err = vka_cspace_alloc(vka, &irq_cap);
    if (err != 0) {
        ZF_LOGE("Failed to allocate cslot for irq\n");
        return seL4_CapNull;
    }
    vka_cspace_make_path(vka, irq_cap, &irq_path);
    err = simple_get_IRQ_control(simple, irq, irq_path);
    if (err != seL4_NoError) {
        ZF_LOGE("Failed to get cap to irq_number %d\n", irq);
        vka_cspace_free(vka, irq_cap);
        return seL4_CapNull;
    }
    /* Badge the provided endpoint. The bit position of the badge tells us the array
     * index of the associated IRQ data. */
    err = vka_cspace_alloc(vka, &bnotification_cap);
    if (err != 0) {
        ZF_LOGE("Failed to allocate cslot for irq\n");
        vka_cspace_free(vka, irq_cap);
        return seL4_CapNull;
    }
    vka_cspace_make_path(vka, notification_cap, &notification_path);
    vka_cspace_make_path(vka, bnotification_cap, &bnotification_path);
    badge = seL4_CapData_Badge_new(BIT(idx));
    err = vka_cnode_mint(&bnotification_path, &notification_path, seL4_AllRights, badge);
    if (err != seL4_NoError) {
        ZF_LOGE("Failed to badge IRQ notification endpoint\n");
        vka_cspace_free(vka, irq_cap);
        vka_cspace_free(vka, bnotification_cap);
        return seL4_CapNull;
    }
    /* bind the IRQ cap to our badged endpoint */
    err = seL4_IRQHandler_SetNotification(irq_cap, bnotification_cap);
    if (err != seL4_NoError) {
        ZF_LOGE("Failed to bind IRQ handler to notification\n");
        vka_cspace_free(vka, irq_cap);
        vka_cspace_free(vka, bnotification_cap);
        return seL4_CapNull;
    }
    /* Finally ACK any pending IRQ and enable the IRQ */
    seL4_IRQHandler_Ack(irq_cap);

    DIRQSERVER("Registered IRQ %d with badge 0x%lx\n", irq, BIT(idx));
    return irq_cap;
}
示例#4
0
文件: pit.c 项目: seL4/seL4_libs
seL4_timer_t *
sel4platsupport_get_pit(vka_t *vka, simple_t *simple, ps_io_port_ops_t *ops, seL4_CPtr notification)
{
    seL4_timer_t *pit = calloc(1, sizeof(*pit));
    if (pit == NULL) {
        ZF_LOGE("Failed to malloc object of size %zu\n", sizeof(*pit));
        return NULL;
    }

    /* initialise an io port ops interface if none was provided */
    if (ops == NULL) {
        ops = calloc(1, sizeof(*ops));

        if (ops == NULL) {
            ZF_LOGE("Failed to malloc object of size %zu", sizeof(*ops));
            goto error;
        }

        /* store ops pointer in pit so it can be freed later */
        pit->data = ops;

        if (sel4platsupport_get_io_port_ops(ops, simple) != 0) {
            ZF_LOGE("Failed to initialise io port ops");
            goto error;
        }
    } else {
        pit->data = NULL;
    }

    pit->destroy = pit_destroyer;
    pit->handle_irq = timer_common_handle_irq;

    /* set up irq */
    cspacepath_t dest;
    if (sel4platsupport_copy_irq_cap(vka, simple, PIT_INTERRUPT, &dest) != seL4_NoError) {
        goto error;
    }
    pit->irq = dest.capPtr;

    /* bind to endpoint */
    if (seL4_IRQHandler_SetNotification(pit->irq, notification) != seL4_NoError) {
        ZF_LOGE("seL4_IRQHandler_SetEndpoint failed\n");
        goto error;
    }

    /* ack (api hack) */
    seL4_IRQHandler_Ack(pit->irq);

    /* finally set up the actual timer */
    pit->timer = pit_get_timer(ops);
    if (pit->timer == NULL) {
        goto error;
    }

    /* sucess */
    return pit;

error:
    if (pit->irq != 0) {
        timer_common_cleanup_irq(vka, pit->irq);
        free(pit->data);
        free(pit);
    }

    return NULL;
}