/* * The first psycho must always programmed up for the system clock and error * handling purposes. */ static void have_pci(pnode_t node) { int size; uint_t portid; char compatible[OBP_MAXDRVNAME]; size = GETPROPLEN(node, "portid"); if (size == -1) size = GETPROPLEN(node, "upa-portid"); if (size == -1) return; if (size > sizeof (portid)) cmn_err(CE_PANIC, "portid size wrong"); if (GETPROP(node, "portid", (caddr_t)&portid) == -1) if (GETPROP(node, "upa-portid", (caddr_t)&portid) == -1) cmn_err(CE_PANIC, "portid not found"); niobus++; /* * Need two physical TSBs for Schizo compatible nodes, * one otherwise. */ compatible[0] = '\0'; (void) prom_getprop(node, OBP_COMPATIBLE, compatible); if (strcmp(compatible, "pci108e,8001") == 0) niommu_tsbs += IOMMU_PER_SCHIZO; else niommu_tsbs++; }
void get_drone_ip(void) { int ret; char prop_value[PROP_VALUE_MAX]; char prop_name[PROP_NAME_MAX]; int inet_part[4]; // quick and dirty way to guess Drone IP address ret = GETPROP("wifi.interface", prop_value); if (ret > 0) { INFO("wifi interface = %s\n", prop_value); snprintf(prop_name, PROP_NAME_MAX, "dhcp.%s.ipaddress", prop_value); ret = GETPROP(prop_name, prop_value); } if (ret > 0) { INFO("IP address = %s\n", prop_value); ret = 0; if (sscanf(prop_value, "%d.%d.%d.%d", &inet_part[0], &inet_part[1], &inet_part[2], &inet_part[3]) == 4) { ret = 1; sprintf(drone_ip, "%u.%u.%u.%u", inet_part[0]& 0xff, inet_part[1]& 0xff, inet_part[2]&0xff, WIFI_ARDRONE_ADDR_LAST_BYTE); } } if (ret == 0) { // fallback to default address sprintf(drone_ip, WIFI_ARDRONE_IP); } INFO("assuming drone IP address is %s\n", drone_ip); }
/* * The first eeprom is used as the TOD clock, referenced * by v_eeprom_addr in locore.s. */ static void have_eeprom(pnode_t node) { int size; uint32_t eaddr; /* * "todmostek" module will be selected based on finding a "model" * property value of "mk48t59" in the "eeprom" node. */ if (tod_module_name == NULL) { char buf[MAXSYSNAME]; if ((GETPROP(node, "model", buf) != -1) && (strcmp(buf, "mk48t59") == 0)) tod_module_name = "todmostek"; } /* * If we have found two distinct eeprom's, then we're done. */ if (v_eeprom_addr && v_timecheck_addr != v_eeprom_addr) return; /* * multiple eeproms may exist but at least * one must have an "address" property */ if ((size = GETPROPLEN(node, OBP_ADDRESS)) == -1) return; if (size != sizeof (eaddr)) cmn_err(CE_PANIC, "eeprom addr size"); if (GETPROP(node, OBP_ADDRESS, (caddr_t)&eaddr) == -1) cmn_err(CE_PANIC, "eeprom addr"); /* * If we have a chosen eeprom and it is not this node, keep looking. */ if (chosen_eeprom != NULL && chosen_eeprom != node) { v_timecheck_addr = (caddr_t)(uintptr_t)eaddr; return; } v_eeprom_addr = (caddr_t)(uintptr_t)eaddr; /* * If we don't find an I/O board to use to check the clock, * we'll fall back on whichever TOD is available. */ if (v_timecheck_addr == NULL) v_timecheck_addr = v_eeprom_addr; /* * Does this eeprom have watchdog support? */ if (GETPROPLEN(node, WATCHDOG_ENABLE) != -1) watchdog_available = 1; }
static void have_auxio(pnode_t node) { size_t size, n; uint32_t addr[5]; /* * Get the size of the auzio's address property. * On some platforms, the address property contains one * entry and on others it contains five entries. * In all cases, the first entries are compatible. * * This routine gets the address property for the auxio * node and stores the first entry in v_auxio_addr which * is used by the routine set_auxioreg in sun4u/ml/locore.s. */ if ((size = GETPROPLEN(node, OBP_ADDRESS)) == -1) cmn_err(CE_PANIC, "no auxio address property"); switch (n = (size / sizeof (addr[0]))) { case 1: break; case 5: break; default: cmn_err(CE_PANIC, "auxio addr has %lu entries?", n); } if (GETPROP(node, OBP_ADDRESS, (caddr_t)addr) == -1) cmn_err(CE_PANIC, "auxio addr"); v_auxio_addr = (caddr_t)(uintptr_t)(addr[0]); /* make into pointer */ }
static void have_pmc(pnode_t node) { uint32_t vaddr; pnode_t root; /* * Watchdog property is in the root node. */ root = prom_nextnode((pnode_t)0); if (GETPROPLEN(root, WATCHDOG_ENABLE) != -1) { /* * The hardware watchdog timer resides within logical * unit 8 of SuperI/O. The address property of the node * contains the virtual address that we use to program * the timer. */ if (GETPROP(node, OBP_ADDRESS, (caddr_t)&vaddr) == -1) { watchdog_available = 0; return; } v_pmc_addr_reg = (volatile uint8_t *)(uintptr_t)vaddr; v_pmc_data_reg = (volatile uint8_t *)(uintptr_t)vaddr + 1; watchdog_available = 1; } }
void map_wellknown_devices() { struct wkdevice *wkp; phandle_t ieeprom; pnode_t root; uint_t stick_freq; /* * if there is a chosen eeprom, note it (for have_eeprom()) */ if (GETPROPLEN(prom_chosennode(), CHOSEN_EEPROM) == sizeof (phandle_t) && GETPROP(prom_chosennode(), CHOSEN_EEPROM, (caddr_t)&ieeprom) != -1) chosen_eeprom = (pnode_t)prom_decode_int(ieeprom); root = prom_nextnode((pnode_t)0); /* * Get System clock frequency from root node if it exists. */ if (GETPROP(root, "stick-frequency", (caddr_t)&stick_freq) != -1) system_clock_freq = stick_freq; map_wellknown(NEXT((pnode_t)0)); /* * See if it worked */ for (wkp = wkdevice; wkp->wk_namep; ++wkp) { if (wkp->wk_flags == V_MUSTHAVE) { cmn_err(CE_PANIC, "map_wellknown_devices: required " "device %s not mapped", wkp->wk_namep); } } /* * all sun4u systems must have an IO bus, i.e. sbus or pcibus */ if (niobus == 0) cmn_err(CE_PANIC, "map_wellknown_devices: no i/o bus node"); check_cpus_ver(); check_cpus_set(); }
static void have_rtc(pnode_t node) { int size; uint32_t eaddr; /* * "ds1287" module will be selected based on finding a "model" * property value of "ds1287" in the "rtc" node. */ if (tod_module_name == NULL) { char buf[MAXSYSNAME]; if (GETPROP(node, "model", buf) != -1) { if ((strcmp(buf, "m5819p") == 0) || (strcmp(buf, "m5823") == 0)) tod_module_name = "todm5823"; else if (strcmp(buf, "ds1287") == 0) tod_module_name = "todds1287"; } } /* * XXX - drives on if address prop doesn't exist, later falls * over in tod module */ if ((size = GETPROPLEN(node, OBP_ADDRESS)) == -1) return; if (size != sizeof (eaddr)) cmn_err(CE_PANIC, "rtc addr size"); if (GETPROP(node, OBP_ADDRESS, (caddr_t)&eaddr) == -1) cmn_err(CE_PANIC, "rtc addr"); v_rtc_addr_reg = (caddr_t)(uintptr_t)eaddr; v_rtc_data_reg = (volatile unsigned char *)(uintptr_t)eaddr + 1; /* * Does this rtc have watchdog support? */ if (GETPROPLEN(node, WATCHDOG_ENABLE) != -1) watchdog_available = 1; }
int get_portid(pnode_t node, pnode_t *cmpp) { int portid; int i; char dev_type[OBP_MAXPROPNAME]; pnode_t cpu_parent; if (cmpp != NULL) *cmpp = OBP_NONODE; if (GETPROP(node, "portid", (caddr_t)&portid) != -1) return (portid); if (GETPROP(node, "upa-portid", (caddr_t)&portid) != -1) return (portid); if (GETPROP(node, "device_type", (caddr_t)&dev_type) == -1) return (-1); /* * For a virtual cpu node that is a CMP core, the "portid" * is in the parent node. * For a virtual cpu node that is a CMT strand, the "portid" is * in its grandparent node. * So we iterate up as far as 2 levels to get the "portid". */ if (strcmp(dev_type, "cpu") == 0) { cpu_parent = node = prom_parentnode(node); for (i = 0; i < 2; i++) { if (node == OBP_NONODE || node == OBP_BADNODE) break; if (GETPROP(node, "portid", (caddr_t)&portid) != -1) { if (cmpp != NULL) *cmpp = cpu_parent; return (portid); } node = prom_parentnode(node); } } return (-1); }
static void have_tod(pnode_t node) { static char tod_name[MAXSYSNAME]; if (GETPROP(node, OBP_NAME, (caddr_t)tod_name) == -1) cmn_err(CE_PANIC, "tod name"); /* * This is a node with "device_type" property value of "tod". * Name of the tod module is the name from the node. */ tod_module_name = tod_name; }
static void fill_address(pnode_t curnode, char *namep) { struct wkdevice *wkp; int size; uint32_t vaddr; for (wkp = wkdevice; wkp->wk_namep; ++wkp) { if (strcmp(wkp->wk_namep, namep) != 0) continue; if (wkp->wk_flags == V_MAPPED) return; if (wkp->wk_vaddrp != NULL) { if ((size = GETPROPLEN(curnode, OBP_ADDRESS)) == -1) { cmn_err(CE_CONT, "device %s size %d\n", namep, size); continue; } if (size != sizeof (vaddr)) { cmn_err(CE_CONT, "device %s address prop too " "big\n", namep); continue; } if (GETPROP(curnode, OBP_ADDRESS, (caddr_t)&vaddr) == -1) { cmn_err(CE_CONT, "device %s not mapped\n", namep); continue; } /* make into a native pointer */ *wkp->wk_vaddrp = (caddr_t)(uintptr_t)vaddr; #ifdef VPRINTF VPRINTF("fill_address: %s mapped to %p\n", namep, (void *)*wkp->wk_vaddrp); #endif /* VPRINTF */ } if (wkp->wk_func != NULL) (*wkp->wk_func)(curnode); /* * If this one is optional and there may be more than * one, don't set V_MAPPED, which would cause us to skip it * next time around */ if (wkp->wk_flags != V_MULTI) wkp->wk_flags = V_MAPPED; } }
/* * The first sysio must always programmed up for the system clock and error * handling purposes, referenced by v_sysio_addr in machdep.c. */ static void have_sbus(pnode_t node) { int size; uint_t portid; size = GETPROPLEN(node, "upa-portid"); if (size == -1 || size > sizeof (portid)) cmn_err(CE_PANIC, "upa-portid size"); if (GETPROP(node, "upa-portid", (caddr_t)&portid) == -1) cmn_err(CE_PANIC, "upa-portid"); niobus++; /* * need one physical TSB */ niommu_tsbs++; }
void fill_cpu(pnode_t node) { extern int cpu_get_cpu_unum(int, char *, int, int *); struct cpu_node *cpunode; processorid_t cpuid; int portid; int tlbsize; int size; uint_t clk_freq; pnode_t cmpnode; char namebuf[OBP_MAXPROPNAME], unum[UNUM_NAMLEN]; char *namebufp; int proplen; if ((portid = get_portid(node, &cmpnode)) == -1) { cmn_err(CE_PANIC, "portid not found"); } if (GETPROP(node, "cpuid", (caddr_t)&cpuid) == -1) { cpuid = portid; } if (cpuid < 0 || cpuid >= NCPU) { cmn_err(CE_PANIC, "cpu node %x: cpuid %d out of range", node, cpuid); return; } cpunode = &cpunodes[cpuid]; cpunode->portid = portid; cpunode->nodeid = node; if (cpu_get_cpu_unum(cpuid, unum, UNUM_NAMLEN, &size) != 0) { cpunode->fru_fmri[0] = '\0'; } else { (void) snprintf(cpunode->fru_fmri, sizeof (cpunode->fru_fmri), "%s%s", CPU_FRU_FMRI, unum); } if (cmpnode) { /* * For the CMT case, the parent "core" node contains * properties needed below, use it instead of the * cpu node. */ if ((GETPROP(cmpnode, "device_type", namebuf) > 0) && (strcmp(namebuf, "core") == 0)) { node = cmpnode; } } (void) GETPROP(node, (cmpnode ? "compatible" : "name"), namebuf); /* Make sure CPU name is within boundary and NULL terminated */ proplen = GETPROPLEN(node, (cmpnode ? "compatible" : "name")); ASSERT(proplen > 0 && proplen <= OBP_MAXPROPNAME); if (proplen >= OBP_MAXPROPNAME) proplen = OBP_MAXPROPNAME - 1; namebuf[proplen] = '\0'; namebufp = namebuf; if (strncmp(namebufp, "SUNW,", 5) == 0) namebufp += 5; else if (strncmp(namebufp, "FJSV,", 5) == 0) namebufp += 5; (void) strcpy(cpunode->name, namebufp); (void) GETPROP(node, "implementation#", (caddr_t)&cpunode->implementation); (void) GETPROP(node, "mask#", (caddr_t)&cpunode->version); if (IS_CHEETAH(cpunode->implementation)) { /* remap mask reg */ cpunode->version = REMAP_CHEETAH_MASK(cpunode->version); } if (GETPROP(node, "clock-frequency", (caddr_t)&clk_freq) == -1) { /* * If we didn't find it in the CPU node, look in the root node. */ pnode_t root = prom_nextnode((pnode_t)0); if (GETPROP(root, "clock-frequency", (caddr_t)&clk_freq) == -1) clk_freq = 0; } cpunode->clock_freq = clk_freq; ASSERT(cpunode->clock_freq != 0); /* * Compute scaling factor based on rate of %tick. This is used * to convert from ticks derived from %tick to nanoseconds. See * comment in sun4u/sys/clock.h for details. */ cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC << (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq); (void) GETPROP(node, "#itlb-entries", (caddr_t)&tlbsize); ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ cpunode->itlb_size = (ushort_t)tlbsize; (void) GETPROP(node, "#dtlb-entries", (caddr_t)&tlbsize); ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ cpunode->dtlb_size = (ushort_t)tlbsize; if (cmpnode != OBP_NONODE) { /* * If the CPU has a level 3 cache, then it will be the * external cache. Otherwise the level 2 cache is the * external cache. */ size = 0; (void) GETPROP(node, "l3-cache-size", (caddr_t)&size); if (size <= 0) (void) GETPROP(node, "l2-cache-size", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_size = size; size = 0; (void) GETPROP(node, "l3-cache-line-size", (caddr_t)&size); if (size <= 0) (void) GETPROP(node, "l2-cache-line-size", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_linesize = size; size = 0; (void) GETPROP(node, "l2-cache-associativity", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_associativity = size; cmp_add_cpu(portid, cpuid); } else { size = 0; (void) GETPROP(node, "ecache-size", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_size = size; size = 0; (void) GETPROP(node, "ecache-line-size", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_linesize = size; size = 0; (void) GETPROP(node, "ecache-associativity", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_associativity = size; } /* by default set msram to non-mirrored one */ cpunode->msram = ECACHE_CPU_NON_MIRROR; if (GETPROPLEN(node, "msram") != -1) { cpunode->msram = ECACHE_CPU_MIRROR; } if (GETPROPLEN(node, "msram-observed") != -1) { cpunode->msram = ECACHE_CPU_MIRROR; } if (ncpunode == 0) { cpu_fiximp(node); } cpunode->ecache_setsize = cpunode->ecache_size / cpunode->ecache_associativity; adj_ecache_setsize(cpunode->ecache_setsize); ncpunode++; }
/* * map_wellknown - map known devices & registers */ static void map_wellknown(pnode_t curnode) { extern int status_okay(int, char *, int); char tmp_name[MAXSYSNAME]; int sok; #ifdef VPRINTF VPRINTF("map_wellknown(%x)\n", curnode); #endif /* VPRINTF */ for (curnode = CHILD(curnode); curnode; curnode = NEXT(curnode)) { /* * prune subtree if status property indicating not okay */ sok = status_okay((int)curnode, (char *)NULL, 0); if (!sok) { char devtype_buf[OBP_MAXPROPNAME]; int size; #ifdef VPRINTF VPRINTF("map_wellknown: !okay status property\n"); #endif /* VPRINTF */ /* * a status property indicating bad memory will be * associated with a node which has a "device_type" * property with a value of "memory-controller" */ if ((size = GETPROPLEN(curnode, OBP_DEVICETYPE)) == -1) continue; if (size > OBP_MAXPROPNAME) { cmn_err(CE_CONT, "node %x '%s' prop too " "big\n", curnode, OBP_DEVICETYPE); continue; } if (GETPROP(curnode, OBP_DEVICETYPE, devtype_buf) == -1) { cmn_err(CE_CONT, "node %x '%s' get failed\n", curnode, OBP_DEVICETYPE); continue; } if (strcmp(devtype_buf, "memory-controller") != 0) continue; /* * ...else fall thru and process the node... */ } bzero(tmp_name, MAXSYSNAME); if (GETPROP(curnode, OBP_NAME, (caddr_t)tmp_name) != -1) fill_address(curnode, tmp_name); if (GETPROP(curnode, OBP_DEVICETYPE, tmp_name) != -1 && strcmp(tmp_name, "cpu") == 0) { fill_cpu(curnode); } if (strcmp(tmp_name, "tod") == 0) have_tod(curnode); if (sok && (strcmp(tmp_name, "memory-controller") == 0) && (&plat_fill_mc != NULL)) plat_fill_mc(curnode); map_wellknown(curnode); } }