/* * 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); }
/* * Verify target ID is valid (exists in the OPENPROM tree), as * listed from node ID sid forward. */ static int openpromcheckid(int sid, int tid) { for (; sid != 0; sid = nextsibling(sid)) if (sid == tid || openpromcheckid(firstchild(sid), tid)) return (1); return (0); }
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); } }
static void central_attach(device_t parent, device_t self, void *aux) { struct central_softc *sc = device_private(self); struct mainbus_attach_args *ma = aux; int node0, node; sc->sc_bt = ma->ma_bustag; sc->sc_node = ma->ma_node; sc->sc_cbt = central_alloc_bus_tag(sc); prom_getprop(sc->sc_node, "ranges", sizeof(struct central_range), &sc->sc_nrange, (void **)&sc->sc_range); printf("\n"); node0 = firstchild(sc->sc_node); for (node = node0; node; node = nextsibling(node)) { struct central_attach_args ca; bzero(&ca, sizeof(ca)); ca.ca_node = node; ca.ca_bustag = sc->sc_cbt; if (central_get_string(ca.ca_node, "name", &ca.ca_name)) { printf("can't fetch name for node 0x%x\n", node); continue; } prom_getprop(node, "reg", sizeof(struct central_reg), &ca.ca_nreg, (void **)&ca.ca_reg); (void)config_found(self, (void *)&ca, central_print); if (ca.ca_name != NULL) free(ca.ca_name, M_DEVBUF); } }
int openpromioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) { struct opiocdesc *op; int node, optionsnode, len, ok, error, s; char *name, *value, *nextprop; optionsnode = prom_getoptionsnode(); /* All too easy... */ if (cmd == OPIOCGETOPTNODE) { *(int *)data = optionsnode; return (0); } /* Verify node id */ op = (struct opiocdesc *)data; node = op->op_nodeid; if (node != 0 && node != lastnode && node != optionsnode) { /* Not an easy one, must search for it */ s = splhigh(); ok = openpromcheckid(findroot(), node); splx(s); if (!ok) return (EINVAL); lastnode = node; } name = value = NULL; error = 0; switch (cmd) { case OPIOCGET: if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); error = openpromgetstr(op->op_namelen, op->op_name, &name); if (error) break; s = splhigh(); len = prom_proplen(node, name); splx(s); if (len > op->op_buflen) { error = ENOMEM; break; } op->op_buflen = len; /* -1 means no entry; 0 means no value */ if (len <= 0) break; value = malloc(len, M_TEMP, M_WAITOK); s = splhigh(); error = prom_getprop(node, name, 1, &len, &value); splx(s); if (error != 0) break; error = copyout(value, op->op_buf, len); break; case OPIOCSET: if ((flags & FWRITE) == 0) return (EBADF); if (node == 0) return (EINVAL); error = openpromgetstr(op->op_namelen, op->op_name, &name); if (error) break; error = openpromgetstr(op->op_buflen, op->op_buf, &value); if (error) break; s = splhigh(); len = prom_setprop(node, name, value, op->op_buflen + 1); splx(s); if (len != op->op_buflen) error = EINVAL; break; case OPIOCNEXTPROP: if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); error = openpromgetstr(op->op_namelen, op->op_name, &name); if (error) break; s = splhigh(); nextprop = prom_nextprop(node, name); splx(s); len = strlen(nextprop); if (len > op->op_buflen) len = op->op_buflen; else op->op_buflen = len; error = copyout(nextprop, op->op_buf, len); break; case OPIOCGETNEXT: if ((flags & FREAD) == 0) return (EBADF); s = splhigh(); node = nextsibling(node); splx(s); *(int *)data = lastnode = node; break; case OPIOCGETCHILD: if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); s = splhigh(); node = firstchild(node); splx(s); *(int *)data = lastnode = node; break; case OPIOCFINDDEVICE: if ((flags & FREAD) == 0) return (EBADF); error = openpromgetstr(op->op_namelen, op->op_name, &name); if (error) break; node = prom_finddevice(name); if (node == 0 || node == -1) { error = ENOENT; break; } op->op_nodeid = lastnode = node; break; default: return (ENOTTY); } if (name) free(name, M_TEMP); if (value) free(value, M_TEMP); return (error); }
/* * Attach all the sub-devices we can find */ void lebufattach(struct device *parent, struct device *self, void *aux) { struct sbus_attach_args *sa = aux; struct lebuf_softc *sc = (void *)self; int node; int sbusburst; struct sparc_bus_space_tag *sbt; bus_space_handle_t bh; sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("%s: attach: cannot map registers\n", self->dv_xname); return; } /* * This device's "register space" is just a buffer where the * Lance ring-buffers can be stored. Note the buffer's location * and size, so the `le' driver can pick them up. */ sc->sc_buffer = (void *)bus_space_vaddr(sa->sa_bustag, bh); sc->sc_bufsiz = sa->sa_size; node = sc->sc_node = sa->sa_node; /* * Get transfer burst size from PROM */ sbusburst = ((struct sbus_softc *)parent)->sc_burst; if (sbusburst == 0) sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ sc->sc_burst = getpropint(node, "burst-sizes", -1); if (sc->sc_burst == -1) /* take SBus burst sizes */ sc->sc_burst = sbusburst; /* Clamp at parent's burst sizes */ sc->sc_burst &= sbusburst; /* Allocate a bus tag */ sbt = malloc(sizeof(*sbt), M_DEVBUF, M_NOWAIT | M_ZERO); if (sbt == NULL) { printf("%s: attach: out of memory\n", self->dv_xname); return; } printf(": %dK memory\n", sc->sc_bufsiz / 1024); sbt->cookie = sc; sbt->parent = sc->sc_bustag; sbt->asi = sbt->parent->asi; sbt->sasi = sbt->parent->sasi; /* search through children */ for (node = firstchild(node); node; node = nextsibling(node)) { struct sbus_attach_args sa; sbus_setup_attach_args((struct sbus_softc *)parent, sbt, sc->sc_dmatag, node, &sa); (void)config_found(&sc->sc_dev, (void *)&sa, lebufprint); sbus_destroy_attach_args(&sa); } }
void fhc_attach(struct fhc_softc *sc) { int node0, node; u_int32_t ctrl; printf(" board %d: %s\n", sc->sc_board, getpropstring(sc->sc_node, "board-model")); sc->sc_cbt = fhc_alloc_bus_tag(sc); sc->sc_ign = sc->sc_board << 1; bus_space_write_4(sc->sc_bt, sc->sc_ireg, FHC_I_IGN, sc->sc_ign); sc->sc_ign = bus_space_read_4(sc->sc_bt, sc->sc_ireg, FHC_I_IGN); ctrl = bus_space_read_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL); if (!sc->sc_is_central) ctrl |= FHC_P_CTRL_IXIST; ctrl &= ~(FHC_P_CTRL_AOFF | FHC_P_CTRL_BOFF | FHC_P_CTRL_SLINE); bus_space_write_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL, ctrl); bus_space_read_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL); /* clear interrupts */ bus_space_write_4(sc->sc_bt, sc->sc_freg, FHC_F_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_freg, FHC_F_ICLR); bus_space_write_4(sc->sc_bt, sc->sc_sreg, FHC_S_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_sreg, FHC_S_ICLR); bus_space_write_4(sc->sc_bt, sc->sc_ureg, FHC_U_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_ureg, FHC_U_ICLR); bus_space_write_4(sc->sc_bt, sc->sc_treg, FHC_T_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_treg, FHC_T_ICLR); getprop(sc->sc_node, "ranges", sizeof(struct fhc_range), &sc->sc_nrange, (void **)&sc->sc_range); node0 = firstchild(sc->sc_node); for (node = node0; node; node = nextsibling(node)) { struct fhc_attach_args fa; bzero(&fa, sizeof(fa)); fa.fa_node = node; fa.fa_bustag = sc->sc_cbt; if (fhc_get_string(fa.fa_node, "name", &fa.fa_name)) { printf("can't fetch name for node 0x%x\n", node); continue; } getprop(node, "reg", sizeof(struct fhc_reg), &fa.fa_nreg, (void **)&fa.fa_reg); getprop(node, "interrupts", sizeof(int), &fa.fa_nintr, (void **)&fa.fa_intr); getprop(node, "address", sizeof(*fa.fa_promvaddrs), &fa.fa_npromvaddrs, (void **)&fa.fa_promvaddrs); (void)config_found(&sc->sc_dv, (void *)&fa, fhc_print); if (fa.fa_name != NULL) free(fa.fa_name, M_DEVBUF); if (fa.fa_reg != NULL) free(fa.fa_reg, M_DEVBUF); if (fa.fa_nintr != NULL) free(fa.fa_intr, M_DEVBUF); if (fa.fa_promvaddrs != NULL) free(fa.fa_promvaddrs, M_DEVBUF); } sc->sc_blink.bl_func = fhc_led_blink; sc->sc_blink.bl_arg = sc; blink_led_register(&sc->sc_blink); }
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); } }