11ae08745Sheppo /* 21ae08745Sheppo * CDDL HEADER START 31ae08745Sheppo * 41ae08745Sheppo * The contents of this file are subject to the terms of the 51ae08745Sheppo * Common Development and Distribution License (the "License"). 61ae08745Sheppo * You may not use this file except in compliance with the License. 71ae08745Sheppo * 81ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91ae08745Sheppo * or http://www.opensolaris.org/os/licensing. 101ae08745Sheppo * See the License for the specific language governing permissions 111ae08745Sheppo * and limitations under the License. 121ae08745Sheppo * 131ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each 141ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the 161ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 171ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 181ae08745Sheppo * 191ae08745Sheppo * CDDL HEADER END 201ae08745Sheppo */ 211ae08745Sheppo 221ae08745Sheppo /* 23*b5353d91SAbhinandan Ekande * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 241ae08745Sheppo * Use is subject to license terms. 251ae08745Sheppo */ 261ae08745Sheppo 271ae08745Sheppo #include <sys/types.h> 281ae08745Sheppo #include <sys/esunddi.h> 291ae08745Sheppo #include <sys/promif_impl.h> 301ae08745Sheppo 311ae08745Sheppo #ifdef _KMDB 321ae08745Sheppo static pnode_t chosennode; 331ae08745Sheppo static pnode_t optionsnode; 341ae08745Sheppo #else 351ae08745Sheppo static char *gettoken(char *tp, char *token); 361ae08745Sheppo static pnode_t finddevice(char *path); 371ae08745Sheppo #endif 381ae08745Sheppo 391ae08745Sheppo /* 401ae08745Sheppo * Routines for walking the PROMs devinfo tree 411ae08745Sheppo */ 421ae08745Sheppo 431ae08745Sheppo #ifdef _KMDB 441ae08745Sheppo 451ae08745Sheppo void 461ae08745Sheppo promif_set_nodes(pnode_t chosen, pnode_t options) 471ae08745Sheppo { 481ae08745Sheppo chosennode = chosen; 491ae08745Sheppo optionsnode = options; 501ae08745Sheppo } 511ae08745Sheppo 521ae08745Sheppo int 531ae08745Sheppo promif_finddevice(void *p) 541ae08745Sheppo { 551ae08745Sheppo cell_t *ci = (cell_t *)p; 561ae08745Sheppo char *path; 571ae08745Sheppo 581ae08745Sheppo ASSERT(ci[1] == 1); 591ae08745Sheppo 601ae08745Sheppo path = p1275_cell2ptr(ci[3]); 611ae08745Sheppo 621ae08745Sheppo if (strcmp("/chosen", path) == 0) { 631ae08745Sheppo ci[4] = p1275_dnode2cell(chosennode); 641ae08745Sheppo } else if (strcmp("/options", path) == 0) { 651ae08745Sheppo ci[4] = p1275_dnode2cell(optionsnode); 661ae08745Sheppo } else { 671ae08745Sheppo /* only supports known nodes */ 681ae08745Sheppo ASSERT(0); 691ae08745Sheppo } 701ae08745Sheppo 711ae08745Sheppo return (0); 721ae08745Sheppo } 731ae08745Sheppo 741ae08745Sheppo #else 751ae08745Sheppo 761ae08745Sheppo int 771ae08745Sheppo promif_finddevice(void *p) 781ae08745Sheppo { 791ae08745Sheppo cell_t *ci = (cell_t *)p; 801ae08745Sheppo pnode_t node; 811ae08745Sheppo 821ae08745Sheppo ASSERT(ci[1] == 1); 831ae08745Sheppo 84*b5353d91SAbhinandan Ekande /* 85*b5353d91SAbhinandan Ekande * We are passing the cpu pointer (CPU->cpu_id) explicitly to 86*b5353d91SAbhinandan Ekande * thread_affinity_set() so that we don't attempt to grab the 87*b5353d91SAbhinandan Ekande * cpu_lock internally in thread_affinity_set() and may sleep 88*b5353d91SAbhinandan Ekande * as a result. 89*b5353d91SAbhinandan Ekande * It is safe to pass CPU->cpu_id and it will always be valid. 90*b5353d91SAbhinandan Ekande */ 91*b5353d91SAbhinandan Ekande thread_affinity_set(curthread, CPU->cpu_id); 921ae08745Sheppo node = finddevice(p1275_cell2ptr(ci[3])); 931ae08745Sheppo 941ae08745Sheppo ci[4] = p1275_dnode2cell(node); 95*b5353d91SAbhinandan Ekande thread_affinity_clear(curthread); 961ae08745Sheppo 971ae08745Sheppo return (0); 981ae08745Sheppo } 991ae08745Sheppo 1001ae08745Sheppo #endif 1011ae08745Sheppo 1021ae08745Sheppo int 1031ae08745Sheppo promif_nextnode(void *p) 1041ae08745Sheppo { 1051ae08745Sheppo cell_t *ci = (cell_t *)p; 1061ae08745Sheppo pnode_t next; 1071ae08745Sheppo 1081ae08745Sheppo ASSERT(ci[1] == 1); 1091ae08745Sheppo 1101ae08745Sheppo next = promif_stree_nextnode(p1275_cell2dnode(ci[3])); 1111ae08745Sheppo 1121ae08745Sheppo ci[4] = p1275_dnode2cell(next); 1131ae08745Sheppo 1141ae08745Sheppo return (0); 1151ae08745Sheppo } 1161ae08745Sheppo 1171ae08745Sheppo int 1181ae08745Sheppo promif_childnode(void *p) 1191ae08745Sheppo { 1201ae08745Sheppo cell_t *ci = (cell_t *)p; 1211ae08745Sheppo pnode_t child; 1221ae08745Sheppo 1231ae08745Sheppo ASSERT(ci[1] == 1); 1241ae08745Sheppo 1251ae08745Sheppo child = promif_stree_childnode(p1275_cell2dnode(ci[3])); 1261ae08745Sheppo 1271ae08745Sheppo ci[4] = p1275_dnode2cell(child); 1281ae08745Sheppo 1291ae08745Sheppo return (0); 1301ae08745Sheppo } 1311ae08745Sheppo 1321ae08745Sheppo int 1331ae08745Sheppo promif_parentnode(void *p) 1341ae08745Sheppo { 1351ae08745Sheppo cell_t *ci = (cell_t *)p; 1361ae08745Sheppo pnode_t parent; 1371ae08745Sheppo 1381ae08745Sheppo ASSERT(ci[1] == 1); 1391ae08745Sheppo 1401ae08745Sheppo parent = promif_stree_parentnode(p1275_cell2dnode(ci[3])); 1411ae08745Sheppo 1421ae08745Sheppo ci[4] = p1275_dnode2cell(parent); 1431ae08745Sheppo 1441ae08745Sheppo return (0); 1451ae08745Sheppo } 1461ae08745Sheppo 1471ae08745Sheppo #ifndef _KMDB 1481ae08745Sheppo 1491ae08745Sheppo /* 1501ae08745Sheppo * Get a token from a prom pathname, collecting everything 1511ae08745Sheppo * until a non-comma, non-colon separator is found. Any 1521ae08745Sheppo * options, including the ':' option separator, on the end 1531ae08745Sheppo * of the token are removed. 1541ae08745Sheppo */ 1551ae08745Sheppo static char * 1561ae08745Sheppo gettoken(char *tp, char *token) 1571ae08745Sheppo { 1581ae08745Sheppo char *result = token; 1591ae08745Sheppo 1601ae08745Sheppo for (;;) { 1611ae08745Sheppo tp = prom_path_gettoken(tp, token); 1621ae08745Sheppo token += prom_strlen(token); 1631ae08745Sheppo if ((*tp == ',') || (*tp == ':')) { 1641ae08745Sheppo *token++ = *tp++; 1651ae08745Sheppo *token = '\0'; 1661ae08745Sheppo continue; 1671ae08745Sheppo } 1681ae08745Sheppo break; 1691ae08745Sheppo } 1701ae08745Sheppo 1711ae08745Sheppo /* strip off any options from the token */ 1721ae08745Sheppo prom_strip_options(result, result); 1731ae08745Sheppo 1741ae08745Sheppo return (tp); 1751ae08745Sheppo } 1761ae08745Sheppo 1771ae08745Sheppo /* 1781ae08745Sheppo * Retrieve the unit address for a node by looking it up 1791ae08745Sheppo * in the corresponding dip. -1 is returned if no unit 1801ae08745Sheppo * address can be determined. 1811ae08745Sheppo */ 1821ae08745Sheppo static int 1831ae08745Sheppo get_unit_addr(pnode_t np, char *paddr) 1841ae08745Sheppo { 1851ae08745Sheppo dev_info_t *dip; 1861ae08745Sheppo char *addr; 1871ae08745Sheppo 1881ae08745Sheppo if ((dip = e_ddi_nodeid_to_dip(np)) == NULL) { 1891ae08745Sheppo return (-1); 1901ae08745Sheppo } 1911ae08745Sheppo 1921ae08745Sheppo if ((addr = ddi_get_name_addr(dip)) == NULL) { 1931ae08745Sheppo ddi_release_devi(dip); 1941ae08745Sheppo return (-1); 1951ae08745Sheppo } 1961ae08745Sheppo 1971ae08745Sheppo (void) prom_strcpy(paddr, addr); 1981ae08745Sheppo 1991ae08745Sheppo ddi_release_devi(dip); 2001ae08745Sheppo 2011ae08745Sheppo return (0); 2021ae08745Sheppo } 2031ae08745Sheppo 2041ae08745Sheppo /* 2051ae08745Sheppo * Get node id of node in prom tree that path identifies 2061ae08745Sheppo */ 2071ae08745Sheppo static pnode_t 2081ae08745Sheppo finddevice(char *path) 2091ae08745Sheppo { 2101ae08745Sheppo char name[OBP_MAXPROPNAME]; 2111ae08745Sheppo char addr[OBP_MAXPROPNAME]; 2121ae08745Sheppo char pname[OBP_MAXPROPNAME]; 2131ae08745Sheppo char paddr[OBP_MAXPROPNAME]; 2141ae08745Sheppo char *tp; 2151ae08745Sheppo pnode_t np; 2161ae08745Sheppo pnode_t device; 2171ae08745Sheppo 2181ae08745Sheppo CIF_DBG_NODE("finddevice: %s\n", path); 2191ae08745Sheppo 2201ae08745Sheppo tp = path; 2211ae08745Sheppo np = prom_rootnode(); 2221ae08745Sheppo device = OBP_BADNODE; 2231ae08745Sheppo 2241ae08745Sheppo /* must be a fully specified path */ 2251ae08745Sheppo if (*tp++ != '/') 2261ae08745Sheppo goto done; 2271ae08745Sheppo 2281ae08745Sheppo for (;;) { 2291ae08745Sheppo /* get the name from the path */ 2301ae08745Sheppo tp = gettoken(tp, name); 2311ae08745Sheppo if (*name == '\0') 2321ae08745Sheppo break; 2331ae08745Sheppo 2341ae08745Sheppo /* get the address from the path */ 2351ae08745Sheppo if (*tp == '@') { 2361ae08745Sheppo tp++; 2371ae08745Sheppo tp = gettoken(tp, addr); 2381ae08745Sheppo } else { 2391ae08745Sheppo addr[0] = '\0'; 2401ae08745Sheppo } 2411ae08745Sheppo 2421ae08745Sheppo CIF_DBG_NODE("looking for: %s%s%s\n", name, 2431ae08745Sheppo (*addr != '\0') ? "@" : "", addr); 2441ae08745Sheppo 2451ae08745Sheppo if ((np = prom_childnode(np)) == OBP_NONODE) 2461ae08745Sheppo break; 2471ae08745Sheppo 2481ae08745Sheppo while (np != OBP_NONODE) { 2491ae08745Sheppo 2501ae08745Sheppo /* get the name from the current node */ 2511ae08745Sheppo if (prom_getprop(np, OBP_NAME, pname) < 0) 2521ae08745Sheppo goto done; 2531ae08745Sheppo 2541ae08745Sheppo /* get the address from the current node */ 2551ae08745Sheppo if (get_unit_addr(np, paddr) < 0) 2561ae08745Sheppo paddr[0] = '\0'; 2571ae08745Sheppo 2581ae08745Sheppo /* compare the names and addresses */ 2591ae08745Sheppo if ((prom_strcmp(name, pname) == 0) && 2601ae08745Sheppo (prom_strcmp(addr, paddr) == 0)) { 2611ae08745Sheppo CIF_DBG_NODE("found dev: %s%s%s (0x%x)\n", 2621ae08745Sheppo pname, (*paddr != '\0') ? "@" : "", 2631ae08745Sheppo paddr, np); 2641ae08745Sheppo break; 2651ae08745Sheppo } else { 2661ae08745Sheppo CIF_DBG_NODE(" no match: %s%s%s vs %s%s%s\n", 2671ae08745Sheppo name, (*addr != '\0') ? "@" : "", addr, 2681ae08745Sheppo pname, (*paddr != '\0') ? "@" : "", paddr); 2691ae08745Sheppo } 2701ae08745Sheppo np = prom_nextnode(np); 2711ae08745Sheppo } 2721ae08745Sheppo 2731ae08745Sheppo /* path does not map to a node */ 2741ae08745Sheppo if (np == OBP_NONODE) 2751ae08745Sheppo break; 2761ae08745Sheppo 2771ae08745Sheppo if (*tp == '\0') { 2781ae08745Sheppo /* found a matching node */ 2791ae08745Sheppo device = np; 2801ae08745Sheppo break; 2811ae08745Sheppo } 2821ae08745Sheppo 2831ae08745Sheppo /* 2841ae08745Sheppo * Continue the loop with the 2851ae08745Sheppo * next component of the path. 2861ae08745Sheppo */ 2871ae08745Sheppo tp++; 2881ae08745Sheppo } 2891ae08745Sheppo done: 2901ae08745Sheppo 2911ae08745Sheppo if (device == OBP_BADNODE) { 2921ae08745Sheppo CIF_DBG_NODE("device not found\n\n"); 2931ae08745Sheppo } else { 2941ae08745Sheppo CIF_DBG_NODE("returning 0x%x\n\n", device); 2951ae08745Sheppo } 2961ae08745Sheppo 2971ae08745Sheppo return (device); 2981ae08745Sheppo } 2991ae08745Sheppo 3001ae08745Sheppo #endif 301