Ejemplo n.º 1
0
static int
ps3pic_attach(device_t dev)
{
	struct ps3pic_softc *sc;
	uint64_t ppe;
	int thread;

	sc = device_get_softc(dev);

	sc->bitmap_thread0 = contigmalloc(128 /* 512 bits * 2 */, M_PS3PIC,
	    M_NOWAIT | M_ZERO, 0, BUS_SPACE_MAXADDR, 64 /* alignment */,
	    PAGE_SIZE /* boundary */);
	sc->mask_thread0 = sc->bitmap_thread0 + 4;
	sc->bitmap_thread1 = sc->bitmap_thread0 + 8;
	sc->mask_thread1 = sc->bitmap_thread0 + 12;

	lv1_get_logical_ppe_id(&ppe);
	thread = 32 - fls(mfctrl());
	lv1_configure_irq_state_bitmap(ppe, thread,
	    vtophys(sc->bitmap_thread0));
#ifdef SMP
	lv1_configure_irq_state_bitmap(ppe, !thread,
	    vtophys(sc->bitmap_thread1));

	/* Map both IPIs to the same VIRQ to avoid changes in intr_machdep */
	lv1_construct_event_receive_port(&sc->sc_ipi_outlet[0]);
	lv1_connect_irq_plug_ext(ppe, thread, sc->sc_ipi_outlet[0],
	    sc->sc_ipi_outlet[0], 0);
	lv1_construct_event_receive_port(&sc->sc_ipi_outlet[1]);
	lv1_connect_irq_plug_ext(ppe, !thread, sc->sc_ipi_outlet[0],
	    sc->sc_ipi_outlet[1], 0);
#endif

	powerpc_register_pic(dev, 0, sc->sc_ipi_outlet[0], 1, FALSE);
	return (0);
}
Ejemplo n.º 2
0
int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq)
{
	int result;
	u64 outlet;

	result = lv1_construct_event_receive_port(&outlet);

	if (result) {
		pr_debug("%s:%d: lv1_construct_event_receive_port failed: %s\n",
			__func__, __LINE__, ps3_result(result));
		*virq = NO_IRQ;
		return result;
	}

	result = ps3_irq_plug_setup(cpu, outlet, virq);
	BUG_ON(result);

	return result;
}
Ejemplo n.º 3
0
int ps3_alloc_event_irq(unsigned int *virq)
{
	int result;
	unsigned long outlet;

	result = lv1_construct_event_receive_port(&outlet);

	if (result) {
		pr_debug("%s:%d: lv1_construct_event_receive_port failed: %s\n",
			__func__, __LINE__, ps3_result(result));
		*virq = NO_IRQ;
		return result;
	}

	*virq = irq_create_mapping(NULL, outlet);

	pr_debug("%s:%d: outlet %lu, virq %u\n", __func__, __LINE__, outlet,
		*virq);

	return 0;
}
Ejemplo n.º 4
0
static void
ps3bus_resources_init(struct rman *rm, int bus_index, int dev_index,
    struct ps3bus_devinfo *dinfo)
{
	uint64_t irq_type, irq, outlet;
	uint64_t reg_type, paddr, len;
	uint64_t ppe, junk;
	int i, result;
	int thread;

	resource_list_init(&dinfo->resources);

	lv1_get_logical_ppe_id(&ppe);
	thread = 32 - fls(mfctrl());

	/* Scan for interrupts */
	for (i = 0; i < 10; i++) {
		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
		    (lv1_repository_string("bus") >> 32) | bus_index,
		    lv1_repository_string("dev") | dev_index,
		    lv1_repository_string("intr") | i, 0, &irq_type, &irq);

		if (result != 0)
			break;

		switch (irq_type) {
		case SB_IRQ:
			lv1_construct_event_receive_port(&outlet);
			lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
			    0);
			lv1_connect_interrupt_event_receive_port(dinfo->bus,
			    dinfo->dev, outlet, irq);
			break;
		case OHCI_IRQ:
		case EHCI_IRQ:
			lv1_construct_io_irq_outlet(irq, &outlet);
			lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
			    0);
			break;
		default:
			printf("Unknown IRQ type %ld for device %d.%d\n",
			    irq_type, dinfo->bus, dinfo->dev);
			break;
		}

		resource_list_add(&dinfo->resources, SYS_RES_IRQ, i,
		    outlet, outlet, 1);
	}

	/* Scan for registers */
	for (i = 0; i < 10; i++) {
		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
		    (lv1_repository_string("bus") >> 32) | bus_index,
		    lv1_repository_string("dev") | dev_index,
		    lv1_repository_string("reg") | i, 
		    lv1_repository_string("type"), &reg_type, &junk);

		if (result != 0)
			break;

		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
		    (lv1_repository_string("bus") >> 32) | bus_index,
		    lv1_repository_string("dev") | dev_index,
		    lv1_repository_string("reg") | i, 
		    lv1_repository_string("data"), &paddr, &len);

		result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev,
		    paddr, len, 12 /* log_2(4 KB) */, &paddr);

		if (result != 0) {
			printf("Mapping registers failed for device "
			    "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev,
			    dinfo->bustype, dinfo->devtype, result);
			continue;
		}

		rman_manage_region(rm, paddr, paddr + len - 1);
		resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i,
		    paddr, paddr + len, len);
	}
}