2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. 2N/A * A topo_list_t of all disks is returned by a successful disk_list_gather() 2N/A * call, and the list is freed by a disk_list_free(). To create a 'disk' topo 2N/A * node below a specific 'bay' parent node either disk_declare_path() or 2N/A * disk_declare_addr() are called. The caller determines which 'disk' is 2N/A * in which 'bay'. A disk's 'label' and 'authority' information come from 2N/A * its parent 'bay' node. 2N/A/* common callback information for di_walk_node() and di_devlink_walk */ 2N/A * Temporary until DDI_NT_SGEN is moved from sgen to ddi header 2N/A * Set the properties of the disk node, from dev_di_node_t data. 2N/A * Properties include: 2N/A * group: protocol properties: resource, asru, label, fru 2N/A * group: authority properties: chassis-name, chassis-serial, chassis-part 2N/A * group: io properties: devfs-path, devid 2N/A * group: storage properties: 2N/A * - logical-disk, disk-model, disk-manufacturer, serial-number 2N/A * - firmware-revision, capacity-in-bytes 2N/A * NOTE: the io and storage groups won't be present if the dnode passed in is 2N/A * NULL. This happens when a disk is found through ses, but is not enumerated 2N/A * in the devinfo tree. 2N/A /* pull the label property down from our parent 'bay' node */ 2N/A /* get the resource fmri, and use it as the fru */ 2N/A /* create the storage group */ 2N/A /* no dnode was found for this disk - skip the io and storage groups */ 2N/A /* form and set the asru */ 2N/A /* set the storage group public /dev name */ 2N/A /* populate other misc storage group properties */ 2N/A * Pull the chassis name and serial number down from our receptacle 2N/A * 'bay' node (with value of UNKNOWN if not found). 2N/A /* Get string fmri of receptacle. */ 2N/A /* make cro for empty receptacle (no occupant info) */ 2N/A * Trim leading and trailing whitespace from the string. 2N/A * Manufacturing strings can contain characters that are invalid for use in hc 2N/A * authority names. This trims leading and trailing whitespace, and 2N/A * substitutes any characters known to be bad. 2N/A * create the disk topo node. 2N/A * 0 : either successful binding or a node is already bound. 2N/A * when a node is already bound the *dtnp is not set. 2N/A "hcfmri (%s%d/%s%d) error %s\n",
2N/A * if disk 0 is already there then we're done 2N/A "bind (%s%d/%s%d) error %s\n",
2N/A /* add the properties of the disk */ 2N/A "disk_set_props (%s%d/%s%d) error %s\n",
2N/A "disk_cro_mk (%s%d/%s%d) error %s\n",
2N/A * calls disk_tnode_create(). 2N/A * 0 : resulted disk tnode is not NULL. 2N/A * resulted disk tnode is NULL but disk_tnode_create() returns success 2N/A * because it detected the disk tnode is already bound. 2N/A * -1 : resulted disk tnode is NULL and no disk node is already bound. 2N/A "disk_tnode_create error %s\n",
2N/A * declares the disk node with given the device path. 2N/A * 0 or -1 returned by disk_declare(). 2N/A * 1 : no matching devinfo node exists. 2N/A * Check for match using physical phci (ddn_ppaths). Use 2N/A * di_devfs_path_match so generic.vs.non-generic names match. 2N/A "failed to find disk matching path %s",
path);
2N/A * declares the disk node with given the device devid. 2N/A * The devid should be the resulted value from from devid_str_encode(). 2N/A * 0 or -1 returned by disk_declare(). 2N/A * 1 : no matching devinfo node exists. 2N/A * Check for match using physical phci (ddn_ppaths). Use 2N/A * di_devfs_path_match so generic.vs.non-generic names match. 2N/A "failed to find disk matching devid %s",
devid);
2N/A * declares the disk node with given the target port addreess. 2N/A * 0 or -1 returned by disk_declare(). 2N/A * 1 : no matching devinfo node exists. 2N/A /* Check for match using addr. */ 2N/A "found disk matching addr %s",
addr);
2N/A "failed to find disk matching target_port addr %s",
addr);
2N/A * declares the disk node with given the target port addreesses. 2N/A * 0, -1 or 1 returned by disk_declare_target_port(). 2N/A * 1 : all target port(s) failed to be enumerated. 2N/A /* Check for match using addr. */ 2N/A * when one target port is handled okay remaining 2N/A * target port info is already reflected to 2N/A * the resulted disk node so no need to continue. 2N/A * rval is 1 when no matching devinfo node is found. 2N/A * continue to next target port. 2N/A "given target port(s) failed to be enumerated.\n");
2N/A * Used to declare a disk that has been discovered through other means (usually 2N/A * ses), that is not enumerated in the solaris devinfo tree. 2N/A * Used to declare an empty receptacle. 2N/A * This function adds a new item to a ddm the array-of-pointers-to-string. 2N/A * An example call would look like: 2N/A * aps_add(mod, &dnode->ddn_lpaths, &dnode->ddn_lpaths_n, new); 2N/A * We don't have topo_mod_realloc, so we need to do the realloc by hand. 2N/A int n = *
p_n;
/* current number of elements */ 2N/A return (-
1);
/* bad call */ 2N/A return (-
1);
/* out of memory */ 2N/A return (-
1);
/* bad call */ 2N/A for (i = 0; i < n; i++)
2N/A for (i = 0; i < n; i++)
2N/A/* di_devlink callback to add an lpath to a dnode */ 2N/A /* trim the dsk/rdsk and slice off the public name */ 2N/A for (i = 0; i < n; i++) {
2N/A/* Add devinfo information to a dnode */ 2N/A /* cache various bits of new information about the device. */ 2N/A /* form synthetic part number for disks */ 2N/A * To save kernel memory, the driver may not define 2N/A * "device-blksize" when its value is default DEV_BSIZE. 2N/A node,
"fm-ereport-capable", &s) == 0);
2N/A /* A devinfo node may add a dpath */ 2N/A /* A non-scsi_vhci devinfo node may also be a ppath */ 2N/A * A devinfo node may also add an lpath, pick any minor name so 2N/A * that we don't have a dependency on a specific minor name having 2N/A * been created duringing attach. 2N/A /* A devinfo may add a target_port. */ 2N/A /* A devinfo may add a attached_port. */ 2N/A /* A devinfo may add a bridge_port. */ 2N/A/* Add pathinfo information to a dnode */ 2N/A /* A pathinfo may add a ppath */ 2N/A /* A pathinfo may add a target_port. */ 2N/A /* A pathinfo may add a attached_port. */ 2N/A /* A pathinfo may add a bridge_port. */ 2N/A /* free the stuff we point to */ 2N/A /* NOTE: topo_mod_strfree does NULL checking. */ 2N/A /* free array of pointers to strings */ 2N/A * NOTE: if there is no devid, then we can end up with duplicate 2N/A * dnodes, but this doesn't do any harm. 2N/A /* Check for duplicate using devid search. */ 2N/A /* Add devinfo information to dnode. */ 2N/A * Establish the physical ppath and target ports. If the device is 2N/A * non-mpxio then dpath and ppath are the same, and the target port is a 2N/A * property of the device node. 2N/A * If dpath is a client node under scsi_vhci, then iterate over all 2N/A * paths and get their physical paths and target port properrties. 2N/A * di_path_client_next_path call below will 2N/A * return non-NULL, and ppath is set to the physical path to the first 2N/A * NOTE: It is possible to get a generic.vs.non-generic path 2N/A * for di_devfs_path.vs.di_path_devfs_path like: 2N/A * xml: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/sd@2,0 2N/A * pnode: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/disk@2,0 2N/A * To resolve this issue disk_declare_path() needs to use the 2N/A * special di_devfs_path_match() interface. 2N/A /* Add pathinfo information to dnode */ 2N/A /* Print some information about dnode for debug. */ 2N/A/* di_walk_node callback for disk_list_gather */ 2N/A * Check the node type so we done trigger on nodes that happen to use 2N/A * the same property names that we're interested in. 2N/A * If it's not a scsi_vhci client and doesn't have a target_port 2N/A * property and doesn't have a target property then it's not a storage 2N/A * device and we're not interested. 2N/A * NOTE: dev_list_gather should be moved out and done just after 2N/A * di_init devinfo snapshot so that we only do this once per snapshot 2N/A "topo_mod_devinfo() failed");
2N/A "topo_mod_devlink() failed");
2N/A /* walk the devinfo snapshot looking for disk nodes */