예제 #1
0
파일: vbus.c 프로젝트: ajinkya93/OpenBSD
int
vbus_intr_map(int node, int ino, uint64_t *sysino)
{
	int *imap = NULL, nimap;
	int *reg = NULL, nreg;
	int *imap_mask;
	int parent;
	int address_cells, interrupt_cells;
	uint64_t devhandle;
	uint64_t devino;
	int len;
	int err;

	parent = OF_parent(node);

	address_cells = getpropint(parent, "#address-cells", 2);
	interrupt_cells = getpropint(parent, "#interrupt-cells", 1);
	KASSERT(interrupt_cells == 1);

	len = OF_getproplen(parent, "interrupt-map-mask");
	if (len < (address_cells + interrupt_cells) * sizeof(int))
		return (-1);
	imap_mask = malloc(len, M_DEVBUF, M_NOWAIT);
	if (imap_mask == NULL)
		return (-1);
	if (OF_getprop(parent, "interrupt-map-mask", imap_mask, len) != len)
		return (-1);

	getprop(parent, "interrupt-map", sizeof(int), &nimap, (void **)&imap);
	getprop(node, "reg", sizeof(*reg), &nreg, (void **)&reg);
	if (nreg < address_cells)
		return (-1);

	while (nimap >= address_cells + interrupt_cells + 2) {
		if (vbus_cmp_cells(imap, reg, imap_mask, address_cells) &&
		    vbus_cmp_cells(&imap[address_cells], &ino,
		    &imap_mask[address_cells], interrupt_cells)) {
			node = imap[address_cells + interrupt_cells];
			devino = imap[address_cells + interrupt_cells + 1];

			free(reg, M_DEVBUF, 0);
			reg = NULL;

			getprop(node, "reg", sizeof(*reg), &nreg, (void **)&reg);
			devhandle = reg[0] & 0x0fffffff;

			err = hv_intr_devino_to_sysino(devhandle, devino, sysino);
			if (err != H_EOK)
				return (-1);

			KASSERT(*sysino == INTVEC(*sysino));
			return (0);
		}
		imap += address_cells + interrupt_cells + 2;
		nimap -= address_cells + interrupt_cells + 2;
	}

	return (-1);
}
예제 #2
0
static int
vnex_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
                driver_filter_t *filt,driver_intr_t *intr, void *arg, void **cookiep)
{

    uint64_t reg, nreg;
    uint64_t ihdl, cfg;
    uint64_t ino, nino;
    int error, cpuid;

    if (res == NULL)
        panic("%s: NULL interrupt resource!", __func__);

    if ((error = bus_get_resource(dev, SYS_RES_MEMORY, 0, &reg, &nreg)))
        goto fail;

    if ((error = bus_get_resource(child, SYS_RES_IRQ, 0, &ino, &nino)))
        goto fail;

    cfg = SUN4V_REG_SPEC2CFG_HDL(reg);

    if (hv_intr_devino_to_sysino(cfg, (uint32_t)ino, &ihdl) != H_EOK) {
        error = ENXIO;
        goto fail;
    }

    cpuid = 0;

    if (hv_intr_settarget(ihdl, cpuid) != H_EOK) {
        error = ENXIO;
        goto fail;
    }

    if (hv_intr_setstate(ihdl, HV_INTR_IDLE_STATE) != H_EOK) {
        error = ENXIO;
        goto fail;
    }

    if (hv_intr_setenabled(ihdl, HV_INTR_ENABLED) != H_EOK) {
        error = ENXIO;
        goto fail;
    }

    if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
        flags |= INTR_EXCL;

    /* We depend here on rman_activate_resource() being idempotent. */
    if ((error = rman_activate_resource(res)))
        goto fail;

    error = inthand_add(device_get_nameunit(child), ihdl,
                        filt, intr, arg, flags, cookiep);

    printf("inthandler added\n");
fail:

    return (error);
}