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); }
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; }
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; }
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"), ®_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); } }