112126SHyon.Kim@Sun.COM /*
212126SHyon.Kim@Sun.COM * CDDL HEADER START
312126SHyon.Kim@Sun.COM *
412126SHyon.Kim@Sun.COM * The contents of this file are subject to the terms of the
512126SHyon.Kim@Sun.COM * Common Development and Distribution License (the "License").
612126SHyon.Kim@Sun.COM * You may not use this file except in compliance with the License.
712126SHyon.Kim@Sun.COM *
812126SHyon.Kim@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912126SHyon.Kim@Sun.COM * or http://www.opensolaris.org/os/licensing.
1012126SHyon.Kim@Sun.COM * See the License for the specific language governing permissions
1112126SHyon.Kim@Sun.COM * and limitations under the License.
1212126SHyon.Kim@Sun.COM *
1312126SHyon.Kim@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1412126SHyon.Kim@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512126SHyon.Kim@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1612126SHyon.Kim@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1712126SHyon.Kim@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1812126SHyon.Kim@Sun.COM *
1912126SHyon.Kim@Sun.COM * CDDL HEADER END
2012126SHyon.Kim@Sun.COM */
2112126SHyon.Kim@Sun.COM
2212126SHyon.Kim@Sun.COM /*
2312126SHyon.Kim@Sun.COM * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2412126SHyon.Kim@Sun.COM */
2512126SHyon.Kim@Sun.COM
2612126SHyon.Kim@Sun.COM #include <sys/types.h>
2712126SHyon.Kim@Sun.COM #include <sys/systeminfo.h>
2812126SHyon.Kim@Sun.COM #include <sys/scsi/generic/commands.h>
2912126SHyon.Kim@Sun.COM #include <sys/scsi/impl/commands.h>
3012126SHyon.Kim@Sun.COM
3112126SHyon.Kim@Sun.COM #include <scsi/libsmp.h>
3212126SHyon.Kim@Sun.COM #include <scsi/libsmp_plugin.h>
3312126SHyon.Kim@Sun.COM
3412126SHyon.Kim@Sun.COM #include <dlfcn.h>
3512126SHyon.Kim@Sun.COM #include <link.h>
3612126SHyon.Kim@Sun.COM #include <dirent.h>
3712126SHyon.Kim@Sun.COM #include <string.h>
3812126SHyon.Kim@Sun.COM #include <strings.h>
3912126SHyon.Kim@Sun.COM #include <limits.h>
4012126SHyon.Kim@Sun.COM
4112126SHyon.Kim@Sun.COM #include "smp_impl.h"
4212126SHyon.Kim@Sun.COM
4312126SHyon.Kim@Sun.COM static boolean_t _libsmp_plugin_dlclose;
4412126SHyon.Kim@Sun.COM
4512126SHyon.Kim@Sun.COM /*
4612126SHyon.Kim@Sun.COM * As part of basic initialization, we always retrieve the REPORT GENERAL
4712126SHyon.Kim@Sun.COM * data so that we will know whether this target supports the long response
4812126SHyon.Kim@Sun.COM * format.
4912126SHyon.Kim@Sun.COM */
5012126SHyon.Kim@Sun.COM static int
smp_report_general(smp_target_t * tp)5112126SHyon.Kim@Sun.COM smp_report_general(smp_target_t *tp)
5212126SHyon.Kim@Sun.COM {
5312126SHyon.Kim@Sun.COM smp_action_t *ap;
5412126SHyon.Kim@Sun.COM smp_report_general_resp_t *rp;
5512126SHyon.Kim@Sun.COM smp_result_t result;
5612126SHyon.Kim@Sun.COM size_t len;
5712126SHyon.Kim@Sun.COM
5812126SHyon.Kim@Sun.COM if ((ap = smp_action_alloc(SMP_FUNC_REPORT_GENERAL, tp, 0)) == NULL)
5912126SHyon.Kim@Sun.COM return (-1);
6012126SHyon.Kim@Sun.COM
6112126SHyon.Kim@Sun.COM if (smp_exec(ap, tp) != 0) {
6212126SHyon.Kim@Sun.COM smp_action_free(ap);
6312126SHyon.Kim@Sun.COM return (smp_set_errno(ESMP_REPGEN_FAILED));
6412126SHyon.Kim@Sun.COM }
6512126SHyon.Kim@Sun.COM
6612126SHyon.Kim@Sun.COM smp_action_get_response(ap, &result, (void **)&rp, &len);
6712126SHyon.Kim@Sun.COM
6812126SHyon.Kim@Sun.COM if (result != SMP_RES_FUNCTION_ACCEPTED || len < 24) {
6912126SHyon.Kim@Sun.COM smp_action_free(ap);
7012126SHyon.Kim@Sun.COM return (smp_set_errno(ESMP_REPGEN_FAILED));
7112126SHyon.Kim@Sun.COM }
7212126SHyon.Kim@Sun.COM
7312126SHyon.Kim@Sun.COM bcopy(rp, &tp->st_repgen, sizeof (tp->st_repgen));
7412126SHyon.Kim@Sun.COM
7512126SHyon.Kim@Sun.COM smp_action_free(ap);
7612126SHyon.Kim@Sun.COM
7712126SHyon.Kim@Sun.COM return (0);
7812126SHyon.Kim@Sun.COM }
7912126SHyon.Kim@Sun.COM
8012126SHyon.Kim@Sun.COM static int
smp_report_manufacturer_information(smp_target_t * tp)8112126SHyon.Kim@Sun.COM smp_report_manufacturer_information(smp_target_t *tp)
8212126SHyon.Kim@Sun.COM {
8312126SHyon.Kim@Sun.COM smp_action_t *ap;
8412126SHyon.Kim@Sun.COM smp_report_manufacturer_info_resp_t *rp;
8512126SHyon.Kim@Sun.COM smp_result_t result;
8612126SHyon.Kim@Sun.COM size_t len;
8712126SHyon.Kim@Sun.COM
8812126SHyon.Kim@Sun.COM ap = smp_action_alloc(SMP_FUNC_REPORT_MANUFACTURER_INFO, tp, 0);
8912126SHyon.Kim@Sun.COM if (ap == NULL)
9012126SHyon.Kim@Sun.COM return (-1);
9112126SHyon.Kim@Sun.COM
9212126SHyon.Kim@Sun.COM if (smp_exec(ap, tp) != 0) {
9312126SHyon.Kim@Sun.COM smp_action_free(ap);
9412126SHyon.Kim@Sun.COM return (smp_set_errno(ESMP_REPGEN_FAILED));
9512126SHyon.Kim@Sun.COM }
9612126SHyon.Kim@Sun.COM
9712126SHyon.Kim@Sun.COM smp_action_get_response(ap, &result, (void **)&rp, &len);
9812126SHyon.Kim@Sun.COM
9912126SHyon.Kim@Sun.COM if (result != SMP_RES_FUNCTION_ACCEPTED ||
10012126SHyon.Kim@Sun.COM len != sizeof (smp_report_manufacturer_info_resp_t)) {
10112126SHyon.Kim@Sun.COM smp_action_free(ap);
10212126SHyon.Kim@Sun.COM return (0); /* Not supported */
10312126SHyon.Kim@Sun.COM }
10412126SHyon.Kim@Sun.COM
10512126SHyon.Kim@Sun.COM tp->st_vendor = smp_trim_strdup(rp->srmir_vendor_identification,
10612126SHyon.Kim@Sun.COM sizeof (rp->srmir_vendor_identification));
10712126SHyon.Kim@Sun.COM tp->st_product = smp_trim_strdup(rp->srmir_product_identification,
10812126SHyon.Kim@Sun.COM sizeof (rp->srmir_product_identification));
10912126SHyon.Kim@Sun.COM tp->st_revision = smp_trim_strdup(rp->srmir_product_revision_level,
11012126SHyon.Kim@Sun.COM sizeof (rp->srmir_product_revision_level));
11112126SHyon.Kim@Sun.COM
11212126SHyon.Kim@Sun.COM if (rp->srmir_sas_1_1_format) {
11312126SHyon.Kim@Sun.COM tp->st_component_vendor =
11412126SHyon.Kim@Sun.COM smp_trim_strdup(rp->srmir_component_vendor_identification,
11512126SHyon.Kim@Sun.COM sizeof (rp->srmir_component_vendor_identification));
11612126SHyon.Kim@Sun.COM
11712126SHyon.Kim@Sun.COM tp->st_component_id = SCSI_READ16(&rp->srmir_component_id);
11812126SHyon.Kim@Sun.COM tp->st_component_revision = rp->srmir_component_revision_level;
11912126SHyon.Kim@Sun.COM }
12012126SHyon.Kim@Sun.COM
12112126SHyon.Kim@Sun.COM if (tp->st_vendor == NULL || tp->st_product == NULL ||
12212126SHyon.Kim@Sun.COM tp->st_revision == NULL ||
12312126SHyon.Kim@Sun.COM (rp->srmir_sas_1_1_format && tp->st_component_vendor == NULL)) {
12412126SHyon.Kim@Sun.COM smp_action_free(ap);
12512126SHyon.Kim@Sun.COM return (smp_set_errno(ESMP_NOMEM));
12612126SHyon.Kim@Sun.COM }
12712126SHyon.Kim@Sun.COM
12812126SHyon.Kim@Sun.COM smp_action_free(ap);
12912126SHyon.Kim@Sun.COM
13012126SHyon.Kim@Sun.COM return (0);
13112126SHyon.Kim@Sun.COM }
13212126SHyon.Kim@Sun.COM
13312126SHyon.Kim@Sun.COM static int
smp_target_fill(smp_target_t * tp)13412126SHyon.Kim@Sun.COM smp_target_fill(smp_target_t *tp)
13512126SHyon.Kim@Sun.COM {
13612126SHyon.Kim@Sun.COM if (smp_report_general(tp) != 0 ||
13712126SHyon.Kim@Sun.COM smp_report_manufacturer_information(tp) != 0)
13812126SHyon.Kim@Sun.COM return (-1);
13912126SHyon.Kim@Sun.COM
14012126SHyon.Kim@Sun.COM return (0);
14112126SHyon.Kim@Sun.COM }
14212126SHyon.Kim@Sun.COM
14312126SHyon.Kim@Sun.COM const smp_function_def_t *
smp_get_funcdef(smp_target_t * tp,int fn)14412126SHyon.Kim@Sun.COM smp_get_funcdef(smp_target_t *tp, int fn)
14512126SHyon.Kim@Sun.COM {
14612126SHyon.Kim@Sun.COM smp_plugin_t *pp;
14712126SHyon.Kim@Sun.COM const smp_function_def_t *dp;
14812126SHyon.Kim@Sun.COM
14912126SHyon.Kim@Sun.COM for (pp = tp->st_plugin_first; pp != NULL; pp = pp->sp_next) {
15012126SHyon.Kim@Sun.COM if (pp->sp_functions == NULL)
15112126SHyon.Kim@Sun.COM continue;
15212126SHyon.Kim@Sun.COM
15312126SHyon.Kim@Sun.COM for (dp = &pp->sp_functions[0]; dp->sfd_rq_len != NULL; dp++) {
15412126SHyon.Kim@Sun.COM if (dp->sfd_function == fn)
15512126SHyon.Kim@Sun.COM return (dp);
15612126SHyon.Kim@Sun.COM }
15712126SHyon.Kim@Sun.COM }
15812126SHyon.Kim@Sun.COM
15912126SHyon.Kim@Sun.COM (void) smp_error(ESMP_BADFUNC, "failed to find function 0x%x", fn);
16012126SHyon.Kim@Sun.COM return (NULL);
16112126SHyon.Kim@Sun.COM }
16212126SHyon.Kim@Sun.COM
16312126SHyon.Kim@Sun.COM int
smp_plugin_register(smp_plugin_t * pp,int version,const smp_plugin_config_t * pcp)16412126SHyon.Kim@Sun.COM smp_plugin_register(smp_plugin_t *pp, int version,
16512126SHyon.Kim@Sun.COM const smp_plugin_config_t *pcp)
16612126SHyon.Kim@Sun.COM {
16712126SHyon.Kim@Sun.COM if (version != LIBSMP_PLUGIN_VERSION)
16812126SHyon.Kim@Sun.COM return (smp_set_errno(ESMP_VERSION));
16912126SHyon.Kim@Sun.COM
17012126SHyon.Kim@Sun.COM pp->sp_functions = pcp->spc_functions;
17112126SHyon.Kim@Sun.COM
17212126SHyon.Kim@Sun.COM return (0);
17312126SHyon.Kim@Sun.COM }
17412126SHyon.Kim@Sun.COM
17512126SHyon.Kim@Sun.COM void
smp_plugin_setspecific(smp_plugin_t * pp,void * data)17612126SHyon.Kim@Sun.COM smp_plugin_setspecific(smp_plugin_t *pp, void *data)
17712126SHyon.Kim@Sun.COM {
17812126SHyon.Kim@Sun.COM pp->sp_data = data;
17912126SHyon.Kim@Sun.COM }
18012126SHyon.Kim@Sun.COM
18112126SHyon.Kim@Sun.COM void *
smp_plugin_getspecific(smp_plugin_t * pp)18212126SHyon.Kim@Sun.COM smp_plugin_getspecific(smp_plugin_t *pp)
18312126SHyon.Kim@Sun.COM {
18412126SHyon.Kim@Sun.COM return (pp->sp_data);
18512126SHyon.Kim@Sun.COM }
18612126SHyon.Kim@Sun.COM
18712126SHyon.Kim@Sun.COM static void
smp_plugin_cleanstr(char * s)18812126SHyon.Kim@Sun.COM smp_plugin_cleanstr(char *s)
18912126SHyon.Kim@Sun.COM {
19012126SHyon.Kim@Sun.COM while (*s != '\0') {
19112126SHyon.Kim@Sun.COM if (*s == ' ' || *s == '/')
19212126SHyon.Kim@Sun.COM *s = '-';
19312126SHyon.Kim@Sun.COM s++;
19412126SHyon.Kim@Sun.COM }
19512126SHyon.Kim@Sun.COM }
19612126SHyon.Kim@Sun.COM
19712126SHyon.Kim@Sun.COM static void
smp_plugin_destroy(smp_plugin_t * pp)19812126SHyon.Kim@Sun.COM smp_plugin_destroy(smp_plugin_t *pp)
19912126SHyon.Kim@Sun.COM {
20012126SHyon.Kim@Sun.COM if (pp->sp_initialized && pp->sp_fini != NULL)
20112126SHyon.Kim@Sun.COM pp->sp_fini(pp);
20212126SHyon.Kim@Sun.COM
20312126SHyon.Kim@Sun.COM if (_libsmp_plugin_dlclose)
20412126SHyon.Kim@Sun.COM (void) dlclose(pp->sp_object);
20512126SHyon.Kim@Sun.COM
20612126SHyon.Kim@Sun.COM smp_free(pp);
20712126SHyon.Kim@Sun.COM }
20812126SHyon.Kim@Sun.COM
20912126SHyon.Kim@Sun.COM static int
smp_plugin_loadone(smp_target_t * tp,const char * path,uint32_t pass)21012126SHyon.Kim@Sun.COM smp_plugin_loadone(smp_target_t *tp, const char *path, uint32_t pass)
21112126SHyon.Kim@Sun.COM {
21212126SHyon.Kim@Sun.COM smp_plugin_t *pp, **loc;
21312126SHyon.Kim@Sun.COM void *obj;
21412126SHyon.Kim@Sun.COM int (*smp_priority)(void);
21512126SHyon.Kim@Sun.COM
21612126SHyon.Kim@Sun.COM if ((obj = dlopen(path, RTLD_PARENT | RTLD_LOCAL | RTLD_LAZY)) == NULL)
21712126SHyon.Kim@Sun.COM return (0);
21812126SHyon.Kim@Sun.COM
21912126SHyon.Kim@Sun.COM if ((pp = smp_zalloc(sizeof (smp_plugin_t))) == NULL) {
22012126SHyon.Kim@Sun.COM (void) dlclose(obj);
22112126SHyon.Kim@Sun.COM return (-1);
22212126SHyon.Kim@Sun.COM }
22312126SHyon.Kim@Sun.COM
22412126SHyon.Kim@Sun.COM pp->sp_object = obj;
22512126SHyon.Kim@Sun.COM pp->sp_init = (int (*)())dlsym(obj, "_smp_init");
22612126SHyon.Kim@Sun.COM pp->sp_fini = (void (*)())dlsym(obj, "_smp_fini");
22712126SHyon.Kim@Sun.COM pp->sp_target = tp;
22812126SHyon.Kim@Sun.COM
22912126SHyon.Kim@Sun.COM if (pp->sp_init == NULL) {
23012126SHyon.Kim@Sun.COM smp_plugin_destroy(pp);
23112126SHyon.Kim@Sun.COM return (0);
23212126SHyon.Kim@Sun.COM }
23312126SHyon.Kim@Sun.COM
23412126SHyon.Kim@Sun.COM /*
23512126SHyon.Kim@Sun.COM * Framework modules can establish an explicit prioritying by declaring
23612126SHyon.Kim@Sun.COM * the '_smp_priority' symbol, which returns an integer used to create
23712126SHyon.Kim@Sun.COM * an explicit ordering between plugins.
23812126SHyon.Kim@Sun.COM */
23912126SHyon.Kim@Sun.COM if ((smp_priority = (int (*)())dlsym(obj, "_smp_priority")) != NULL)
24012126SHyon.Kim@Sun.COM pp->sp_priority = smp_priority();
24112126SHyon.Kim@Sun.COM
24212126SHyon.Kim@Sun.COM pp->sp_priority |= (uint64_t)pass << 32;
24312126SHyon.Kim@Sun.COM
24412126SHyon.Kim@Sun.COM for (loc = &tp->st_plugin_first; *loc != NULL; loc = &(*loc)->sp_next) {
24512126SHyon.Kim@Sun.COM if ((*loc)->sp_priority > pp->sp_priority)
24612126SHyon.Kim@Sun.COM break;
24712126SHyon.Kim@Sun.COM }
24812126SHyon.Kim@Sun.COM
24912126SHyon.Kim@Sun.COM if (*loc != NULL)
25012126SHyon.Kim@Sun.COM (*loc)->sp_prev = pp;
25112126SHyon.Kim@Sun.COM else
25212126SHyon.Kim@Sun.COM tp->st_plugin_last = pp;
25312126SHyon.Kim@Sun.COM
25412126SHyon.Kim@Sun.COM pp->sp_next = *loc;
25512126SHyon.Kim@Sun.COM *loc = pp;
25612126SHyon.Kim@Sun.COM
25712126SHyon.Kim@Sun.COM if (pp->sp_init(pp) != 0)
25812126SHyon.Kim@Sun.COM return (-1);
25912126SHyon.Kim@Sun.COM pp->sp_initialized = B_TRUE;
26012126SHyon.Kim@Sun.COM
26112126SHyon.Kim@Sun.COM return (0);
26212126SHyon.Kim@Sun.COM }
26312126SHyon.Kim@Sun.COM
26412126SHyon.Kim@Sun.COM static int
smp_plugin_load_dir(smp_target_t * tp,const char * pluginroot)26512126SHyon.Kim@Sun.COM smp_plugin_load_dir(smp_target_t *tp, const char *pluginroot)
26612126SHyon.Kim@Sun.COM {
26712126SHyon.Kim@Sun.COM char path[PATH_MAX];
26812126SHyon.Kim@Sun.COM DIR *dirp;
26912126SHyon.Kim@Sun.COM struct dirent64 *dp;
27012126SHyon.Kim@Sun.COM char *c_vendor, *vendor, *product, *revision;
27112126SHyon.Kim@Sun.COM char isa[257];
27212126SHyon.Kim@Sun.COM
27312126SHyon.Kim@Sun.COM (void) snprintf(path, sizeof (path), "%s/%s",
27412126SHyon.Kim@Sun.COM pluginroot, LIBSMP_PLUGIN_FRAMEWORK);
27512126SHyon.Kim@Sun.COM
27612126SHyon.Kim@Sun.COM #if defined(_LP64)
27712126SHyon.Kim@Sun.COM if (sysinfo(SI_ARCHITECTURE_64, isa, sizeof (isa)) < 0)
27812126SHyon.Kim@Sun.COM isa[0] = '\0';
27912126SHyon.Kim@Sun.COM #else
28012126SHyon.Kim@Sun.COM isa[0] = '\0';
28112126SHyon.Kim@Sun.COM #endif
28212126SHyon.Kim@Sun.COM
28312126SHyon.Kim@Sun.COM if ((dirp = opendir(path)) != NULL) {
28412126SHyon.Kim@Sun.COM while ((dp = readdir64(dirp)) != NULL) {
28512126SHyon.Kim@Sun.COM if (strcmp(dp->d_name, ".") == 0 ||
28612126SHyon.Kim@Sun.COM strcmp(dp->d_name, "..") == 0)
28712126SHyon.Kim@Sun.COM continue;
28812126SHyon.Kim@Sun.COM
28912126SHyon.Kim@Sun.COM (void) snprintf(path, sizeof (path), "%s/%s/%s/%s",
29012126SHyon.Kim@Sun.COM pluginroot, LIBSMP_PLUGIN_FRAMEWORK,
29112126SHyon.Kim@Sun.COM isa, dp->d_name);
29212126SHyon.Kim@Sun.COM
29312126SHyon.Kim@Sun.COM if (smp_plugin_loadone(tp, path, 0) != 0) {
29412126SHyon.Kim@Sun.COM (void) closedir(dirp);
29512126SHyon.Kim@Sun.COM return (-1);
29612126SHyon.Kim@Sun.COM }
29712126SHyon.Kim@Sun.COM }
29812126SHyon.Kim@Sun.COM
29912126SHyon.Kim@Sun.COM (void) closedir(dirp);
30012126SHyon.Kim@Sun.COM }
30112126SHyon.Kim@Sun.COM
30212126SHyon.Kim@Sun.COM /*
30312126SHyon.Kim@Sun.COM * Now attempt to load platform-specific plugins. The framework
30412126SHyon.Kim@Sun.COM * plugins had better give us the ability to perform basic SMP
30512126SHyon.Kim@Sun.COM * functions like REPORT GENERAL and REPORT MANUFACTURER INFORMATION;
30612126SHyon.Kim@Sun.COM * if not, we're toast anyway. If the latter is not supported, we
30712126SHyon.Kim@Sun.COM * will not be able to use any vendor-specific plugins. Note that
30812126SHyon.Kim@Sun.COM * there are actually two possible specifications for vendor plugins:
30912126SHyon.Kim@Sun.COM * those matching the vendor/product/revision fields, and those
31012126SHyon.Kim@Sun.COM * matching the component vendor/id/revision fields. The component is
31112126SHyon.Kim@Sun.COM * less specific, so we try to load those first.
31212126SHyon.Kim@Sun.COM */
31312126SHyon.Kim@Sun.COM
31412126SHyon.Kim@Sun.COM if (smp_target_fill(tp) != 0)
31512126SHyon.Kim@Sun.COM return (-1);
31612126SHyon.Kim@Sun.COM
31712126SHyon.Kim@Sun.COM if (tp->st_vendor == NULL)
31812126SHyon.Kim@Sun.COM return (0);
31912126SHyon.Kim@Sun.COM
32012126SHyon.Kim@Sun.COM if (tp->st_component_vendor != NULL) {
321*13093SRoger.Faulkner@Oracle.COM c_vendor = strdupa(tp->st_component_vendor);
32212126SHyon.Kim@Sun.COM smp_plugin_cleanstr(c_vendor);
32312126SHyon.Kim@Sun.COM }
32412126SHyon.Kim@Sun.COM
325*13093SRoger.Faulkner@Oracle.COM vendor = strdupa(tp->st_vendor);
326*13093SRoger.Faulkner@Oracle.COM product = strdupa(tp->st_product);
327*13093SRoger.Faulkner@Oracle.COM revision = strdupa(tp->st_revision);
32812126SHyon.Kim@Sun.COM
32912126SHyon.Kim@Sun.COM smp_plugin_cleanstr(vendor);
33012126SHyon.Kim@Sun.COM smp_plugin_cleanstr(product);
33112126SHyon.Kim@Sun.COM smp_plugin_cleanstr(revision);
33212126SHyon.Kim@Sun.COM
33312126SHyon.Kim@Sun.COM if (tp->st_component_vendor != NULL) {
33412126SHyon.Kim@Sun.COM (void) snprintf(path, sizeof (path), "%s/%s/%s/component_%s%s",
33512126SHyon.Kim@Sun.COM pluginroot, LIBSMP_PLUGIN_VENDOR, isa, c_vendor,
33612126SHyon.Kim@Sun.COM LIBSMP_PLUGIN_EXT);
33712126SHyon.Kim@Sun.COM if (smp_plugin_loadone(tp, path, 1) != 0)
33812126SHyon.Kim@Sun.COM return (-1);
33912126SHyon.Kim@Sun.COM
34012126SHyon.Kim@Sun.COM (void) snprintf(path, sizeof (path),
34112126SHyon.Kim@Sun.COM "%s/%s/%s/component_%s-%04x%s",
34212126SHyon.Kim@Sun.COM pluginroot, LIBSMP_PLUGIN_VENDOR, isa, c_vendor,
34312126SHyon.Kim@Sun.COM tp->st_component_id, LIBSMP_PLUGIN_EXT);
34412126SHyon.Kim@Sun.COM if (smp_plugin_loadone(tp, path, 2) != 0)
34512126SHyon.Kim@Sun.COM return (-1);
34612126SHyon.Kim@Sun.COM
34712126SHyon.Kim@Sun.COM (void) snprintf(path, sizeof (path),
34812126SHyon.Kim@Sun.COM "%s/%s/%s/component_%s-%04x-%02x%s",
34912126SHyon.Kim@Sun.COM pluginroot, LIBSMP_PLUGIN_VENDOR, isa, c_vendor,
35012126SHyon.Kim@Sun.COM tp->st_component_id, tp->st_component_revision,
35112126SHyon.Kim@Sun.COM LIBSMP_PLUGIN_EXT);
35212126SHyon.Kim@Sun.COM if (smp_plugin_loadone(tp, path, 3) != 0)
35312126SHyon.Kim@Sun.COM return (-1);
35412126SHyon.Kim@Sun.COM }
35512126SHyon.Kim@Sun.COM
35612126SHyon.Kim@Sun.COM (void) snprintf(path, sizeof (path), "%s/%s/%s/%s%s", pluginroot,
35712126SHyon.Kim@Sun.COM LIBSMP_PLUGIN_VENDOR, isa, vendor, LIBSMP_PLUGIN_EXT);
35812126SHyon.Kim@Sun.COM if (smp_plugin_loadone(tp, path, 4) != 0)
35912126SHyon.Kim@Sun.COM return (-1);
36012126SHyon.Kim@Sun.COM
36112126SHyon.Kim@Sun.COM (void) snprintf(path, sizeof (path), "%s/%s/%s/%s-%s%s", pluginroot,
36212126SHyon.Kim@Sun.COM LIBSMP_PLUGIN_VENDOR, isa, vendor, product, LIBSMP_PLUGIN_EXT);
36312126SHyon.Kim@Sun.COM if (smp_plugin_loadone(tp, path, 5) != 0)
36412126SHyon.Kim@Sun.COM return (-1);
36512126SHyon.Kim@Sun.COM
36612126SHyon.Kim@Sun.COM (void) snprintf(path, sizeof (path), "%s/%s/%s/%s-%s-%s%s", pluginroot,
36712126SHyon.Kim@Sun.COM LIBSMP_PLUGIN_VENDOR, isa, vendor, product,
36812126SHyon.Kim@Sun.COM revision, LIBSMP_PLUGIN_EXT);
36912126SHyon.Kim@Sun.COM if (smp_plugin_loadone(tp, path, 6) != 0)
37012126SHyon.Kim@Sun.COM return (-1);
37112126SHyon.Kim@Sun.COM
37212126SHyon.Kim@Sun.COM return (0);
37312126SHyon.Kim@Sun.COM }
37412126SHyon.Kim@Sun.COM
37512126SHyon.Kim@Sun.COM int
smp_plugin_load(smp_target_t * tp)37612126SHyon.Kim@Sun.COM smp_plugin_load(smp_target_t *tp)
37712126SHyon.Kim@Sun.COM {
37812126SHyon.Kim@Sun.COM char pluginroot[PATH_MAX];
37912126SHyon.Kim@Sun.COM const char *pluginpath, *p, *q;
38012126SHyon.Kim@Sun.COM
38112126SHyon.Kim@Sun.COM if ((pluginpath = getenv("SMP_PLUGINPATH")) == NULL)
38212126SHyon.Kim@Sun.COM pluginpath = LIBSMP_DEFAULT_PLUGINDIR;
38312126SHyon.Kim@Sun.COM _libsmp_plugin_dlclose = (getenv("SMP_NODLCLOSE") == NULL);
38412126SHyon.Kim@Sun.COM
38512126SHyon.Kim@Sun.COM for (p = pluginpath; p != NULL; p = q) {
38612126SHyon.Kim@Sun.COM if ((q = strchr(p, ':')) != NULL) {
38712126SHyon.Kim@Sun.COM ptrdiff_t len = q - p;
38812126SHyon.Kim@Sun.COM (void) strncpy(pluginroot, p, len);
38912126SHyon.Kim@Sun.COM pluginroot[len] = '\0';
39012126SHyon.Kim@Sun.COM while (*q == ':')
39112126SHyon.Kim@Sun.COM ++q;
39212126SHyon.Kim@Sun.COM if (*q == '\0')
39312126SHyon.Kim@Sun.COM q = NULL;
39412126SHyon.Kim@Sun.COM if (len == 0)
39512126SHyon.Kim@Sun.COM continue;
39612126SHyon.Kim@Sun.COM } else {
39712126SHyon.Kim@Sun.COM (void) strcpy(pluginroot, p);
39812126SHyon.Kim@Sun.COM }
39912126SHyon.Kim@Sun.COM
40012126SHyon.Kim@Sun.COM if (pluginroot[0] != '/')
40112126SHyon.Kim@Sun.COM continue;
40212126SHyon.Kim@Sun.COM
40312126SHyon.Kim@Sun.COM if (smp_plugin_load_dir(tp, pluginroot) != 0)
40412126SHyon.Kim@Sun.COM return (-1);
40512126SHyon.Kim@Sun.COM }
40612126SHyon.Kim@Sun.COM
40712126SHyon.Kim@Sun.COM if (tp->st_plugin_first == NULL)
40812126SHyon.Kim@Sun.COM return (smp_error(ESMP_PLUGIN, "no plugins found"));
40912126SHyon.Kim@Sun.COM
41012126SHyon.Kim@Sun.COM return (0);
41112126SHyon.Kim@Sun.COM }
41212126SHyon.Kim@Sun.COM
41312126SHyon.Kim@Sun.COM void
smp_plugin_unload(smp_target_t * tp)41412126SHyon.Kim@Sun.COM smp_plugin_unload(smp_target_t *tp)
41512126SHyon.Kim@Sun.COM {
41612126SHyon.Kim@Sun.COM smp_plugin_t *pp;
41712126SHyon.Kim@Sun.COM
41812126SHyon.Kim@Sun.COM while ((pp = tp->st_plugin_first) != NULL) {
41912126SHyon.Kim@Sun.COM tp->st_plugin_first = pp->sp_next;
42012126SHyon.Kim@Sun.COM smp_plugin_destroy(pp);
42112126SHyon.Kim@Sun.COM }
42212126SHyon.Kim@Sun.COM }
423