/* * add OBP_REG property to picl cpu node if it's not already there. */ static void add_reg_prop(picl_nodehdl_t pn, di_node_t dn) { int reg_prop[SUN4V_CPU_REGSIZE]; int status; int dlen; int *pdata; ptree_propinfo_t propinfo; status = ptree_get_propval_by_name(pn, OBP_REG, reg_prop, sizeof (reg_prop)); if (status == PICL_SUCCESS) { return; } dlen = di_prom_prop_lookup_ints(ph, dn, OBP_REG, &pdata); if (dlen < 0) { return; } status = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_BYTEARRAY, PICL_READ, dlen * sizeof (int), OBP_REG, NULL, NULL); if (status != PICL_SUCCESS) { return; } (void) ptree_create_and_add_prop(pn, &propinfo, pdata, NULL); }
/* Creates a "FRUDataAvailable" void property for the given PICL node */ static int add_void_fda_prop(picl_nodehdl_t nodeh) { picl_prophdl_t proph; ptree_propinfo_t propinfo; int err; err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_VOID, PICL_READ, 0, "FRUDataAvailable", NULL, NULL); if (err != PICL_SUCCESS) return (err); err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph); if (err != PICL_SUCCESS) return (err); return (PICL_SUCCESS); }
/* Creates a "slot" property for a given PICL node */ static int add_slot_prop(picl_nodehdl_t nodeh, int slotnum) { picl_prophdl_t proph; ptree_propinfo_t propinfo; int err; err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_INT, PICL_READ, 4, "Slot", NULL, NULL); if (err != PICL_SUCCESS) return (err); err = ptree_create_and_add_prop(nodeh, &propinfo, &slotnum, &proph); if (err != PICL_SUCCESS) return (err); return (PICL_SUCCESS); }
static int add_regular_prop(picl_nodehdl_t nodeh, char *name, int type, int access, int size, void *valbuf, picl_prophdl_t *prophp) { int err; ptree_propinfo_t propinfo; picl_prophdl_t proph; err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, type, access, size, name, NULL, NULL); if (err != PICL_SUCCESS) return (err); err = ptree_create_and_add_prop(nodeh, &propinfo, valbuf, &proph); if (err == PICL_SUCCESS && prophp) *prophp = proph; return (err); }
/* * Create and add the specified volatile property */ static int add_volatile_prop(picl_nodehdl_t nodeh, char *name, int type, int access, int size, ptree_vol_rdfunc_t *rdfunc, ptree_vol_wrfunc_t *wrfunc, picl_prophdl_t *prophp) { int err; ptree_propinfo_t propinfo; picl_prophdl_t proph; err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc); if (err != PICL_SUCCESS) return (err); err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph); if (err == PICL_SUCCESS && prophp) *prophp = proph; return (err); }
/* Creates a "ViewPoints" property -- used for chassis */ static int add_viewpoints_prop(picl_nodehdl_t nodeh, char *string) { picl_prophdl_t proph; ptree_propinfo_t propinfo; int err; if (string == NULL) return (PICL_FAILURE); err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(string)+1, "ViewPoints", NULL, NULL); if (err != PICL_SUCCESS) return (err); err = ptree_create_and_add_prop(nodeh, &propinfo, string, &proph); if (err != PICL_SUCCESS) return (err); return (PICL_SUCCESS); }
/* Creates a "Label" property for a given PICL node */ static int add_label_prop(picl_nodehdl_t nodeh, char *label) { picl_prophdl_t proph; ptree_propinfo_t propinfo; int err; if (label == NULL) return (PICL_FAILURE); err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(label)+1, "Label", NULL, NULL); if (err != PICL_SUCCESS) return (err); err = ptree_create_and_add_prop(nodeh, &propinfo, label, &proph); if (err != PICL_SUCCESS) return (err); return (PICL_SUCCESS); }
/* Creates a "reference" property between two PICL nodes */ static int add_ref_prop(picl_nodehdl_t nodeh, picl_nodehdl_t tmph, char *str) { picl_prophdl_t proph; ptree_propinfo_t propinfo; int err; if (str == NULL) return (PICL_FAILURE); err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t), str, NULL, NULL); if (err != PICL_SUCCESS) return (err); err = ptree_create_and_add_prop(nodeh, &propinfo, &tmph, &proph); if (err != PICL_SUCCESS) 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); }
/* * This function is identical to the one in the picldevtree plugin. * Unfortunately we can't just reuse that code. */ int add_string_list_prop(picl_nodehdl_t nodeh, char *name, char *strlist, unsigned int nrows) { ptree_propinfo_t propinfo; picl_prophdl_t proph; picl_prophdl_t tblh; int err; unsigned int i; unsigned int j; picl_prophdl_t *proprow; int len; #define NCOLS_IN_STRING_TABLE 1 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_TABLE, PICL_READ, sizeof (picl_prophdl_t), name, NULL, NULL); if (err != PICL_SUCCESS) return (err); err = ptree_create_table(&tblh); if (err != PICL_SUCCESS) return (err); err = ptree_create_and_add_prop(nodeh, &propinfo, &tblh, &proph); if (err != PICL_SUCCESS) return (err); proprow = alloca(sizeof (picl_prophdl_t) * nrows); if (proprow == NULL) { (void) ptree_destroy_prop(proph); return (PICL_FAILURE); } for (j = 0; j < nrows; ++j) { len = strlen(strlist) + 1; err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, len, name, NULL, NULL); if (err != PICL_SUCCESS) break; err = ptree_create_prop(&propinfo, strlist, &proprow[j]); if (err != PICL_SUCCESS) break; strlist += len; err = ptree_add_row_to_table(tblh, NCOLS_IN_STRING_TABLE, &proprow[j]); if (err != PICL_SUCCESS) break; } if (err != PICL_SUCCESS) { for (i = 0; i < j; ++i) (void) ptree_destroy_prop(proprow[i]); (void) ptree_delete_prop(proph); (void) ptree_destroy_prop(proph); return (err); } return (PICL_SUCCESS); }
/* * This function is identical to the one in the picldevtree plugin. * Unfortunately we can't just reuse that code. */ static void add_devinfo_props(picl_nodehdl_t nodeh, di_node_t di_node) { int instance; char *di_val; di_prop_t di_prop; int di_ptype; ptree_propinfo_t propinfo; instance = di_instance(di_node); (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_INT, PICL_READ, sizeof (instance), PICL_PROP_INSTANCE, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, NULL); di_val = di_bus_addr(di_node); if (di_val) { (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, PICL_PROP_BUS_ADDR, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, NULL); } di_val = di_binding_name(di_node); if (di_val) { (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, PICL_PROP_BINDING_NAME, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, NULL); } di_val = di_driver_name(di_node); if (di_val) { (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, PICL_PROP_DRIVER_NAME, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, NULL); } di_val = di_devfs_path(di_node); if (di_val) { (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, PICL_PROP_DEVFS_PATH, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, NULL); di_devfs_path_free(di_val); } for (di_prop = di_prop_next(di_node, DI_PROP_NIL); di_prop != DI_PROP_NIL; di_prop = di_prop_next(di_node, di_prop)) { di_val = di_prop_name(di_prop); di_ptype = di_prop_type(di_prop); switch (di_ptype) { case DI_PROP_TYPE_BOOLEAN: (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_VOID, PICL_READ, (size_t)0, di_val, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, NULL); break; case DI_PROP_TYPE_INT: { int *idata; int len; len = di_prop_ints(di_prop, &idata); if (len < 0) /* Recieved error, so ignore prop */ break; if (len == 1) (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_INT, PICL_READ, len * sizeof (int), di_val, NULL, NULL); else (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_BYTEARRAY, PICL_READ, len * sizeof (int), di_val, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, idata, NULL); } break; case DI_PROP_TYPE_STRING: { char *sdata; int len; len = di_prop_strings(di_prop, &sdata); if (len < 0) break; if (len == 1) { (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(sdata) + 1, di_val, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, sdata, NULL); } else { (void) add_string_list_prop(nodeh, di_val, sdata, len); } } break; case DI_PROP_TYPE_BYTE: { int len; unsigned char *bdata; len = di_prop_bytes(di_prop, &bdata); if (len < 0) break; (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_BYTEARRAY, PICL_READ, len, di_val, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, bdata, NULL); } break; case DI_PROP_TYPE_UNKNOWN: break; case DI_PROP_TYPE_UNDEF_IT: break; default: break; } } }