/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Implements auxiliary routines declared in pcp_utils.h to facilitate
* finding the appropriate communication transport & device path for a
* given service. This supports the transition from the legacy service channel
* transport (glvc) to the logical domain channel (vldc) transport native
* to platforms running Logical Domains (LDoms).
*/
#include <fcntl.h>
#include <strings.h>
#include <stdlib.h>
#include <libgen.h>
#include <unistd.h>
#include <stdio.h>
#include <libdevinfo.h>
#include "pcp_utils.h"
/*
* The mechanism to relate a service to a device path is different for
* vldc and glvc, due to the way the device pathnames are encoded:
* Sample service: sunvts
* Service Name: SUNW,sun4v-sunvts
* GLVC device path:
* "/devices/virtual-devices@100/sunvts@a:glvc"
* VLDC device path:
* "/devices/virtual-devices@100/channel-devices@200/virtual-channel@3:sunvts"
*
* As VLDC is the communication mechanism used in an LDoms environment, it is
* the preferred channel, and its existence is checked for first.
*/
/*
* Extract from dev_path the "service name" portion.
* For vldc, the service corresponds to the minor name of the device path
* (e.g. virtual-channel@3:sunvts for sunvts). If service is non-NULL, it must
* match the extracted service name for the function to succeed.
* The service name is returned in match (if non-NULL), and the function
* itself returns true on success; false on failure.
*/
static bool_t
{
char *devname, *s;
return (false);
if (s++ == NULL) {
goto end;
}
/*
* If in addition, a service string is specified to
* be matched, do a comparison
*/
if (match)
ret = true;
goto end;
} else {
ret = false;
goto end;
}
} else if (match) {
}
ret = true;
goto end;
}
end:
return (ret);
}
/*
* Extract from dev_path the "service name" portion.
* For glvc, the service corresponds to the node name of the device path
* (e.g. sunvts@a:glvc for sunvts). If service is non-NULL, it must
* match the extracted service name for the function to succeed.
* The service name is returned in match (if non-NULL), and the function
* itself returns true on success; false on failure.
*/
static bool_t
{
int len;
return (false);
ret = false;
goto end;
}
ret = false;
goto end;
}
/*
* If a service string is specified, check if there
* is a match
*/
ret = false;
if (*match)
}
end:
return (ret);
}
/*
* This routine accepts either a prefixed service name or a legacy full
* pathname (which might not even exist in the filesystem), and in either case
* returns a canonical service name. If the parameter is neither a service
* name (i.e. with a "SUNW,sun4v-" prefix), nor a path to a legacy glvc or
* vldc device, NULL is returned.
*/
char *
{
/*
* First check whether a service name
*/
return (sname);
}
/*
* Not a service name, check if it's a valid pathname
*/
return (NULL);
}
/*
* Ideally, we should only check for a valid glvc pathname,
* requiring all vldc access to be only via service names. But
* to prevent a flag day with code that's already passing in
* vldc full pathnames (e.g. sunMC), we allow them here.
*/
return (vldc_path);
return (glvc_path);
}
return (NULL);
}
/*
* Walk all "service" device nodes to find the one with the
* matching glvc minor name
*/
static char *
{
char *glvc_path;
char *minor_name;
return (NULL);
/* Ensure that the 'glvc' driver is loaded */
if (root_node == DI_NODE_NIL) {
return (dev_path);
}
while (service_node != DI_NODE_NIL) {
/* Make sure node name matches service name */
/* Walk minor nodes */
while (minor != DI_NODE_NIL) {
break;
}
}
}
break;
}
return (dev_path);
}
/*
* Walk all vldc device nodes to find the one with the
* matching minor name
*/
static char *
{
char *vldc_path;
char *minor_name;
/* Ensure that the 'vldc' driver is loaded */
if (root_node == DI_NODE_NIL) {
return (dev_path);
}
while (vldc_node != DI_NODE_NIL) {
/* Walk minor nodes */
while (minor != DI_NODE_NIL) {
break;
}
}
break;
}
return (dev_path);
}
/*
* Given a service name or a full legacy pathname, return
* the full pathname to the appropriate vldc or glvc device.
*/
char *
{
char *pathn_p;
char *service;
return (NULL);
/*
* First lookup vldc nodes
*/
*type = VLDC_STREAMING;
} else {
/*
* If no vldc, try to find a glvc node
*/
*type = GLVC_NON_STREAM;
}
}
return (pathn_p);
}