11991Sheppo /*
21991Sheppo * CDDL HEADER START
31991Sheppo *
41991Sheppo * The contents of this file are subject to the terms of the
51991Sheppo * Common Development and Distribution License (the "License").
61991Sheppo * You may not use this file except in compliance with the License.
71991Sheppo *
81991Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91991Sheppo * or http://www.opensolaris.org/os/licensing.
101991Sheppo * See the License for the specific language governing permissions
111991Sheppo * and limitations under the License.
121991Sheppo *
131991Sheppo * When distributing Covered Code, include this CDDL HEADER in each
141991Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151991Sheppo * If applicable, add the following below this CDDL HEADER, with the
161991Sheppo * fields enclosed by brackets "[]" replaced with your own identifying
171991Sheppo * information: Portions Copyright [yyyy] [name of copyright owner]
181991Sheppo *
191991Sheppo * CDDL HEADER END
201991Sheppo */
211991Sheppo
221991Sheppo /*
23*11066Srafael.vanoni@sun.com * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
241991Sheppo * Use is subject to license terms.
251991Sheppo */
261991Sheppo
271991Sheppo #include <sys/types.h>
281991Sheppo #include <sys/ddi.h>
291991Sheppo #include <sys/sunddi.h>
301991Sheppo #include <sys/promif_impl.h>
311991Sheppo #include <sys/ds.h>
321991Sheppo #include <sys/modctl.h>
331991Sheppo #include <sys/ksynch.h>
341991Sheppo #include <sys/varconfig.h>
351991Sheppo
361991Sheppo #ifndef _KMDB
371991Sheppo
381991Sheppo #define PROMIF_DS_TIMEOUT_SEC 15
391991Sheppo
401991Sheppo static kmutex_t promif_prop_lock;
411991Sheppo static kcondvar_t promif_prop_cv;
421991Sheppo static var_config_msg_t promif_ds_resp;
431991Sheppo static var_config_resp_t *cfg_rsp = &promif_ds_resp.var_config_resp;
441991Sheppo static int (*ds_send)();
451991Sheppo static int (*ds_init)();
461991Sheppo
471991Sheppo /*
481991Sheppo * Domains Services interaction
491991Sheppo */
501991Sheppo static ds_svc_hdl_t ds_primary_handle;
511991Sheppo static ds_svc_hdl_t ds_backup_handle;
521991Sheppo
531991Sheppo static ds_ver_t vc_version[] = { { 1, 0 } };
541991Sheppo
551991Sheppo #define VC_NVERS (sizeof (vc_version) / sizeof (vc_version[0]))
561991Sheppo
571991Sheppo static ds_capability_t vc_primary_cap = {
581991Sheppo "var-config", /* svc_id */
591991Sheppo vc_version, /* vers */
601991Sheppo VC_NVERS /* nvers */
611991Sheppo };
621991Sheppo
631991Sheppo static ds_capability_t vc_backup_cap = {
641991Sheppo "var-config-backup", /* svc_id */
651991Sheppo vc_version, /* vers */
661991Sheppo VC_NVERS /* nvers */
671991Sheppo };
681991Sheppo
691991Sheppo static void vc_reg_handler(ds_cb_arg_t, ds_ver_t *, ds_svc_hdl_t);
701991Sheppo static void vc_unreg_handler(ds_cb_arg_t);
711991Sheppo static void vc_data_handler(ds_cb_arg_t, void *, size_t);
721991Sheppo
731991Sheppo static ds_clnt_ops_t vc_primary_ops = {
741991Sheppo vc_reg_handler, /* ds_primary_reg_cb */
751991Sheppo vc_unreg_handler, /* ds_primary_unreg_cb */
761991Sheppo vc_data_handler, /* ds_data_cb */
771991Sheppo &ds_primary_handle /* cb_arg */
781991Sheppo };
791991Sheppo
801991Sheppo static ds_clnt_ops_t vc_backup_ops = {
811991Sheppo vc_reg_handler, /* ds_backup_reg_cb */
821991Sheppo vc_unreg_handler, /* ds_backup_unreg_cb */
831991Sheppo vc_data_handler, /* ds_data_cb */
841991Sheppo &ds_backup_handle /* cb_arg */
851991Sheppo };
861991Sheppo
871991Sheppo static void
vc_reg_handler(ds_cb_arg_t arg,ds_ver_t * ver,ds_svc_hdl_t hdl)881991Sheppo vc_reg_handler(ds_cb_arg_t arg, ds_ver_t *ver, ds_svc_hdl_t hdl)
891991Sheppo {
901991Sheppo _NOTE(ARGUNUSED(ver))
911991Sheppo
921991Sheppo if ((ds_svc_hdl_t *)arg == &ds_primary_handle)
931991Sheppo ds_primary_handle = hdl;
941991Sheppo else if ((ds_svc_hdl_t *)arg == &ds_backup_handle)
952600Sjm22469 ds_backup_handle = hdl;
961991Sheppo }
971991Sheppo
981991Sheppo static void
vc_unreg_handler(ds_cb_arg_t arg)991991Sheppo vc_unreg_handler(ds_cb_arg_t arg)
1001991Sheppo {
1011991Sheppo if ((ds_svc_hdl_t *)arg == &ds_primary_handle)
1021991Sheppo ds_primary_handle = DS_INVALID_HDL;
1031991Sheppo else if ((ds_svc_hdl_t *)arg == &ds_backup_handle)
1041991Sheppo ds_backup_handle = DS_INVALID_HDL;
1051991Sheppo }
1061991Sheppo
1071991Sheppo static void
vc_data_handler(ds_cb_arg_t arg,void * buf,size_t buflen)1081991Sheppo vc_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen)
1091991Sheppo {
1101991Sheppo _NOTE(ARGUNUSED(arg))
1111991Sheppo
1121991Sheppo bcopy(buf, &promif_ds_resp, buflen);
1131991Sheppo mutex_enter(&promif_prop_lock);
1141991Sheppo cv_signal(&promif_prop_cv);
1151991Sheppo mutex_exit(&promif_prop_lock);
1161991Sheppo }
1171991Sheppo
1181991Sheppo /*
1191991Sheppo * Initialize the linkage with DS (Domain Services). We assume that
1201991Sheppo * the DS module has already been loaded by the platmod.
1211991Sheppo *
1221991Sheppo * The call to the DS init functions will eventually result in the
1231991Sheppo * invocation of our registration callback handlers, at which time DS
1241991Sheppo * is able to accept requests.
1251991Sheppo */
1261991Sheppo static void
promif_ds_init(void)1271991Sheppo promif_ds_init(void)
1281991Sheppo {
1291991Sheppo static char *me = "promif_ds_init";
1301991Sheppo int rv;
1311991Sheppo
1321991Sheppo if ((ds_init =
1331991Sheppo (int (*)())modgetsymvalue("ds_cap_init", 0)) == 0) {
1341991Sheppo cmn_err(CE_WARN, "%s: can't find ds_cap_init", me);
1351991Sheppo return;
1361991Sheppo }
1371991Sheppo
1381991Sheppo if ((ds_send =
1391991Sheppo (int (*)())modgetsymvalue("ds_cap_send", 0)) == 0) {
1401991Sheppo cmn_err(CE_WARN, "%s: can't find ds_cap_send", me);
1411991Sheppo return;
1421991Sheppo }
1431991Sheppo
1441991Sheppo if ((rv = (*ds_init)(&vc_primary_cap, &vc_primary_ops)) != 0) {
1451991Sheppo cmn_err(CE_NOTE,
1461991Sheppo "%s: ds_cap_init failed (primary): %d", me, rv);
1471991Sheppo }
1481991Sheppo
1491991Sheppo
1501991Sheppo if ((rv = (*ds_init)(&vc_backup_cap, &vc_backup_ops)) != 0) {
1511991Sheppo cmn_err(CE_NOTE,
1521991Sheppo "%s: ds_cap_init failed (backup): %d", me, rv);
1531991Sheppo }
1541991Sheppo }
1551991Sheppo
1561991Sheppo /*
1571991Sheppo * Prepare for ldom variable requests.
1581991Sheppo */
1591991Sheppo void
promif_prop_init(void)1601991Sheppo promif_prop_init(void)
1611991Sheppo {
1621991Sheppo mutex_init(&promif_prop_lock, NULL, MUTEX_DEFAULT, NULL);
1631991Sheppo cv_init(&promif_prop_cv, NULL, CV_DEFAULT, NULL);
1641991Sheppo
1651991Sheppo promif_ds_init();
1661991Sheppo }
1671991Sheppo
1681991Sheppo
1691991Sheppo /*
1701991Sheppo * Replace the current value of a property string given its name and
1711991Sheppo * new value.
1721991Sheppo */
1731991Sheppo int
promif_ldom_setprop(char * name,void * value,int valuelen)1741991Sheppo promif_ldom_setprop(char *name, void *value, int valuelen)
1751991Sheppo {
1761991Sheppo var_config_msg_t *req;
1771991Sheppo var_config_set_req_t *setp;
1781991Sheppo var_config_cmd_t cmd;
1791991Sheppo ds_svc_hdl_t ds_handle;
1801991Sheppo int rv;
1811991Sheppo int namelen = strlen(name);
1821991Sheppo int paylen = namelen + 1 + valuelen; /* valuelen includes the null */
1831991Sheppo static char *me = "promif_ldom_setprop";
1841991Sheppo
1851991Sheppo if (ds_primary_handle != DS_INVALID_HDL)
1861991Sheppo ds_handle = ds_primary_handle;
1871991Sheppo else if (ds_backup_handle != DS_INVALID_HDL)
1881991Sheppo ds_handle = ds_backup_handle;
1891991Sheppo else
1901991Sheppo return (-1);
1911991Sheppo
1925035Sjm22469 /*
1935035Sjm22469 * Since we are emulating OBP, we must comply with the promif
1945035Sjm22469 * infrastructure and execute only on the originating cpu.
1955035Sjm22469 */
1965768Sjm22469 thread_affinity_set(curthread, CPU->cpu_id);
1975035Sjm22469
1981991Sheppo req = kmem_zalloc(sizeof (var_config_hdr_t) + paylen, KM_SLEEP);
1991991Sheppo req->var_config_cmd = VAR_CONFIG_SET_REQ;
2001991Sheppo setp = &req->var_config_set;
2011991Sheppo (void) strcpy(setp->name_and_value, name);
2021991Sheppo (void) strncpy(&setp->name_and_value[namelen + 1], value, valuelen);
2031991Sheppo
2041991Sheppo if ((rv = (*ds_send)(ds_handle, req,
2051991Sheppo sizeof (var_config_hdr_t) + paylen)) != 0) {
2061991Sheppo cmn_err(CE_WARN, "%s: ds_cap_send failed: %d", me, rv);
2071991Sheppo kmem_free(req, sizeof (var_config_hdr_t) + paylen);
2085035Sjm22469 thread_affinity_clear(curthread);
2091991Sheppo return (-1);
2101991Sheppo }
2111991Sheppo
2121991Sheppo kmem_free(req, sizeof (var_config_hdr_t) + paylen);
2131991Sheppo
2141991Sheppo mutex_enter(&promif_prop_lock);
215*11066Srafael.vanoni@sun.com if (cv_reltimedwait(&promif_prop_cv, &promif_prop_lock,
216*11066Srafael.vanoni@sun.com PROMIF_DS_TIMEOUT_SEC * hz, TR_CLOCK_TICK) == -1) {
2171991Sheppo cmn_err(CE_WARN, "%s: ds response timeout", me);
2181991Sheppo rv = -1;
2191991Sheppo goto out;
2201991Sheppo }
2211991Sheppo
2221991Sheppo cmd = promif_ds_resp.vc_hdr.cmd;
2231991Sheppo if (cmd != VAR_CONFIG_SET_RESP) {
2241991Sheppo cmn_err(CE_WARN, "%s: bad response type: %d", me, cmd);
2251991Sheppo rv = -1;
2261991Sheppo goto out;
2271991Sheppo }
2281991Sheppo rv = (cfg_rsp->result == VAR_CONFIG_SUCCESS) ? valuelen : -1;
2291991Sheppo
2301991Sheppo out:
2311991Sheppo mutex_exit(&promif_prop_lock);
2321991Sheppo thread_affinity_clear(curthread);
2331991Sheppo return (rv);
2341991Sheppo }
2351991Sheppo
2361991Sheppo int
promif_setprop(void * p)2371991Sheppo promif_setprop(void *p)
2381991Sheppo {
2391991Sheppo cell_t *ci = (cell_t *)p;
2401991Sheppo pnode_t node;
2411991Sheppo caddr_t name;
2421991Sheppo caddr_t value;
2431991Sheppo int len;
2441991Sheppo
2451991Sheppo ASSERT(ci[1] == 4);
2461991Sheppo
2471991Sheppo node = p1275_cell2dnode(ci[3]);
2481991Sheppo ASSERT(node == prom_optionsnode());
2491991Sheppo name = p1275_cell2ptr(ci[4]);
2501991Sheppo value = p1275_cell2ptr(ci[5]);
2511991Sheppo len = p1275_cell2int(ci[6]);
2521991Sheppo
2531991Sheppo if (promif_stree_getproplen(node, name) != -1)
2541991Sheppo len = promif_ldom_setprop(name, value, len);
2551991Sheppo
2561991Sheppo if (len >= 0)
2571991Sheppo len = promif_stree_setprop(node, name, (void *)value, len);
2581991Sheppo
2591991Sheppo
2601991Sheppo ci[7] = p1275_int2cell(len);
2611991Sheppo
2621991Sheppo return ((len == -1) ? len : 0);
2631991Sheppo }
2641991Sheppo
2651991Sheppo #endif
2661991Sheppo
2671991Sheppo int
promif_getprop(void * p)2681991Sheppo promif_getprop(void *p)
2691991Sheppo {
2701991Sheppo cell_t *ci = (cell_t *)p;
2711991Sheppo pnode_t node;
2721991Sheppo caddr_t name;
2731991Sheppo caddr_t value;
2741991Sheppo int len;
2751991Sheppo
2761991Sheppo ASSERT(ci[1] == 4);
2771991Sheppo
2781991Sheppo node = p1275_cell2dnode(ci[3]);
2791991Sheppo name = p1275_cell2ptr(ci[4]);
2801991Sheppo value = p1275_cell2ptr(ci[5]);
2811991Sheppo
2821991Sheppo len = promif_stree_getprop(node, name, value);
2831991Sheppo
2841991Sheppo ci[7] = p1275_int2cell(len);
2851991Sheppo
2861991Sheppo return ((len == -1) ? len : 0);
2871991Sheppo }
2881991Sheppo
2891991Sheppo int
promif_getproplen(void * p)2901991Sheppo promif_getproplen(void *p)
2911991Sheppo {
2921991Sheppo cell_t *ci = (cell_t *)p;
2931991Sheppo pnode_t node;
2941991Sheppo caddr_t name;
2951991Sheppo int len;
2961991Sheppo
2971991Sheppo ASSERT(ci[1] == 2);
2981991Sheppo
2991991Sheppo node = p1275_cell2dnode(ci[3]);
3001991Sheppo name = p1275_cell2ptr(ci[4]);
3011991Sheppo
3021991Sheppo len = promif_stree_getproplen(node, name);
3031991Sheppo
3041991Sheppo ci[5] = p1275_int2cell(len);
3051991Sheppo
3061991Sheppo return (0);
3071991Sheppo }
3081991Sheppo
3091991Sheppo int
promif_nextprop(void * p)3101991Sheppo promif_nextprop(void *p)
3111991Sheppo {
3121991Sheppo cell_t *ci = (cell_t *)p;
3131991Sheppo pnode_t node;
3141991Sheppo caddr_t prev;
3151991Sheppo caddr_t next;
3161991Sheppo
3171991Sheppo ASSERT(ci[1] == 3);
3181991Sheppo
3191991Sheppo node = p1275_cell2dnode(ci[3]);
3201991Sheppo prev = p1275_cell2ptr(ci[4]);
3211991Sheppo next = p1275_cell2ptr(ci[5]);
3221991Sheppo
3231991Sheppo (void) promif_stree_nextprop(node, prev, next);
3241991Sheppo
3251991Sheppo return (0);
3261991Sheppo }
327