static void get_ncpus(void) { #ifdef MULTIPROCESSOR int node, l; char sbuf[32]; node = findroot(); sparc_ncpus = 0; for (node = OF_child(node); node; node = OF_peer(node)) { if (OF_getprop(node, "device_type", sbuf, sizeof(sbuf)) <= 0) continue; if (strcmp(sbuf, "cpu") != 0) continue; sparc_ncpus++; l = prom_getpropint(node, "dcache-line-size", 0); if (l > dcache_line_size) dcache_line_size = l; l = prom_getpropint(node, "icache-line-size", 0); if (l > icache_line_size) icache_line_size = l; } #else /* #define sparc_ncpus 1 */ icache_line_size = dcache_line_size = 8; /* will be fixed later */ #endif }
/* * Get the number of CPUs in the system and the CPUs' SPARC architecture * version. We need this information early in the boot process. */ int find_cpus(void) { int n; #if defined(SUN4M) || defined(SUN4D) int node; #endif /* * Set default processor architecture version * * All sun4 and sun4c platforms have v7 CPUs; * sun4m may have v7 (Cyrus CY7C601 modules) or v8 CPUs (all * other models, presumably). */ cpu_arch = 7; /* On sun4 and sun4c we support only one CPU */ if (!CPU_ISSUN4M && !CPU_ISSUN4D) return (1); n = 0; #if defined(SUN4M) node = findroot(); for (node = firstchild(node); node; node = nextsibling(node)) { if (strcmp(prom_getpropstring(node, "device_type"), "cpu") != 0) continue; if (n++ == 0) cpu_arch = prom_getpropint(node, "sparc-version", 7); } #endif /* SUN4M */ #if defined(SUN4D) node = findroot(); for (node = firstchild(node); node; node = nextsibling(node)) { int unode; if (strcmp(prom_getpropstring(node, "name"), "cpu-unit") != 0) continue; for (unode = firstchild(node); unode; unode = nextsibling(unode)) { if (strcmp(prom_getpropstring(unode, "device_type"), "cpu") != 0) continue; if (n++ == 0) cpu_arch = prom_getpropint(unode, "sparc-version", 7); } } #endif return (n); }
static void cpuunit_attach(device_t parent, device_t self, void *aux) { struct cpuunit_softc *sc = device_private(self); struct mainbus_attach_args *ma = aux; int node, error; bus_space_tag_t sbt; sc->sc_node = ma->ma_node; sc->sc_st = ma->ma_bustag; sc->sc_device_id = prom_getpropint(sc->sc_node, "device-id", -1); sc->sc_board = prom_getpropint(sc->sc_node, "board#", -1); printf(": board #%d, ID %d\n", sc->sc_board, sc->sc_device_id); /* * Initialize the bus space tag we pass on to our children. */ sbt = sc->sc_bustag = malloc(sizeof(*sbt), M_DEVBUF, M_WAITOK); memcpy(sbt, sc->sc_st, sizeof(*sbt)); sbt->cookie = sc; sbt->parent = sc->sc_st; sbt->nranges = 0; sbt->ranges = NULL; /* * Collect address translations from the OBP. */ error = prom_getprop(sc->sc_node, "ranges", sizeof(struct openprom_range), &sbt->nranges, &sbt->ranges); if (error) { printf("%s: error %d getting \"ranges\" property\n", device_xname(self), error); panic("cpuunit_attach"); } /* Attach the CPU (and possibly bootbus) child nodes. */ for (node = firstchild(sc->sc_node); node != 0; node = nextsibling(node)) { struct cpuunit_attach_args cpua; if (cpuunit_setup_attach_args(sc, sbt, node, &cpua)) panic("cpuunit_attach: failed to set up attach args"); (void) config_found(self, &cpua, cpuunit_print); cpuunit_destroy_attach_args(&cpua); } }
/* * Match a graphics device. */ static int genfb_match_sbus(device_t parent, cfdata_t cf, void *aux) { struct sbus_attach_args *sa = aux; /* if there's no address property we can't use the device */ if (prom_getpropint(sa->sa_node, "address", -1) == -1) return 0; if (strcmp("display", prom_getpropstring(sa->sa_node, "device_type")) == 0) return 1; return 0; }
/* * Attach the CPU. * Discover interesting goop about the virtual address cache * (slightly funny place to do it, but this is where it is to be found). */ void cpu_attach(device_t parent, device_t dev, void *aux) { int node; long clk, sclk = 0; struct mainbus_attach_args *ma = aux; struct cpu_info *ci; const char *sep; register int i, l; int bigcache, cachesize; char buf[100]; int totalsize = 0; int linesize, dcachesize, icachesize; /* tell them what we have */ node = ma->ma_node; /* * Allocate cpu_info structure if needed. */ ci = alloc_cpuinfo((u_int)node); /* * Only do this on the boot cpu. Other cpu's call * cpu_reset_fpustate() from cpu_hatch() before they * call into the idle loop. * For other cpus, we need to call mi_cpu_attach() * and complete setting up cpcb. */ if (ci->ci_flags & CPUF_PRIMARY) { fpstate_cache = pool_cache_init(sizeof(struct fpstate64), SPARC64_BLOCK_SIZE, 0, 0, "fpstate", NULL, IPL_NONE, NULL, NULL, NULL); cpu_reset_fpustate(); } #ifdef MULTIPROCESSOR else { mi_cpu_attach(ci); ci->ci_cpcb = lwp_getpcb(ci->ci_data.cpu_idlelwp); } for (i = 0; i < IPI_EVCNT_NUM; ++i) evcnt_attach_dynamic(&ci->ci_ipi_evcnt[i], EVCNT_TYPE_INTR, NULL, device_xname(dev), ipi_evcnt_names[i]); #endif evcnt_attach_dynamic(&ci->ci_tick_evcnt, EVCNT_TYPE_INTR, NULL, device_xname(dev), "timer"); mutex_init(&ci->ci_ctx_lock, MUTEX_SPIN, IPL_VM); clk = prom_getpropint(node, "clock-frequency", 0); if (clk == 0) { /* * Try to find it in the OpenPROM root... */ clk = prom_getpropint(findroot(), "clock-frequency", 0); } if (clk) { /* Tell OS what frequency we run on */ ci->ci_cpu_clockrate[0] = clk; ci->ci_cpu_clockrate[1] = clk / 1000000; } sclk = prom_getpropint(findroot(), "stick-frequency", 0); ci->ci_system_clockrate[0] = sclk; ci->ci_system_clockrate[1] = sclk / 1000000; snprintf(buf, sizeof buf, "%s @ %s MHz", prom_getpropstring(node, "name"), clockfreq(clk)); snprintf(cpu_model, sizeof cpu_model, "%s (%s)", machine_model, buf); aprint_normal(": %s, UPA id %d\n", buf, ci->ci_cpuid); aprint_naive("\n"); if (ci->ci_system_clockrate[0] != 0) { aprint_normal_dev(dev, "system tick frequency %d MHz\n", (int)ci->ci_system_clockrate[1]); } aprint_normal_dev(dev, ""); bigcache = 0; icachesize = prom_getpropint(node, "icache-size", 0); if (icachesize > icache_size) icache_size = icachesize; linesize = l = prom_getpropint(node, "icache-line-size", 0); if (linesize > icache_line_size) icache_line_size = linesize; for (i = 0; (1 << i) < l && l; i++) /* void */; if ((1 << i) != l && l) panic("bad icache line size %d", l); totalsize = icachesize; if (totalsize == 0) totalsize = l * prom_getpropint(node, "icache-nlines", 64) * prom_getpropint(node, "icache-associativity", 1); cachesize = totalsize / prom_getpropint(node, "icache-associativity", 1); bigcache = cachesize; sep = ""; if (totalsize > 0) { aprint_normal("%s%ldK instruction (%ld b/l)", sep, (long)totalsize/1024, (long)linesize); sep = ", "; } dcachesize = prom_getpropint(node, "dcache-size", 0); if (dcachesize > dcache_size) dcache_size = dcachesize; linesize = l = prom_getpropint(node, "dcache-line-size", 0); if (linesize > dcache_line_size) dcache_line_size = linesize; for (i = 0; (1 << i) < l && l; i++) /* void */; if ((1 << i) != l && l) panic("bad dcache line size %d", l); totalsize = dcachesize; if (totalsize == 0) totalsize = l * prom_getpropint(node, "dcache-nlines", 128) * prom_getpropint(node, "dcache-associativity", 1); cachesize = totalsize / prom_getpropint(node, "dcache-associativity", 1); if (cachesize > bigcache) bigcache = cachesize; if (totalsize > 0) { aprint_normal("%s%ldK data (%ld b/l)", sep, (long)totalsize/1024, (long)linesize); sep = ", "; } linesize = l = prom_getpropint(node, "ecache-line-size", 0); for (i = 0; (1 << i) < l && l; i++) /* void */; if ((1 << i) != l && l) panic("bad ecache line size %d", l); totalsize = prom_getpropint(node, "ecache-size", 0); if (totalsize == 0) totalsize = l * prom_getpropint(node, "ecache-nlines", 32768) * prom_getpropint(node, "ecache-associativity", 1); cachesize = totalsize / prom_getpropint(node, "ecache-associativity", 1); if (cachesize > bigcache) bigcache = cachesize; if (totalsize > 0) { aprint_normal("%s%ldK external (%ld b/l)", sep, (long)totalsize/1024, (long)linesize); } aprint_normal("\n"); if (ecache_min_line_size == 0 || linesize < ecache_min_line_size) ecache_min_line_size = linesize; /* * Now that we know the size of the largest cache on this CPU, * re-color our pages. */ uvm_page_recolor(atop(bigcache)); /* XXX */ }
/* * Attach a display. We need to notice if it is the console, too. */ static void genfb_attach_sbus(device_t parent, device_t self, void *args) { struct genfb_sbus_softc *sc = device_private(self); struct sbus_attach_args *sa = args; static const struct genfb_ops zero_ops; struct genfb_ops ops = zero_ops; prop_dictionary_t dict; bus_space_handle_t bh; paddr_t fbpa; vaddr_t fbva; int node = sa->sa_node; int isconsole; aprint_normal("\n"); sc->sc_gen.sc_dev = self; /* Remember cookies for genfb_mmap_sbus() */ sc->sc_tag = sa->sa_bustag; sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset); /* read geometry information from the device tree */ sc->sc_gen.sc_width = prom_getpropint(sa->sa_node, "width", 1152); sc->sc_gen.sc_height = prom_getpropint(sa->sa_node, "height", 900); sc->sc_gen.sc_depth = prom_getpropint(sa->sa_node, "depth", 8); sc->sc_gen.sc_stride = prom_getpropint(sa->sa_node, "linebytes", (sc->sc_gen.sc_width * sc->sc_gen.sc_depth + 7) >> 3 ); sc->sc_gen.sc_fbsize = sc->sc_gen.sc_height * sc->sc_gen.sc_stride; fbva = (uint32_t)prom_getpropint(sa->sa_node, "address", 0); if (fbva == 0) panic("this fb has no address property\n"); aprint_normal_dev(self, "%d x %d at %d bit\n", sc->sc_gen.sc_width, sc->sc_gen.sc_height, sc->sc_gen.sc_depth); pmap_extract(pmap_kernel(), fbva, &fbpa); sc->sc_gen.sc_fboffset = (fbpa & 0x01ffffff) - (sc->sc_paddr & 0x01ffffff); aprint_normal_dev(self, "framebuffer at offset 0x%x\n", (uint32_t)sc->sc_gen.sc_fboffset); #if notyet if (sc->sc_gen.sc_depth <= 8) { /* setup some ANSIish colour map */ char boo[256]; snprintf(boo, 256, "\" pal!\" %x %x %x %x %x call", sa->sa_node, 0, 0xa0, 0xa0, 0); prom_interpret(boo); } #endif isconsole = fb_is_console(node); dict = device_properties(self); prop_dictionary_set_bool(dict, "is_console", isconsole); if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset + sc->sc_gen.sc_fboffset, sc->sc_gen.sc_fbsize, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "cannot map framebuffer\n"); return; } sc->sc_gen.sc_fbaddr = (void *)bus_space_vaddr(sa->sa_bustag, bh); ops.genfb_ioctl = genfb_ioctl_sbus; ops.genfb_mmap = genfb_mmap_sbus; genfb_attach(&sc->sc_gen, &ops); }
void bppattach(device_t parent, device_t self, void *aux) { struct bpp_softc *dsc = device_private(self); struct lsi64854_softc *sc = &dsc->sc_lsi64854; struct sbus_softc *sbsc = device_private(parent); struct sbus_attach_args *sa = aux; int burst, sbusburst; int node; sc->sc_dev = self; selinit(&dsc->sc_rsel); selinit(&dsc->sc_wsel); dsc->sc_sih = softint_establish(SOFTINT_CLOCK, bppsoftintr, dsc); sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; node = sa->sa_node; /* Map device registers */ if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, &sc->sc_regs) != 0) { aprint_error(": cannot map registers\n"); return; } /* * Get transfer burst size from PROM and plug it into the * controller registers. This is needed on the Sun4m; do * others need it too? */ sbusburst = sbsc->sc_burst; if (sbusburst == 0) sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ burst = prom_getpropint(node, "burst-sizes", -1); if (burst == -1) /* take SBus burst sizes */ burst = sbusburst; /* Clamp at parent's burst sizes */ burst &= sbusburst; sc->sc_burst = (burst & SBUS_BURST_32) ? 32 : (burst & SBUS_BURST_16) ? 16 : 0; /* Join the Sbus device family */ dsc->sc_sd.sd_reset = NULL; sbus_establish(&dsc->sc_sd, self); /* Initialize the DMA channel */ sc->sc_channel = L64854_CHANNEL_PP; lsi64854_attach(sc); /* Establish interrupt handler */ if (sa->sa_nintr) { sc->sc_intrchain = bppintr; sc->sc_intrchainarg = dsc; (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, bppintr, sc); } /* Allocate buffer XXX - should actually use dmamap_uio() */ dsc->sc_bufsz = 1024; dsc->sc_buf = malloc(dsc->sc_bufsz, M_DEVBUF, M_NOWAIT); /* XXX read default state */ { bus_space_handle_t h = sc->sc_regs; struct hwstate *hw = &dsc->sc_hwdefault; int ack_rate = sa->sa_frequency / 1000000; hw->hw_hcr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_HCR); hw->hw_ocr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_OCR); hw->hw_tcr = bus_space_read_1(sc->sc_bustag, h, L64854_REG_TCR); hw->hw_or = bus_space_read_1(sc->sc_bustag, h, L64854_REG_OR); DPRINTF(("bpp: hcr %x ocr %x tcr %x or %x\n", hw->hw_hcr, hw->hw_ocr, hw->hw_tcr, hw->hw_or)); /* Set these to sane values */ hw->hw_hcr = ((ack_rate<<BPP_HCR_DSS_SHFT)&BPP_HCR_DSS_MASK) | ((ack_rate<<BPP_HCR_DSW_SHFT)&BPP_HCR_DSW_MASK); hw->hw_ocr |= BPP_OCR_ACK_OP; } }
void beattach(device_t parent, device_t self, void *aux) { struct sbus_attach_args *sa = aux; struct qec_softc *qec = device_private(parent); struct be_softc *sc = device_private(self); struct ifnet *ifp = &sc->sc_ethercom.ec_if; struct mii_data *mii = &sc->sc_mii; struct mii_softc *child; int node = sa->sa_node; bus_dma_tag_t dmatag = sa->sa_dmatag; bus_dma_segment_t seg; bus_size_t size; int instance; int rseg, error; uint32_t v; sc->sc_dev = self; if (sa->sa_nreg < 3) { printf(": only %d register sets\n", sa->sa_nreg); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR(sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base), (bus_size_t)sa->sa_reg[0].oa_size, 0, &sc->sc_cr) != 0) { printf(": cannot map registers\n"); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR(sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base), (bus_size_t)sa->sa_reg[1].oa_size, 0, &sc->sc_br) != 0) { printf(": cannot map registers\n"); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR(sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base), (bus_size_t)sa->sa_reg[2].oa_size, 0, &sc->sc_tr) != 0) { printf(": cannot map registers\n"); return; } sc->sc_bustag = sa->sa_bustag; sc->sc_qec = qec; sc->sc_qr = qec->sc_regs; sc->sc_rev = prom_getpropint(node, "board-version", -1); printf(": rev %x,", sc->sc_rev); callout_init(&sc->sc_tick_ch, 0); sc->sc_channel = prom_getpropint(node, "channel#", -1); if (sc->sc_channel == -1) sc->sc_channel = 0; sc->sc_burst = prom_getpropint(node, "burst-sizes", -1); if (sc->sc_burst == -1) sc->sc_burst = qec->sc_burst; /* Clamp at parent's burst sizes */ sc->sc_burst &= qec->sc_burst; /* Establish interrupt handler */ if (sa->sa_nintr) (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET, beintr, sc); prom_getether(node, sc->sc_enaddr); printf(" address %s\n", ether_sprintf(sc->sc_enaddr)); /* * Allocate descriptor ring and buffers. */ /* for now, allocate as many bufs as there are ring descriptors */ sc->sc_rb.rb_ntbuf = QEC_XD_RING_MAXSIZE; sc->sc_rb.rb_nrbuf = QEC_XD_RING_MAXSIZE; size = QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) + QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) + sc->sc_rb.rb_ntbuf * BE_PKT_BUF_SZ + sc->sc_rb.rb_nrbuf * BE_PKT_BUF_SZ; /* Get a DMA handle */ if ((error = bus_dmamap_create(dmatag, size, 1, size, 0, BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) { aprint_error_dev(self, "DMA map create error %d\n", error); return; } /* Allocate DMA buffer */ if ((error = bus_dmamem_alloc(sa->sa_dmatag, size, 0, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "DMA buffer alloc error %d\n", error); return; } /* Map DMA memory in CPU addressable space */ if ((error = bus_dmamem_map(sa->sa_dmatag, &seg, rseg, size, &sc->sc_rb.rb_membase, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { aprint_error_dev(self, "DMA buffer map error %d\n", error); bus_dmamem_free(sa->sa_dmatag, &seg, rseg); return; } /* Load the buffer */ if ((error = bus_dmamap_load(dmatag, sc->sc_dmamap, sc->sc_rb.rb_membase, size, NULL, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "DMA buffer map load error %d\n", error); bus_dmamem_unmap(dmatag, sc->sc_rb.rb_membase, size); bus_dmamem_free(dmatag, &seg, rseg); return; } sc->sc_rb.rb_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr; /* * Initialize our media structures and MII info. */ mii->mii_ifp = ifp; mii->mii_readreg = be_mii_readreg; mii->mii_writereg = be_mii_writereg; mii->mii_statchg = be_mii_statchg; ifmedia_init(&mii->mii_media, 0, be_ifmedia_upd, be_ifmedia_sts); /* * Initialize transceiver and determine which PHY connection to use. */ be_mii_sync(sc); v = bus_space_read_4(sc->sc_bustag, sc->sc_tr, BE_TRI_MGMTPAL); instance = 0; if ((v & MGMT_PAL_EXT_MDIO) != 0) { mii_attach(self, mii, 0xffffffff, BE_PHY_EXTERNAL, MII_OFFSET_ANY, 0); child = LIST_FIRST(&mii->mii_phys); if (child == NULL) { /* No PHY attached */ ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, instance), 0, NULL); ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, instance)); } else { /* * Note: we support just one PHY on the external * MII connector. */ #ifdef DIAGNOSTIC if (LIST_NEXT(child, mii_list) != NULL) { aprint_error_dev(self, "spurious MII device %s attached\n", device_xname(child->mii_dev)); } #endif if (child->mii_phy != BE_PHY_EXTERNAL || child->mii_inst > 0) { aprint_error_dev(self, "cannot accommodate MII device %s" " at phy %d, instance %d\n", device_xname(child->mii_dev), child->mii_phy, child->mii_inst); } else { sc->sc_phys[instance] = child->mii_phy; } /* * XXX - we can really do the following ONLY if the * phy indeed has the auto negotiation capability!! */ ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, instance)); /* Mark our current media setting */ be_pal_gate(sc, BE_PHY_EXTERNAL); instance++; } } if ((v & MGMT_PAL_INT_MDIO) != 0) { /* * The be internal phy looks vaguely like MII hardware, * but not enough to be able to use the MII device * layer. Hence, we have to take care of media selection * ourselves. */ sc->sc_mii_inst = instance; sc->sc_phys[instance] = BE_PHY_INTERNAL; /* Use `ifm_data' to store BMCR bits */ ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, instance), 0, NULL); ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, instance), BMCR_S100, NULL); ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, instance), 0, NULL); printf("on-board transceiver at %s: 10baseT, 100baseTX, auto\n", device_xname(self)); be_mii_reset(sc, BE_PHY_INTERNAL); /* Only set default medium here if there's no external PHY */ if (instance == 0) { be_pal_gate(sc, BE_PHY_INTERNAL); ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, instance)); } else be_mii_writereg(self, BE_PHY_INTERNAL, MII_BMCR, BMCR_ISO); } memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); ifp->if_softc = sc; ifp->if_start = bestart; ifp->if_ioctl = beioctl; ifp->if_watchdog = bewatchdog; ifp->if_init = beinit; ifp->if_stop = bestop; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; IFQ_SET_READY(&ifp->if_snd); /* claim 802.1q capability */ sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; /* Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); }
void spif_attach(device_t parent, device_t self, void *aux) { struct spif_softc *sc = device_private(self); struct sbus_attach_args *sa = aux; sc->sc_dev = self; if (sa->sa_nintr != 2) { printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr); return; } if (sa->sa_nreg != 1) { printf(": expected %d registers, got %d\n", 1, sa->sa_nreg); return; } sc->sc_bustag = sa->sa_bustag; if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, &sc->sc_regh) != 0) { printf(": can't map registers\n"); return; } if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) { printf(": can't map dtr regs\n"); goto fail_unmapregs; } if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) { printf(": can't map dtr regs\n"); goto fail_unmapregs; } if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) { printf(": can't map dtr regs\n"); goto fail_unmapregs; } if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) { printf(": can't map dtr regs\n"); goto fail_unmapregs; } sc->sc_ppcih = bus_intr_establish(sa->sa_bustag, sa->sa_intr[PARALLEL_INTR].oi_pri, IPL_SERIAL, spif_ppcintr, sc); if (sc->sc_ppcih == NULL) { printf(": failed to establish ppc interrupt\n"); goto fail_unmapregs; } sc->sc_stcih = bus_intr_establish(sa->sa_bustag, sa->sa_intr[SERIAL_INTR].oi_pri, IPL_SERIAL, spif_stcintr, sc); if (sc->sc_stcih == NULL) { printf(": failed to establish stc interrupt\n"); goto fail_unmapregs; } sc->sc_softih = softint_establish(SOFTINT_SERIAL, spif_softintr, sc); if (sc->sc_softih == NULL) { printf(": can't get soft intr\n"); goto fail_unmapregs; } sc->sc_node = sa->sa_node; sc->sc_rev = prom_getpropint(sc->sc_node, "revlev", 0); sc->sc_osc = prom_getpropint(sc->sc_node, "verosc", 0); switch (sc->sc_osc) { case SPIF_OSC10: sc->sc_osc = 10000000; break; case SPIF_OSC9: default: sc->sc_osc = 9830400; break; } sc->sc_nser = 8; sc->sc_npar = 1; sc->sc_rev2 = STC_READ(sc, STC_GFRCR); STC_WRITE(sc, STC_GSVR, 0); stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL); while (STC_READ(sc, STC_GSVR) != 0xff); while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2); STC_WRITE(sc, STC_PPRH, CD180_PPRH); STC_WRITE(sc, STC_PPRL, CD180_PPRL); STC_WRITE(sc, STC_MSMR, SPIF_MSMR); STC_WRITE(sc, STC_TSMR, SPIF_TSMR); STC_WRITE(sc, STC_RSMR, SPIF_RSMR); STC_WRITE(sc, STC_GSVR, 0); STC_WRITE(sc, STC_GSCR1, 0); STC_WRITE(sc, STC_GSCR2, 0); STC_WRITE(sc, STC_GSCR3, 0); printf(": rev %x chiprev %x osc %sMHz\n", sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc)); (void)config_found(self, stty_match, NULL); (void)config_found(self, sbpp_match, NULL); return; fail_unmapregs: bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_size); }
static void zx_attach(device_t parent, device_t self, void *args) { struct zx_softc *sc; struct sbus_attach_args *sa; bus_space_handle_t bh; bus_space_tag_t bt; struct fbdevice *fb; #if NWSDISPLAY > 0 struct wsemuldisplaydev_attach_args aa; struct rasops_info *ri = &zx_console_screen.scr_ri; unsigned long defattr; #endif int isconsole, width, height; sc = device_private(self); sc->sc_dv = self; sa = args; fb = &sc->sc_fb; bt = sa->sa_bustag; sc->sc_bt = bt; sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0, 0x800000, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, &bh) != 0) { aprint_error_dev(self, "can't map bits\n"); return; } fb->fb_pixels = (void *)bus_space_vaddr(bt, bh); sc->sc_pixels = (uint32_t *)fb->fb_pixels; if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR, PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "can't map zc\n"); return; } sc->sc_bhzc = bh; if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0, PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "can't map ld/ss0\n"); return; } sc->sc_bhzdss0 = bh; if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1, PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "can't map ld/ss1\n"); return; } sc->sc_bhzdss1 = bh; if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS, PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "can't map zx\n"); return; } sc->sc_bhzx = bh; if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR, PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "can't map zcu\n"); return; } sc->sc_bhzcu = bh; fb->fb_driver = &zx_fbdriver; fb->fb_device = sc->sc_dv; fb->fb_flags = device_cfdata(sc->sc_dv)->cf_flags & FB_USERMASK; fb->fb_pfour = NULL; fb->fb_linebytes = prom_getpropint(sa->sa_node, "linebytes", 8192); width = prom_getpropint(sa->sa_node, "width", 1280); height = prom_getpropint(sa->sa_node, "height", 1024); fb_setsize_obp(fb, 32, width, height, sa->sa_node); fb->fb_type.fb_cmsize = 256; fb->fb_type.fb_depth = 32; fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes; fb->fb_type.fb_type = FBTYPE_SUNLEO; printf(": %d x %d", fb->fb_type.fb_width, fb->fb_type.fb_height); isconsole = fb_is_console(sa->sa_node); if (isconsole) printf(" (console)"); printf("\n"); if (sa->sa_nintr != 0) bus_intr_establish(bt, sa->sa_pri, IPL_NONE, zx_intr, sc); sc->sc_cmap = malloc(768, M_DEVBUF, M_NOWAIT); zx_reset(sc); #if NWSDISPLAY > 0 sc->sc_width = fb->fb_type.fb_width; sc->sc_stride = 8192; /* 32 bit */ sc->sc_height = fb->fb_type.fb_height; /* setup rasops and so on for wsdisplay */ wsfont_init(); sc->sc_mode = WSDISPLAYIO_MODE_EMUL; sc->sc_bg = WS_DEFAULT_BG; vcons_init(&sc->vd, sc, &zx_defaultscreen, &zx_accessops); sc->vd.init_screen = zx_init_screen; if (isconsole) { /* we mess with zx_console_screen only once */ vcons_init_screen(&sc->vd, &zx_console_screen, 1, &defattr); zx_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; zx_defaultscreen.textops = &ri->ri_ops; zx_defaultscreen.capabilities = WSSCREEN_WSCOLORS; zx_defaultscreen.nrows = ri->ri_rows; zx_defaultscreen.ncols = ri->ri_cols; zx_fillrect(sc, 0, 0, width, height, ri->ri_devcmap[defattr >> 16], ZX_STD_ROP); wsdisplay_cnattach(&zx_defaultscreen, ri, 0, 0, defattr); vcons_replay_msgbuf(&zx_console_screen); } else { /* * we're not the console so we just clear the screen and don't * set up any sort of text display */ if (zx_defaultscreen.textops == NULL) {
/* * Attach a display. We need to notice if it is the console, too. */ static void p9100_sbus_attach(struct device *parent, struct device *self, void *args) { struct p9100_softc *sc = device_private(self); struct sbus_attach_args *sa = args; struct fbdevice *fb = &sc->sc_fb; int isconsole; int node; int i, j; uint8_t ver; #if NWSDISPLAY > 0 struct wsemuldisplaydev_attach_args aa; struct rasops_info *ri; unsigned long defattr; #endif sc->sc_last_offset = 0xffffffff; /* Remember cookies for p9100_mmap() */ sc->sc_bustag = sa->sa_bustag; sc->sc_ctl_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base); sc->sc_ctl_psize = 0x8000;/*(bus_size_t)sa->sa_reg[0].oa_size;*/ sc->sc_cmd_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base); sc->sc_cmd_psize = (bus_size_t)sa->sa_reg[1].oa_size; sc->sc_fb_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base); sc->sc_fb_psize = (bus_size_t)sa->sa_reg[2].oa_size; fb->fb_driver = &p9100fbdriver; fb->fb_device = &sc->sc_dev; fb->fb_flags = device_cfdata(&sc->sc_dev)->cf_flags & FB_USERMASK; #ifdef PNOZZ_EMUL_CG3 fb->fb_type.fb_type = FBTYPE_SUN3COLOR; #else fb->fb_type.fb_type = FBTYPE_P9100; #endif fb->fb_pixels = NULL; sc->sc_mode = WSDISPLAYIO_MODE_EMUL; node = sa->sa_node; isconsole = fb_is_console(node); if (!isconsole) { aprint_normal("\n"); aprint_error_dev(self, "fatal error: PROM didn't configure device\n"); return; } /* * When the ROM has mapped in a p9100 display, the address * maps only the video RAM, so in any case we have to map the * registers ourselves. We only need the video RAM if we are * going to print characters via rconsole. */ if (sbus_bus_map(sc->sc_bustag, sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base, /* * XXX for some reason the SBus resources don't cover * all registers, so we just map what we need */ /*sc->sc_ctl_psize*/ 0x8000, /*BUS_SPACE_MAP_LINEAR*/0, &sc->sc_ctl_memh) != 0) { aprint_error_dev(self, "cannot map control registers\n"); return; } if (sa->sa_npromvaddrs != 0) fb->fb_pixels = (void *)sa->sa_promvaddrs[0]; if (fb->fb_pixels == NULL) { if (sbus_bus_map(sc->sc_bustag, sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base, sc->sc_fb_psize, BUS_SPACE_MAP_LINEAR, &sc->sc_fb_memh) != 0) { aprint_error_dev(self, "cannot map framebuffer\n"); return; } fb->fb_pixels = (char *)sc->sc_fb_memh; } else { sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels; } i = p9100_ctl_read_4(sc, 0x0004); switch ((i >> 26) & 7) { case 5: fb->fb_type.fb_depth = 32; break; case 7: fb->fb_type.fb_depth = 24; break; case 3: fb->fb_type.fb_depth = 16; break; case 2: fb->fb_type.fb_depth = 8; break; default: { panic("pnozz: can't determine screen depth (0x%02x)", i); } } sc->sc_depth = (fb->fb_type.fb_depth >> 3); /* XXX for some reason I get a kernel trap with this */ sc->sc_width = prom_getpropint(node, "width", 800); sc->sc_height = prom_getpropint(node, "height", 600); sc->sc_stride = prom_getpropint(node, "linebytes", sc->sc_width * (fb->fb_type.fb_depth >> 3)); /* check the RAMDAC */ ver = p9100_ramdac_read_ctl(sc, DAC_VERSION); p9100_init_engine(sc); fb_setsize_obp(fb, fb->fb_type.fb_depth, sc->sc_width, sc->sc_height, node); sbus_establish(&sc->sc_sd, &sc->sc_dev); bus_intr_establish(sc->sc_bustag, sa->sa_pri, IPL_BIO, p9100_intr, sc); fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes; printf(": rev %d / %x, %dx%d, depth %d mem %x", (i & 7), ver, fb->fb_type.fb_width, fb->fb_type.fb_height, fb->fb_type.fb_depth, (unsigned int)sc->sc_fb_psize); fb->fb_type.fb_cmsize = prom_getpropint(node, "cmsize", 256); if ((1 << fb->fb_type.fb_depth) != fb->fb_type.fb_cmsize) printf(", %d entry colormap", fb->fb_type.fb_cmsize); /* Initialize the default color map. */ /*bt_initcmap(&sc->sc_cmap, 256);*/ j = 0; for (i = 0; i < 256; i++) { sc->sc_cmap.cm_map[i][0] = rasops_cmap[j]; j++; sc->sc_cmap.cm_map[i][1] = rasops_cmap[j]; j++; sc->sc_cmap.cm_map[i][2] = rasops_cmap[j]; j++; } p9100loadcmap(sc, 0, 256); /* make sure we are not blanked */ if (isconsole) p9100_set_video(sc, 1); if (shutdownhook_establish(p9100_shutdown, sc) == NULL) { panic("%s: could not establish shutdown hook", device_xname(&sc->sc_dev)); } if (isconsole) { printf(" (console)\n"); #ifdef RASTERCONSOLE /*p9100loadcmap(sc, 255, 1);*/ fbrcons_init(fb); #endif } else printf("\n"); #if NWSDISPLAY > 0 wsfont_init(); vcons_init(&sc->vd, sc, &p9100_defscreendesc, &p9100_accessops); sc->vd.init_screen = p9100_init_screen; vcons_init_screen(&sc->vd, &p9100_console_screen, 1, &defattr); p9100_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; sc->sc_bg = (defattr >> 16) & 0xff; p9100_clearscreen(sc); ri = &p9100_console_screen.scr_ri; p9100_defscreendesc.nrows = ri->ri_rows; p9100_defscreendesc.ncols = ri->ri_cols; p9100_defscreendesc.textops = &ri->ri_ops; p9100_defscreendesc.capabilities = ri->ri_caps; if(isconsole) { wsdisplay_cnattach(&p9100_defscreendesc, ri, 0, 0, defattr); } aa.console = isconsole; aa.scrdata = &p9100_screenlist; aa.accessops = &p9100_accessops; aa.accesscookie = &sc->vd; config_found(self, &aa, wsemuldisplaydevprint); #endif /* cursor sprite handling */ p9100_init_cursor(sc); /* attach the fb */ fb_attach(fb, isconsole); /* register with power management */ sc->sc_video = 1; sc->sc_powerstate = PWR_RESUME; powerhook_establish(device_xname(&sc->sc_dev), p9100_power_hook, sc); #if NTCTRL > 0 /* register callback for external monitor status change */ tadpole_register_callback(p9100_set_extvga, sc); #endif }
void dmaattach_sbus(device_t parent, device_t self, void *aux) { struct dma_softc *dsc = device_private(self); struct lsi64854_softc *sc = &dsc->sc_lsi64854; struct sbus_attach_args *sa = aux; struct sbus_softc *sbsc = device_private(parent); bus_space_tag_t sbt; int sbusburst, burst; int node; node = sa->sa_node; sc->sc_dev = self; sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; /* Map registers */ if (sa->sa_npromvaddrs) { sbus_promaddr_to_handle(sa->sa_bustag, sa->sa_promvaddrs[0], &sc->sc_regs); } else { if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, &sc->sc_regs) != 0) { aprint_error(": cannot map registers\n"); return; } } /* * Get transfer burst size from PROM and plug it into the * controller registers. This is needed on the Sun4m; do * others need it too? */ sbusburst = sbsc->sc_burst; if (sbusburst == 0) sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ burst = prom_getpropint(node,"burst-sizes", -1); if (burst == -1) /* take SBus burst sizes */ burst = sbusburst; /* Clamp at parent's burst sizes */ burst &= sbusburst; sc->sc_burst = (burst & SBUS_BURST_32) ? 32 : (burst & SBUS_BURST_16) ? 16 : 0; if (device_is_a(self, "ledma")) { char *cabletype; uint32_t csr; /* * Check to see which cable type is currently active and * set the appropriate bit in the ledma csr so that it * gets used. If we didn't netboot, the PROM won't have * the "cable-selection" property; default to TP and then * the user can change it via a "media" option to ifconfig. */ cabletype = prom_getpropstring(node, "cable-selection"); csr = L64854_GCSR(sc); if (strcmp(cabletype, "tpe") == 0) { csr |= E_TP_AUI; } else if (strcmp(cabletype, "aui") == 0) { csr &= ~E_TP_AUI; } else { /* assume TP if nothing there */ csr |= E_TP_AUI; } L64854_SCSR(sc, csr); delay(20000); /* manual says we need a 20ms delay */ sc->sc_channel = L64854_CHANNEL_ENET; } else { sc->sc_channel = L64854_CHANNEL_SCSI; } sbus_establish(&dsc->sc_sd, self); if ((sbt = bus_space_tag_alloc(sc->sc_bustag, dsc)) == NULL) { aprint_error(": out of memory\n"); return; } sbt->sparc_intr_establish = dmabus_intr_establish; lsi64854_attach(sc); /* Attach children */ for (node = firstchild(sa->sa_node); node; node = nextsibling(node)) { struct sbus_attach_args sax; sbus_setup_attach_args(sbsc, sbt, sc->sc_dmatag, node, &sax); (void)config_found(self, (void *)&sax, dmaprint_sbus); sbus_destroy_attach_args(&sax); } }
void qeattach(device_t parent, device_t self, void *aux) { struct sbus_attach_args *sa = aux; struct qec_softc *qec = device_private(parent); struct qe_softc *sc = device_private(self); struct ifnet *ifp = &sc->sc_ethercom.ec_if; int node = sa->sa_node; bus_dma_tag_t dmatag = sa->sa_dmatag; bus_dma_segment_t seg; bus_size_t size; int rseg, error; sc->sc_dev = self; if (sa->sa_nreg < 2) { printf("%s: only %d register sets\n", device_xname(self), sa->sa_nreg); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR( sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base), (bus_size_t)sa->sa_reg[0].oa_size, 0, &sc->sc_cr) != 0) { aprint_error_dev(self, "cannot map registers\n"); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR( sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base), (bus_size_t)sa->sa_reg[1].oa_size, 0, &sc->sc_mr) != 0) { aprint_error_dev(self, "cannot map registers\n"); return; } sc->sc_rev = prom_getpropint(node, "mace-version", -1); printf(" rev %x", sc->sc_rev); sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; sc->sc_qec = qec; sc->sc_qr = qec->sc_regs; sc->sc_channel = prom_getpropint(node, "channel#", -1); sc->sc_burst = qec->sc_burst; qestop(sc); /* Note: no interrupt level passed */ (void)bus_intr_establish(sa->sa_bustag, 0, IPL_NET, qeintr, sc); prom_getether(node, sc->sc_enaddr); /* * Allocate descriptor ring and buffers. */ /* for now, allocate as many bufs as there are ring descriptors */ sc->sc_rb.rb_ntbuf = QEC_XD_RING_MAXSIZE; sc->sc_rb.rb_nrbuf = QEC_XD_RING_MAXSIZE; size = QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) + QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) + sc->sc_rb.rb_ntbuf * QE_PKT_BUF_SZ + sc->sc_rb.rb_nrbuf * QE_PKT_BUF_SZ; /* Get a DMA handle */ if ((error = bus_dmamap_create(dmatag, size, 1, size, 0, BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) { aprint_error_dev(self, "DMA map create error %d\n", error); return; } /* Allocate DMA buffer */ if ((error = bus_dmamem_alloc(dmatag, size, 0, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "DMA buffer alloc error %d\n", error); return; } /* Map DMA buffer in CPU addressable space */ if ((error = bus_dmamem_map(dmatag, &seg, rseg, size, &sc->sc_rb.rb_membase, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { aprint_error_dev(self, "DMA buffer map error %d\n", error); bus_dmamem_free(dmatag, &seg, rseg); return; } /* Load the buffer */ if ((error = bus_dmamap_load(dmatag, sc->sc_dmamap, sc->sc_rb.rb_membase, size, NULL, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "DMA buffer map load error %d\n", error); bus_dmamem_unmap(dmatag, sc->sc_rb.rb_membase, size); bus_dmamem_free(dmatag, &seg, rseg); return; } sc->sc_rb.rb_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr; /* Initialize media properties */ ifmedia_init(&sc->sc_ifmedia, 0, qe_ifmedia_upd, qe_ifmedia_sts); ifmedia_add(&sc->sc_ifmedia, IFM_MAKEWORD(IFM_ETHER,IFM_10_T,0,0), 0, NULL); ifmedia_add(&sc->sc_ifmedia, IFM_MAKEWORD(IFM_ETHER,IFM_10_5,0,0), 0, NULL); ifmedia_add(&sc->sc_ifmedia, IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,0), 0, NULL); ifmedia_set(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO); memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); ifp->if_softc = sc; ifp->if_start = qestart; ifp->if_ioctl = qeioctl; ifp->if_watchdog = qewatchdog; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; IFQ_SET_READY(&ifp->if_snd); /* Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); printf(" address %s\n", ether_sprintf(sc->sc_enaddr)); }
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; DPRINTF(VBUS_INTR, ("vbus_intr_map(): ino 0x%x\n", ino)); parent = OF_parent(node); address_cells = prom_getpropint(parent, "#address-cells", 2); interrupt_cells = prom_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); if (prom_getprop(parent, "interrupt-map", sizeof(int), &nimap, (void **)&imap)) panic("vbus: can't get interrupt-map"); if (prom_getprop(node, "reg", sizeof(*reg), &nreg, (void **)®)) panic("vbus: can't get 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); reg = NULL; if (prom_getprop(node, "reg", sizeof(*reg), &nreg, (void **)®)) panic("vbus: can't get 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); }