fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Function prototypes */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic fpcfga_ret_t get_xport_devlink(const char *hba_phys,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic char ctoi(char c);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic fpcfga_ret_t is_apid_configured(const char *xport_phys,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *dyncomp, struct luninfo_list **lunlistpp, int *l_errnop);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic fpcfga_ret_t insert_lun_to_lunlist(struct luninfo_list **lunlistpp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char *dyncomp, di_node_t devnode, int *l_errnop);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic fpcfga_ret_t update_lunlist(struct luninfo_list **lunlistpp, int lun,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Globals */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Various conversions routines */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortecvt_lawwn_to_dyncomp(const la_wwn_t *pwwn, char **dyncomp, int *l_errnop)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortecvt_dyncomp_to_lawwn(const char *dyncomp, la_wwn_t *port_wwn)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Generates the HBA logical ap_id from physical ap_id.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortemake_xport_logid(const char *xport_phys, char **xport_logpp, int *l_errnop)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * A devlink for the XPORT should exist. Without the /dev/cfg link
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * driver name and instance number based based link needs to be
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * constructed for the minor node type of DDI_NT_FC_ATTACHMENT_POINT.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * sunddi.h defines DDI_NT_FC_ATTACHMENT_POINT for
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ddi_ctl:attachment_point:fc
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (get_xport_devlink(xport_phys, xport_logpp, l_errnop) == FPCFGA_OK) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteget_xport_devlink(const char *xport_phys, char **xport_logpp, int *l_errnop)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = physpath_to_devlink(CFGA_DEV_DIR, (char *)xport_phys,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Remove the "/dev/cfg/" prefix */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Given a xport path and dynamic ap_id, returns the physical
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * path in pathpp. If the dynamic ap is not configured pathpp set to NULL
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and returns FPCFGA_APID_NOCONFIGURE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* A device MUST have a dynamic component */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = is_apid_configured(xport_phys, dyncomp, lunlistpp, l_errnop);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When both the transport and dynamic comp are given this function
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * checks to see if the dynamic ap is configured on the dev tree.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If it is configured the devfs path will be stored in pathpp.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When the dynamic comp is null this function check to see if the transport
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * node has any child.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Retrun value: FPCFGA_OK if the apid is configured.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FPCFGA_APID_NOCONFIGURE if the apid is not configured.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FPCFGA_LIB_ERR for other errors.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char *devfs_phys, *devfs_fp_path, *client_path, *cp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte di_node_t tree_root, root, fpnode, dev_node, client_node;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (strncmp(devfs_phys, DEVICES_DIR SLASH, strlen(DEVICES_DIR) +
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cp = strstr(devfs_phys, MINOR_SEP)) != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((tree_root = di_init("/", DINFOCPYALL | DINFOPATH))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * when there is no child and path info node the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FPCFGA_APID_NOCONFIGURE is returned
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * regardless of the dynamic comp.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((dev_node == DI_NODE_NIL) && (path == DI_PATH_NIL)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * when dyn comp is null the function just checks if there is any
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * child under fp transport attachment point.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * now checks the children node to find
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if dynamic ap is configured. if there are multiple luns
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * store into lunlist.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* is property name port-wwn */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * now checks the path info node to find
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if dynamic ap is configured. if there are multiple luns
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * store into lunlist.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * now parse the path info node.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte count = di_path_prop_lookup_bytes(path, PORT_WWN_PROP,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* if matches get the path of scsi_vhci child node. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the node is
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * state then check the devfs_path to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * see if it has a complete path.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For non scsi_vhci node the path
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * doesn't contain @w(portwwn) part
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * consistently. For scsi_vhci
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * this behavior may not be there.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * To be safe @g(guid) is attempted
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to be added here.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* is property name lun-wwn */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while ((prop_lun = di_prop_next(dev_node, prop_lun)) != DI_PROP_NIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!(strcmp(LUN_PROP, di_prop_name(prop_lun))) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * stores state info in state.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This information is used to get the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * validity of path.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if driver_detached don't try to get
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the devfs_path since it is not
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * complete. ex, /pci@1f,2000/pci@1/
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * SUNW,qlc@5/fp@0,0/ssd
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * which doesn't contain the port wwn
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * part. The attached node looks like
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * /pci@1f,2000/pci@1/SUNW,qlc@5/fp@0,0/
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ssd@w2100002037006b14,0
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sprintf(&path_name[strlen(path_name)], "@w%s,%x", dyncomp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte devlen = strlen(DEVICES_DIR) + strlen(path_name) + 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) snprintf(pathp, devlen, "%s%s", DEVICES_DIR, path_name);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (update_lunlist(lunlistpp, *lunp, state, pathp, l_errnop));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte newlun = curlun = prevlun = (struct luninfo_list *)NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte newlun = calloc(1, sizeof (struct luninfo_list));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* if lunlist is empty add the new lun info and return. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* if the first lun in the list is the same as the new lun return. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if the first lun in the list is less than the new lun add the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * new lun as the first lun and return.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if the first lun in the list is greater than the new lun and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * there is a single lun add new lun after the first lun and return.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * now there is more than two luns in the list and the first lun
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is greter than the input lun.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* add the new lun at the end of list. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* now get port-wwn for the input node. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while ((prop = di_prop_next(node, prop)) != DI_PROP_NIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!(strcmp(PORT_WWN_PROP, di_prop_name(prop))) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * di_prop* returns the number of entries found or 0 if not found
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or -1 for othere failure.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) sprintf(*dyncompp, "%016llx", (wwnConversion(port_wwn_data)));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * di_prop* returns the number of entries found or 0 if not found
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or -1 for othere failure.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) sprintf(*dyncompp, "%016llx", (wwnConversion(port_wwn_data)));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char *devfs_path, path_name[MAXPATHLEN], *lun_guid, *port_wwn;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte is_scsi_vhci_dev = (strstr(path_name, SCSI_VHCI_DRVR) != NULL) ? 1 : 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the node is
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * state then check the devfs_path to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * see if it has a complete path.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For non scsi_vhci node the path
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * doesn't contain @w(portwwn) part
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * consistently. For scsi_vhci
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * this behavior may not be there.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * To be safe @g(guid) is attempted
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to be added here.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte di_ret = di_prop_lookup_strings(DDI_DEV_T_ANY, node,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte di_ret = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,