/* * Create a picl node of type cpu and fill it. * properties are filled from both the device tree and the * Machine description. */ static int construct_cpu_node(picl_nodehdl_t plath, di_node_t dn) { int err; char *nodename; picl_nodehdl_t anodeh; nodename = di_node_name(dn); /* PICL_PROP_NAME */ err = ptree_create_and_add_node(plath, nodename, PICL_CLASS_CPU, &anodeh); if (err != PICL_SUCCESS) return (err); add_devinfo_props(anodeh, dn); add_reg_prop(anodeh, dn); (void) add_cpu_prop(anodeh, NULL); return (err); }
/* Creates and adds all of the frutree nodes */ static int add_all_nodes() { picl_nodehdl_t rooth; picl_nodehdl_t chassish; int err; /* Get the root node of the PICL tree */ err = ptree_get_root(&rooth); if (err != PICL_SUCCESS) { return (err); } /* Create and add the root node of the FRU subtree */ err = ptree_create_and_add_node(rooth, "frutree", "picl", &frutreeh); if (err != PICL_SUCCESS) { syslog(LOG_ERR, CREATE_FRUTREE_FAIL); return (err); } /* Create and add the chassis node */ err = ptree_create_and_add_node(frutreeh, "chassis", "fru", &chassish); if (err != PICL_SUCCESS) { syslog(LOG_ERR, CREATE_CHASSIS_FAIL); return (err); } /* Add ViewPoints prop to chassis node */ err = add_viewpoints_prop(chassish, CHASSIS_VIEWPOINTS); if (err != PICL_SUCCESS) return (err); /* Initialize the FRU nodes for the IO board */ err = do_ioboard_init(chassish); if (err != PICL_SUCCESS) { syslog(LOG_ERR, IOBRD_INIT_FAIL); return (err); } /* Initialize the FRU node for the RSC card */ err = do_rscboard_init(chassish); if (err != PICL_SUCCESS) { syslog(LOG_ERR, RSCBRD_INIT_FAIL); return (err); } /* Initialize the FRU nodes for the FCAL backplanes and GBIC board */ err = do_fcal_init(chassish); if (err != PICL_SUCCESS) { syslog(LOG_ERR, FCAL_INIT_FAIL); return (err); } /* Initialize the FRU nodes for the PDB and the power supplies */ err = do_power_supplies_init(chassish); if (err != PICL_SUCCESS) { syslog(LOG_ERR, PS_INIT_FAIL); return (err); } /* Initialize the FRU nodes for the CPU Memory modules */ err = do_motherboard_init(chassish); if (err != PICL_SUCCESS) { syslog(LOG_ERR, SYSBOARD_INIT_FAIL); return (err); } return (PICL_SUCCESS); }
/* * update_picl * Called when disk goes off-line or goes to ready status. * In the case of disk ready, locate platform tree node for the disk * and add a target property (if missing). * (The target address is fixed for a given disk slot and is used to * tie the frutree disk-unit to the correct ssd node). * Returns EAGAIN for a retriable failure, otherwise 0. */ static int update_picl(led_dtls_t *dtls, int disk) { static char trailer[] = ",0"; picl_nodehdl_t slotndh; picl_nodehdl_t diskndh; ptree_propinfo_t propinfo; int r; if (dtls->disk_detected[disk] != 0) { picl_nodehdl_t fpndh; picl_nodehdl_t ssdndh; picl_prophdl_t tbl_h; picl_prophdl_t tbl_prop_h; picl_prophdl_t row_props_h[FCAL_DEVTABLE_NCOLS]; char valbuf[80]; char addr[MAXPATHLEN]; char *ptrd; const uchar_t *ptrs; int len; int addr_len; for (;;) { r = ptree_get_node_by_path(dtls->fcal_disk_parent, &fpndh); if (r != PICL_SUCCESS) { return (0); } r = ptree_get_propval_by_name(fpndh, PICL_PROP_CLASSNAME, (void *)valbuf, sizeof (valbuf)); if (r != PICL_SUCCESS) { return (0); } else if (strcmp(valbuf, "fp") == 0) { /* * The node with class fp (if present) is a * holding node representing no actual hardware. * Its presence results in two nodes with the * same effective address. (The fp class node is * UnitAddress 0,0 and the other fp node [class * devctl] has bus-addr 0,0). Locating the * required fp node for dynamic reconfiguration * then goes wrong. So, just remove it. */ SYSLOG(LOG_WARNING, EM_SPURIOUS_FP); r = ptree_delete_node(fpndh); if (r == PICL_SUCCESS) { (void) ptree_destroy_node(fpndh); continue; } return (0); } else { break; } } /* * Got a good parent node. Look at its children for a node * with this new port name. * * generate expected bus-addr property from the port-wwn * Note: dtls->disk_port[disk] points to an array of uchar_t, * the first character contains the length of the residue. * The bus-addr property is formatted as follows: * wabcdef0123456789,0 * where the 16 hex-digits represent 8 bytes from disk_port[]; */ ptrs = dtls->disk_port[disk]; if (ptrs == NULL) return (0); len = *ptrs++; ptrd = addr; *ptrd++ = 'w'; for (r = 0; r < len; r++, ptrd += 2) { (void) snprintf(ptrd, MAXPATHLEN - (ptrd - addr), "%.2x", *ptrs++); } addr_len = 1 + strlcat(addr, trailer, MAXPATHLEN); if (addr_len > MAXPATHLEN) return (0); r = ptree_find_node(fpndh, FCAL_PICL_PROP_BUS_ADDR, PICL_PTYPE_CHARSTRING, addr, addr_len, &ssdndh); /* * If the disk node corresponding to the newly inserted disk * cannot be found in the platform tree, we have probably * got in too early - probably before it's up to speed. In * this case, the WWN gleaned from devinfo may also be wrong. * This case is worth retrying in later polls when it may * succeed, so return EAGAIN. All other failures are probably * terminal, so log a failure and quit. */ if (r == PICL_NODENOTFOUND) return (EAGAIN); if (r != PICL_SUCCESS) { SYSLOG(LOG_ERR, EM_NO_FP_NODE, disk); return (0); } /* * Found platform entry for disk, add target prop */ r = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_INT, PICL_READ, sizeof (int), FCAL_PICL_PROP_TARGET, NULL, NULL); if (r != PICL_SUCCESS) return (0); (void) ptree_create_and_add_prop(ssdndh, &propinfo, &disk, NULL); /* * Remove pre-existing disk-unit node and its * properties - maybe its reference property is * out-of-date. */ delete_disk_unit(dtls, disk); /* * Add a disk-unit node in frutree */ r = find_disk_slot(dtls, disk, &slotndh); if (r != PICL_SUCCESS) return (0); r = ptree_create_and_add_node(slotndh, fcal_disk_unit, PICL_CLASS_FRU, &diskndh); if (r != PICL_SUCCESS) return (0); r = create_Device_table(&tbl_h, &tbl_prop_h); if (r != PICL_SUCCESS) return (0); r = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, sizeof (PICL_CLASS_BLOCK), PICL_PROP_CLASS, NULL, NULL); if (r != PICL_SUCCESS) return (0); r = ptree_create_prop(&propinfo, PICL_CLASS_BLOCK, &row_props_h[0]); if (r != PICL_SUCCESS) return (0); r = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_prophdl_t), FCAL_PICL_BLOCK_REF, NULL, NULL); if (r != PICL_SUCCESS) return (0); r = ptree_create_prop(&propinfo, &ssdndh, &row_props_h[1]); if (r != PICL_SUCCESS) return (0); r = ptree_add_row_to_table(tbl_h, FCAL_DEVTABLE_NCOLS, row_props_h); if (r != PICL_SUCCESS) return (0); (void) ptree_add_prop(diskndh, tbl_prop_h); } else { /* * disk gone, remove disk_unit fru from frutree */ delete_disk_unit(dtls, disk); } return (0); }
static int add_fan_nodes_and_props(picl_nodehdl_t plath) { int err; char *pname, *nodename, *devfs_path; env_fan_t *fanp; fan_node_t *fnodep; picl_nodehdl_t nodeh, cnodeh; picl_prophdl_t proph; node_list_t *node_list, *listp; node_list = get_node_list_by_class(plath, PICL_CLASS_FAN_CONTROL, NULL); if (node_list == NULL) return (PICL_FAILURE); for (listp = node_list; listp != NULL; listp = listp->next) { /* * Add various fan nodes and properties */ nodeh = listp->nodeh; err = PICL_SUCCESS; for (fnodep = fan_nodes; fnodep->fan_name != NULL; fnodep++) { /* Skip if already initialized or no fan info */ if (fnodep->nodeh != NULL || fnodep->fanp == NULL) continue; /* * Create "fan" class node and save node handle */ nodename = fnodep->fan_name; err = ptree_create_and_add_node(nodeh, nodename, PICL_CLASS_FAN, &cnodeh); if (env_debug) envd_log(LOG_INFO, "Creating PICL fan node '%s' err:%d\n", nodename, err); if (err != PICL_SUCCESS) break; fnodep->nodeh = cnodeh; /* * Add "devfs_path" property in child node */ fanp = fnodep->fanp; devfs_path = fanp->devfs_path; pname = PICL_PROP_DEVFS_PATH; err = add_regular_prop(cnodeh, pname, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(devfs_path)+1, (void *)devfs_path, &proph); if (err != PICL_SUCCESS) break; /* * Add "Speed" volatile property in this "fan" * class node and save prop handle. */ pname = PROP_FAN_SPEED; err = add_volatile_prop(cnodeh, pname, PICL_PTYPE_INT, PICL_READ, sizeof (fanspeed_t), get_current_speed, NULL, &proph); if (err != PICL_SUCCESS) break; fnodep->proph = proph; /* * Add other "fan" class properties */ pname = PROP_FAN_SPEED_UNIT, err = add_regular_prop(cnodeh, pname, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(fnodep->speed_unit)+1, (void *)fnodep->speed_unit, &proph); if (err != PICL_SUCCESS) break; } if (err != PICL_SUCCESS) { delete_fan_nodes_and_props(); free_node_list(node_list); if (env_debug) envd_log(LOG_WARNING, "Can't create prop/node for fan '%s'\n", nodename); return (err); } } free_node_list(node_list); return (PICL_SUCCESS); }
static int add_sensor_nodes_and_props(picl_nodehdl_t plath) { int err; char *pname, *nodename, *refnode, *devfs_path; node_list_t *node_list, *listp; sensor_node_t *snodep; sensor_thresh_t *threshp; picl_nodehdl_t nodeh, refnodeh, cnodeh; picl_prophdl_t proph; char unitaddr[UNITADDR_LEN_MAX]; env_sensor_t *sensorp; node_list = get_node_list_by_class(plath, PICL_CLASS_TEMP_DEVICE, NULL); if (node_list == NULL) return (PICL_FAILURE); for (listp = node_list; listp != NULL; listp = listp->next) { /* * Get "reg" property. Skip if no "reg" property found. */ nodeh = listp->nodeh; err = get_unit_address_prop(nodeh, (void *)unitaddr, sizeof (unitaddr)); if (err != PICL_SUCCESS) continue; for (snodep = sensor_nodes; snodep->sensor_name != NULL; snodep++) { /* Match "UnitAddress" property */ if (strcasecmp(unitaddr, snodep->unitaddr) != 0) continue; /* * Skip if already initialized or no sensor info */ sensorp = snodep->sensorp; if (snodep->nodeh != NULL || sensorp == NULL) continue; /* * Create temperature-sensor node */ nodename = snodep->sensor_name; err = ptree_create_and_add_node(nodeh, nodename, PICL_CLASS_TEMP_SENSOR, &cnodeh); if (env_debug) envd_log(LOG_INFO, "Creating PICL sensor node '%s' err:%d\n", nodename, err); if (err != PICL_SUCCESS) break; /* save node handle */ snodep->nodeh = cnodeh; /* * Add "devfs_path" property in child node */ devfs_path = sensorp->devfs_path; pname = PICL_PROP_DEVFS_PATH; err = add_regular_prop(cnodeh, pname, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(devfs_path)+1, (void *)devfs_path, &proph); if (err != PICL_SUCCESS) break; /* * Now add volatile "temperature" volatile property * in this "temperature-sensor" class node. */ pname = PROP_TEMPERATURE; err = add_volatile_prop(cnodeh, pname, PICL_PTYPE_INT, PICL_READ, sizeof (tempr_t), get_current_temp, NULL, &proph); if (err != PICL_SUCCESS) break; /* Save prop handle */ snodep->proph = proph; /* * Add threshold related properties */ threshp = sensorp->temp_thresh; if (threshp != NULL) add_sensor_thresh_props(cnodeh, threshp); /* * Finally create property in the sensed device * (if one specified) */ refnode = snodep->sdev_node; pname = snodep->sdev_pname; if (refnode == NULL || pname == NULL) continue; err = ptree_get_node_by_path(refnode, &refnodeh); if (err == PICL_SUCCESS) { err = add_volatile_prop(refnodeh, pname, PICL_PTYPE_INT, PICL_READ, sizeof (tempr_t), get_current_temp, NULL, &proph); } if (err != PICL_SUCCESS) break; /* Save prop handle */ snodep->sdev_proph = proph; } if (err != PICL_SUCCESS) { delete_sensor_nodes_and_props(); free_node_list(node_list); if (env_debug) envd_log(LOG_INFO, "Can't create prop/node for sensor '%s'\n", nodename); return (err); } } free_node_list(node_list); return (PICL_SUCCESS); }