17697SMichael.Christensen@Sun.COM /*
27697SMichael.Christensen@Sun.COM * CDDL HEADER START
37697SMichael.Christensen@Sun.COM *
47697SMichael.Christensen@Sun.COM * The contents of this file are subject to the terms of the
57697SMichael.Christensen@Sun.COM * Common Development and Distribution License (the "License").
67697SMichael.Christensen@Sun.COM * You may not use this file except in compliance with the License.
77697SMichael.Christensen@Sun.COM *
87697SMichael.Christensen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97697SMichael.Christensen@Sun.COM * or http://www.opensolaris.org/os/licensing.
107697SMichael.Christensen@Sun.COM * See the License for the specific language governing permissions
117697SMichael.Christensen@Sun.COM * and limitations under the License.
127697SMichael.Christensen@Sun.COM *
137697SMichael.Christensen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147697SMichael.Christensen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157697SMichael.Christensen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167697SMichael.Christensen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177697SMichael.Christensen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187697SMichael.Christensen@Sun.COM *
197697SMichael.Christensen@Sun.COM * CDDL HEADER END
207697SMichael.Christensen@Sun.COM */
217697SMichael.Christensen@Sun.COM
227697SMichael.Christensen@Sun.COM /*
239603SMichael.Christensen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
247697SMichael.Christensen@Sun.COM * Use is subject to license terms.
257697SMichael.Christensen@Sun.COM */
267697SMichael.Christensen@Sun.COM
277697SMichael.Christensen@Sun.COM
287697SMichael.Christensen@Sun.COM /*
297697SMichael.Christensen@Sun.COM * Domain Services Module System Specific Code.
307697SMichael.Christensen@Sun.COM *
317697SMichael.Christensen@Sun.COM * The Domain Services (DS) module is responsible for communication
327697SMichael.Christensen@Sun.COM * with external service entities. It provides a kernel API for clients to
337697SMichael.Christensen@Sun.COM * publish capabilities and handles the low level communication and
347697SMichael.Christensen@Sun.COM * version negotiation required to export those capabilities to any
357697SMichael.Christensen@Sun.COM * interested service entity. Once a capability has been successfully
367697SMichael.Christensen@Sun.COM * registered with a service entity, the DS module facilitates all
377697SMichael.Christensen@Sun.COM * data transfers between the service entity and the client providing
387697SMichael.Christensen@Sun.COM * that particular capability.
397697SMichael.Christensen@Sun.COM *
407697SMichael.Christensen@Sun.COM * This file provides the system interfaces that are required for
417697SMichael.Christensen@Sun.COM * the ds.c module, which is common to both Solaris and VBSC (linux).
427697SMichael.Christensen@Sun.COM */
437697SMichael.Christensen@Sun.COM
447697SMichael.Christensen@Sun.COM #include <sys/modctl.h>
457697SMichael.Christensen@Sun.COM #include <sys/ksynch.h>
467697SMichael.Christensen@Sun.COM #include <sys/taskq.h>
477697SMichael.Christensen@Sun.COM #include <sys/disp.h>
487697SMichael.Christensen@Sun.COM #include <sys/cmn_err.h>
497697SMichael.Christensen@Sun.COM #include <sys/note.h>
507697SMichael.Christensen@Sun.COM #include <sys/mach_descrip.h>
517697SMichael.Christensen@Sun.COM #include <sys/mdesc.h>
527697SMichael.Christensen@Sun.COM #include <sys/mdeg.h>
537697SMichael.Christensen@Sun.COM #include <sys/ldc.h>
547697SMichael.Christensen@Sun.COM #include <sys/ds.h>
557697SMichael.Christensen@Sun.COM #include <sys/ds_impl.h>
567697SMichael.Christensen@Sun.COM
577697SMichael.Christensen@Sun.COM /*
587697SMichael.Christensen@Sun.COM * All DS ports in the system
597697SMichael.Christensen@Sun.COM *
607697SMichael.Christensen@Sun.COM * The list of DS ports is read in from the MD when the DS module is
617697SMichael.Christensen@Sun.COM * initialized and is never modified. This eliminates the need for
627697SMichael.Christensen@Sun.COM * locking to access the port array itself. Access to the individual
637697SMichael.Christensen@Sun.COM * ports are synchronized at the port level.
647697SMichael.Christensen@Sun.COM */
657697SMichael.Christensen@Sun.COM ds_port_t ds_ports[DS_MAX_PORTS];
667697SMichael.Christensen@Sun.COM ds_portset_t ds_allports; /* all DS ports in the system */
677697SMichael.Christensen@Sun.COM
687697SMichael.Christensen@Sun.COM /*
697697SMichael.Christensen@Sun.COM * Table of registered services
707697SMichael.Christensen@Sun.COM *
717697SMichael.Christensen@Sun.COM * Locking: Accesses to the table of services are synchronized using
727697SMichael.Christensen@Sun.COM * a mutex lock. The reader lock must be held when looking up service
737697SMichael.Christensen@Sun.COM * information in the table. The writer lock must be held when any
747697SMichael.Christensen@Sun.COM * service information is being modified.
757697SMichael.Christensen@Sun.COM */
767697SMichael.Christensen@Sun.COM ds_svcs_t ds_svcs;
777697SMichael.Christensen@Sun.COM
787697SMichael.Christensen@Sun.COM /*
797697SMichael.Christensen@Sun.COM * Taskq for internal task processing
807697SMichael.Christensen@Sun.COM */
817697SMichael.Christensen@Sun.COM static taskq_t *ds_taskq;
827697SMichael.Christensen@Sun.COM
837697SMichael.Christensen@Sun.COM /*
847697SMichael.Christensen@Sun.COM * The actual required number of parallel threads is not expected
857697SMichael.Christensen@Sun.COM * to be very large. Use the maximum number of CPUs in the system
867697SMichael.Christensen@Sun.COM * as a rough upper bound.
877697SMichael.Christensen@Sun.COM */
887697SMichael.Christensen@Sun.COM #define DS_MAX_TASKQ_THR NCPU
897697SMichael.Christensen@Sun.COM #define DS_DISPATCH(fn, arg) taskq_dispatch(ds_taskq, fn, arg, TQ_SLEEP)
907697SMichael.Christensen@Sun.COM
918172SMichael.Christensen@Sun.COM ds_domain_hdl_t ds_my_domain_hdl = DS_DHDL_INVALID;
928172SMichael.Christensen@Sun.COM char *ds_my_domain_name = NULL;
937697SMichael.Christensen@Sun.COM
947697SMichael.Christensen@Sun.COM #ifdef DEBUG
957697SMichael.Christensen@Sun.COM /*
967697SMichael.Christensen@Sun.COM * Debug Flag
977697SMichael.Christensen@Sun.COM */
987697SMichael.Christensen@Sun.COM uint_t ds_debug = 0;
997697SMichael.Christensen@Sun.COM #endif /* DEBUG */
1007697SMichael.Christensen@Sun.COM
1017697SMichael.Christensen@Sun.COM /* initialization functions */
1027697SMichael.Christensen@Sun.COM static void ds_init(void);
1037697SMichael.Christensen@Sun.COM static void ds_fini(void);
1047697SMichael.Christensen@Sun.COM static int ds_ports_init(void);
1057697SMichael.Christensen@Sun.COM static int ds_ports_fini(void);
1067697SMichael.Christensen@Sun.COM
1077697SMichael.Christensen@Sun.COM /* port utilities */
1087697SMichael.Christensen@Sun.COM static int ds_port_add(md_t *mdp, mde_cookie_t port, mde_cookie_t chan);
1097697SMichael.Christensen@Sun.COM
1107697SMichael.Christensen@Sun.COM /* log functions */
1117697SMichael.Christensen@Sun.COM static void ds_log_init(void);
1127697SMichael.Christensen@Sun.COM static void ds_log_fini(void);
1137697SMichael.Christensen@Sun.COM static int ds_log_remove(void);
1147697SMichael.Christensen@Sun.COM static void ds_log_purge(void *arg);
1157697SMichael.Christensen@Sun.COM
1167697SMichael.Christensen@Sun.COM static struct modlmisc modlmisc = {
1177697SMichael.Christensen@Sun.COM &mod_miscops,
1187697SMichael.Christensen@Sun.COM "Domain Services 1.9"
1197697SMichael.Christensen@Sun.COM };
1207697SMichael.Christensen@Sun.COM
1217697SMichael.Christensen@Sun.COM static struct modlinkage modlinkage = {
1227697SMichael.Christensen@Sun.COM MODREV_1,
1237697SMichael.Christensen@Sun.COM (void *)&modlmisc,
1247697SMichael.Christensen@Sun.COM NULL
1257697SMichael.Christensen@Sun.COM };
1267697SMichael.Christensen@Sun.COM
1277697SMichael.Christensen@Sun.COM int
_init(void)1287697SMichael.Christensen@Sun.COM _init(void)
1297697SMichael.Christensen@Sun.COM {
1307697SMichael.Christensen@Sun.COM int rv;
1317697SMichael.Christensen@Sun.COM
1327697SMichael.Christensen@Sun.COM /*
1337697SMichael.Christensen@Sun.COM * Perform all internal setup before initializing
1347697SMichael.Christensen@Sun.COM * the DS ports. This ensures that events can be
1357697SMichael.Christensen@Sun.COM * processed as soon as the port comes up.
1367697SMichael.Christensen@Sun.COM */
1377697SMichael.Christensen@Sun.COM ds_init();
1387697SMichael.Christensen@Sun.COM
1397697SMichael.Christensen@Sun.COM /* force attach channel nexus */
1407697SMichael.Christensen@Sun.COM (void) i_ddi_attach_hw_nodes("cnex");
1417697SMichael.Christensen@Sun.COM
1427697SMichael.Christensen@Sun.COM if ((rv = ds_ports_init()) != 0) {
1437697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "Domain Services initialization failed");
1447697SMichael.Christensen@Sun.COM ds_fini();
1457697SMichael.Christensen@Sun.COM return (rv);
1467697SMichael.Christensen@Sun.COM }
1477697SMichael.Christensen@Sun.COM
1487697SMichael.Christensen@Sun.COM if ((rv = mod_install(&modlinkage)) != 0) {
1497697SMichael.Christensen@Sun.COM (void) ds_ports_fini();
1507697SMichael.Christensen@Sun.COM ds_fini();
1517697SMichael.Christensen@Sun.COM }
1527697SMichael.Christensen@Sun.COM
1537697SMichael.Christensen@Sun.COM return (rv);
1547697SMichael.Christensen@Sun.COM }
1557697SMichael.Christensen@Sun.COM
1567697SMichael.Christensen@Sun.COM int
_info(struct modinfo * modinfop)1577697SMichael.Christensen@Sun.COM _info(struct modinfo *modinfop)
1587697SMichael.Christensen@Sun.COM {
1597697SMichael.Christensen@Sun.COM return (mod_info(&modlinkage, modinfop));
1607697SMichael.Christensen@Sun.COM }
1617697SMichael.Christensen@Sun.COM
1627697SMichael.Christensen@Sun.COM int
_fini(void)1637697SMichael.Christensen@Sun.COM _fini(void)
1647697SMichael.Christensen@Sun.COM {
1657697SMichael.Christensen@Sun.COM int rv;
1667697SMichael.Christensen@Sun.COM
1677697SMichael.Christensen@Sun.COM if ((rv = mod_remove(&modlinkage)) == 0) {
1687697SMichael.Christensen@Sun.COM (void) ds_ports_fini();
1697697SMichael.Christensen@Sun.COM ds_fini();
1707697SMichael.Christensen@Sun.COM }
1717697SMichael.Christensen@Sun.COM
1727697SMichael.Christensen@Sun.COM return (rv);
1737697SMichael.Christensen@Sun.COM }
1747697SMichael.Christensen@Sun.COM
1757697SMichael.Christensen@Sun.COM static void
ds_fini(void)1767697SMichael.Christensen@Sun.COM ds_fini(void)
1777697SMichael.Christensen@Sun.COM {
1787697SMichael.Christensen@Sun.COM /*
1797697SMichael.Christensen@Sun.COM * Flip the enabled switch to make sure that no
1807697SMichael.Christensen@Sun.COM * incoming events get dispatched while things
1817697SMichael.Christensen@Sun.COM * are being torn down.
1827697SMichael.Christensen@Sun.COM */
1837697SMichael.Christensen@Sun.COM ds_enabled = B_FALSE;
1847697SMichael.Christensen@Sun.COM
1857697SMichael.Christensen@Sun.COM /*
1867697SMichael.Christensen@Sun.COM * Destroy the taskq.
1877697SMichael.Christensen@Sun.COM */
1887697SMichael.Christensen@Sun.COM taskq_destroy(ds_taskq);
1897697SMichael.Christensen@Sun.COM
1907697SMichael.Christensen@Sun.COM /*
1917697SMichael.Christensen@Sun.COM * Destroy the message log.
1927697SMichael.Christensen@Sun.COM */
1937697SMichael.Christensen@Sun.COM ds_log_fini();
1947697SMichael.Christensen@Sun.COM
1957697SMichael.Christensen@Sun.COM /*
1967697SMichael.Christensen@Sun.COM * Deallocate the table of registered services
1977697SMichael.Christensen@Sun.COM */
1987697SMichael.Christensen@Sun.COM
1997697SMichael.Christensen@Sun.COM /* clear out all entries */
2007697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock);
2017697SMichael.Christensen@Sun.COM (void) ds_walk_svcs(ds_svc_free, NULL);
2027697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
2037697SMichael.Christensen@Sun.COM
2047697SMichael.Christensen@Sun.COM /* destroy the table itself */
2057697SMichael.Christensen@Sun.COM DS_FREE(ds_svcs.tbl, ds_svcs.maxsvcs * sizeof (ds_svc_t *));
2067697SMichael.Christensen@Sun.COM mutex_destroy(&ds_svcs.lock);
2077697SMichael.Christensen@Sun.COM bzero(&ds_svcs, sizeof (ds_svcs));
2087697SMichael.Christensen@Sun.COM }
2097697SMichael.Christensen@Sun.COM
2107697SMichael.Christensen@Sun.COM /*
2117697SMichael.Christensen@Sun.COM * Initialize the list of ports based on the MD.
2127697SMichael.Christensen@Sun.COM */
2137697SMichael.Christensen@Sun.COM static int
ds_ports_init(void)2147697SMichael.Christensen@Sun.COM ds_ports_init(void)
2157697SMichael.Christensen@Sun.COM {
2167697SMichael.Christensen@Sun.COM int idx;
2177697SMichael.Christensen@Sun.COM int rv = 0;
2187697SMichael.Christensen@Sun.COM md_t *mdp;
2197697SMichael.Christensen@Sun.COM int num_nodes;
2207697SMichael.Christensen@Sun.COM int listsz;
2217697SMichael.Christensen@Sun.COM mde_cookie_t rootnode;
2227697SMichael.Christensen@Sun.COM mde_cookie_t dsnode;
2237697SMichael.Christensen@Sun.COM mde_cookie_t *portp = NULL;
2247697SMichael.Christensen@Sun.COM mde_cookie_t *chanp = NULL;
2257697SMichael.Christensen@Sun.COM int nport;
2267697SMichael.Christensen@Sun.COM int nchan;
2277697SMichael.Christensen@Sun.COM
2287697SMichael.Christensen@Sun.COM if ((mdp = md_get_handle()) == NULL) {
2297697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "Unable to initialize machine description");
2307697SMichael.Christensen@Sun.COM return (-1);
2317697SMichael.Christensen@Sun.COM }
2327697SMichael.Christensen@Sun.COM
2337697SMichael.Christensen@Sun.COM num_nodes = md_node_count(mdp);
2347697SMichael.Christensen@Sun.COM ASSERT(num_nodes > 0);
2357697SMichael.Christensen@Sun.COM
2367697SMichael.Christensen@Sun.COM listsz = num_nodes * sizeof (mde_cookie_t);
2377697SMichael.Christensen@Sun.COM
2387697SMichael.Christensen@Sun.COM /* allocate temporary storage for MD scans */
2397697SMichael.Christensen@Sun.COM portp = kmem_zalloc(listsz, KM_SLEEP);
2407697SMichael.Christensen@Sun.COM chanp = kmem_zalloc(listsz, KM_SLEEP);
2417697SMichael.Christensen@Sun.COM
2427697SMichael.Christensen@Sun.COM rootnode = md_root_node(mdp);
2437697SMichael.Christensen@Sun.COM ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE);
2447697SMichael.Christensen@Sun.COM
2457697SMichael.Christensen@Sun.COM /*
2467697SMichael.Christensen@Sun.COM * The root of the search for DS port nodes is the
2477697SMichael.Christensen@Sun.COM * DS node. Perform a scan to find that node.
2487697SMichael.Christensen@Sun.COM */
2497697SMichael.Christensen@Sun.COM nport = md_scan_dag(mdp, rootnode, md_find_name(mdp, DS_MD_ROOT_NAME),
2507697SMichael.Christensen@Sun.COM md_find_name(mdp, "fwd"), portp);
2517697SMichael.Christensen@Sun.COM
2527697SMichael.Christensen@Sun.COM if (nport <= 0) {
2537697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "No '%s' node in MD", DS_MD_ROOT_NAME);
2547697SMichael.Christensen@Sun.COM goto done;
2557697SMichael.Christensen@Sun.COM }
2567697SMichael.Christensen@Sun.COM
2577697SMichael.Christensen@Sun.COM /* expecting only one DS node */
2587697SMichael.Christensen@Sun.COM if (nport != 1) {
2597697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "Expected one '%s' node in the MD, found %d",
2607697SMichael.Christensen@Sun.COM DS_MD_ROOT_NAME, nport);
2617697SMichael.Christensen@Sun.COM }
2627697SMichael.Christensen@Sun.COM
2637697SMichael.Christensen@Sun.COM dsnode = portp[0];
2647697SMichael.Christensen@Sun.COM
2657697SMichael.Christensen@Sun.COM /* find all the DS ports in the MD */
2667697SMichael.Christensen@Sun.COM nport = md_scan_dag(mdp, dsnode, md_find_name(mdp, DS_MD_PORT_NAME),
2677697SMichael.Christensen@Sun.COM md_find_name(mdp, "fwd"), portp);
2687697SMichael.Christensen@Sun.COM
2697697SMichael.Christensen@Sun.COM if (nport <= 0) {
2707697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "No '%s' nodes in MD", DS_MD_PORT_NAME);
2717697SMichael.Christensen@Sun.COM goto done;
2727697SMichael.Christensen@Sun.COM }
2737697SMichael.Christensen@Sun.COM
2747697SMichael.Christensen@Sun.COM /*
2757697SMichael.Christensen@Sun.COM * Initialize all the ports found in the MD.
2767697SMichael.Christensen@Sun.COM */
2777697SMichael.Christensen@Sun.COM for (idx = 0; idx < nport; idx++) {
2787697SMichael.Christensen@Sun.COM
2797697SMichael.Christensen@Sun.COM /* get the channels for this port */
2807697SMichael.Christensen@Sun.COM nchan = md_scan_dag(mdp, portp[idx],
2817697SMichael.Christensen@Sun.COM md_find_name(mdp, DS_MD_CHAN_NAME),
2827697SMichael.Christensen@Sun.COM md_find_name(mdp, "fwd"), chanp);
2837697SMichael.Christensen@Sun.COM
2847697SMichael.Christensen@Sun.COM if (nchan <= 0) {
2857697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "No '%s' node for DS port",
2867697SMichael.Christensen@Sun.COM DS_MD_CHAN_NAME);
2877697SMichael.Christensen@Sun.COM rv = -1;
2887697SMichael.Christensen@Sun.COM goto done;
2897697SMichael.Christensen@Sun.COM }
2907697SMichael.Christensen@Sun.COM
2917697SMichael.Christensen@Sun.COM /* expecting only one channel */
2927697SMichael.Christensen@Sun.COM if (nchan != 1) {
2937697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "Expected one '%s' node for DS "
2947697SMichael.Christensen@Sun.COM " port, found %d", DS_MD_CHAN_NAME, nchan);
2957697SMichael.Christensen@Sun.COM }
2967697SMichael.Christensen@Sun.COM
2977697SMichael.Christensen@Sun.COM if (ds_port_add(mdp, portp[idx], chanp[0]) != 0) {
2987697SMichael.Christensen@Sun.COM rv = -1;
2997697SMichael.Christensen@Sun.COM goto done;
3007697SMichael.Christensen@Sun.COM }
3017697SMichael.Christensen@Sun.COM }
3027697SMichael.Christensen@Sun.COM
3037697SMichael.Christensen@Sun.COM done:
3047697SMichael.Christensen@Sun.COM if (rv != 0)
3057697SMichael.Christensen@Sun.COM (void) ds_ports_fini();
3067697SMichael.Christensen@Sun.COM
3077697SMichael.Christensen@Sun.COM DS_FREE(portp, listsz);
3087697SMichael.Christensen@Sun.COM DS_FREE(chanp, listsz);
3097697SMichael.Christensen@Sun.COM
3107697SMichael.Christensen@Sun.COM (void) md_fini_handle(mdp);
3117697SMichael.Christensen@Sun.COM
3127697SMichael.Christensen@Sun.COM return (rv);
3137697SMichael.Christensen@Sun.COM }
3147697SMichael.Christensen@Sun.COM
3157697SMichael.Christensen@Sun.COM static int
ds_ports_fini(void)3167697SMichael.Christensen@Sun.COM ds_ports_fini(void)
3177697SMichael.Christensen@Sun.COM {
3187697SMichael.Christensen@Sun.COM int idx;
3197697SMichael.Christensen@Sun.COM
3207697SMichael.Christensen@Sun.COM /*
3217697SMichael.Christensen@Sun.COM * Tear down each initialized port.
3227697SMichael.Christensen@Sun.COM */
3237697SMichael.Christensen@Sun.COM for (idx = 0; idx < DS_MAX_PORTS; idx++) {
3247697SMichael.Christensen@Sun.COM if (DS_PORT_IN_SET(ds_allports, idx)) {
3257697SMichael.Christensen@Sun.COM (void) ds_remove_port(idx, 1);
3267697SMichael.Christensen@Sun.COM }
3277697SMichael.Christensen@Sun.COM }
3287697SMichael.Christensen@Sun.COM
3297697SMichael.Christensen@Sun.COM return (0);
3307697SMichael.Christensen@Sun.COM }
3317697SMichael.Christensen@Sun.COM
3327697SMichael.Christensen@Sun.COM static int
ds_port_add(md_t * mdp,mde_cookie_t port,mde_cookie_t chan)3337697SMichael.Christensen@Sun.COM ds_port_add(md_t *mdp, mde_cookie_t port, mde_cookie_t chan)
3347697SMichael.Christensen@Sun.COM {
3357697SMichael.Christensen@Sun.COM uint64_t port_id;
3367697SMichael.Christensen@Sun.COM uint64_t ldc_id;
3379603SMichael.Christensen@Sun.COM uint8_t *ldcidsp;
3389603SMichael.Christensen@Sun.COM int len;
3397697SMichael.Christensen@Sun.COM
3407697SMichael.Christensen@Sun.COM /* get the ID for this port */
3417697SMichael.Christensen@Sun.COM if (md_get_prop_val(mdp, port, "id", &port_id) != 0) {
3427697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "%s: port 'id' property not found",
3437697SMichael.Christensen@Sun.COM __func__);
3447697SMichael.Christensen@Sun.COM return (-1);
3457697SMichael.Christensen@Sun.COM }
3467697SMichael.Christensen@Sun.COM
3477697SMichael.Christensen@Sun.COM /* sanity check the port id */
3487697SMichael.Christensen@Sun.COM if (port_id > DS_MAX_PORT_ID) {
3497697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "%s: port ID %ld out of range",
3507697SMichael.Christensen@Sun.COM __func__, port_id);
3517697SMichael.Christensen@Sun.COM return (-1);
3527697SMichael.Christensen@Sun.COM }
3537697SMichael.Christensen@Sun.COM
3547697SMichael.Christensen@Sun.COM /* get the channel ID for this port */
3557697SMichael.Christensen@Sun.COM if (md_get_prop_val(mdp, chan, "id", &ldc_id) != 0) {
3567697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "ds@%lx: %s: no channel 'id' property",
3577697SMichael.Christensen@Sun.COM port_id, __func__);
3587697SMichael.Christensen@Sun.COM return (-1);
3597697SMichael.Christensen@Sun.COM }
3607697SMichael.Christensen@Sun.COM
3618172SMichael.Christensen@Sun.COM if (ds_add_port(port_id, ldc_id, DS_DHDL_INVALID, NULL, 1) != 0)
3627697SMichael.Christensen@Sun.COM return (-1);
3637697SMichael.Christensen@Sun.COM
3649603SMichael.Christensen@Sun.COM /*
3659603SMichael.Christensen@Sun.COM * Identify the SP Port. The SP port is the only one with
3669603SMichael.Christensen@Sun.COM * the "ldc-ids" property, and is only on the primary domain.
3679603SMichael.Christensen@Sun.COM */
3689603SMichael.Christensen@Sun.COM if (ds_sp_port_id == DS_PORTID_INVALID &&
3699603SMichael.Christensen@Sun.COM md_get_prop_data(mdp, port, "ldc-ids", &ldcidsp, &len) == 0) {
3709603SMichael.Christensen@Sun.COM ds_sp_port_id = port_id;
3719603SMichael.Christensen@Sun.COM }
3729603SMichael.Christensen@Sun.COM
3737697SMichael.Christensen@Sun.COM return (0);
3747697SMichael.Christensen@Sun.COM }
3757697SMichael.Christensen@Sun.COM
3767697SMichael.Christensen@Sun.COM void
ds_set_my_dom_hdl_name(ds_domain_hdl_t dhdl,char * name)3778172SMichael.Christensen@Sun.COM ds_set_my_dom_hdl_name(ds_domain_hdl_t dhdl, char *name)
3788172SMichael.Christensen@Sun.COM {
3798172SMichael.Christensen@Sun.COM ds_my_domain_hdl = dhdl;
3808172SMichael.Christensen@Sun.COM if (ds_my_domain_name != NULL) {
3818172SMichael.Christensen@Sun.COM DS_FREE(ds_my_domain_name, strlen(ds_my_domain_name)+1);
3828172SMichael.Christensen@Sun.COM ds_my_domain_name = NULL;
3838172SMichael.Christensen@Sun.COM }
3848172SMichael.Christensen@Sun.COM if (name != NULL) {
3858172SMichael.Christensen@Sun.COM ds_my_domain_name = ds_strdup(name);
3868172SMichael.Christensen@Sun.COM }
3878172SMichael.Christensen@Sun.COM }
3888172SMichael.Christensen@Sun.COM
3898172SMichael.Christensen@Sun.COM void
ds_init()3907697SMichael.Christensen@Sun.COM ds_init()
3917697SMichael.Christensen@Sun.COM {
3927697SMichael.Christensen@Sun.COM ds_common_init();
3937697SMichael.Christensen@Sun.COM
3947697SMichael.Christensen@Sun.COM /*
3957697SMichael.Christensen@Sun.COM * Create taskq for internal processing threads. This
3967697SMichael.Christensen@Sun.COM * includes processing incoming request messages and
3977697SMichael.Christensen@Sun.COM * sending out of band registration messages.
3987697SMichael.Christensen@Sun.COM */
3997697SMichael.Christensen@Sun.COM ds_taskq = taskq_create("ds_taskq", 1, minclsyspri, 1,
4007697SMichael.Christensen@Sun.COM DS_MAX_TASKQ_THR, TASKQ_PREPOPULATE | TASKQ_DYNAMIC);
4017697SMichael.Christensen@Sun.COM
4027697SMichael.Christensen@Sun.COM /*
4037697SMichael.Christensen@Sun.COM * Initialize the message log.
4047697SMichael.Christensen@Sun.COM */
4057697SMichael.Christensen@Sun.COM ds_log_init();
4067697SMichael.Christensen@Sun.COM }
4077697SMichael.Christensen@Sun.COM
4087697SMichael.Christensen@Sun.COM int
ds_sys_dispatch_func(void (func)(void *),void * arg)4097697SMichael.Christensen@Sun.COM ds_sys_dispatch_func(void (func)(void *), void *arg)
4107697SMichael.Christensen@Sun.COM {
4117697SMichael.Christensen@Sun.COM return (DS_DISPATCH(func, arg) == NULL);
4127697SMichael.Christensen@Sun.COM }
4137697SMichael.Christensen@Sun.COM
4147697SMichael.Christensen@Sun.COM /*
4157697SMichael.Christensen@Sun.COM * Drain event queue, if necessary.
4167697SMichael.Christensen@Sun.COM */
4177697SMichael.Christensen@Sun.COM void
ds_sys_drain_events(ds_port_t * port)4187697SMichael.Christensen@Sun.COM ds_sys_drain_events(ds_port_t *port)
4197697SMichael.Christensen@Sun.COM {
4207697SMichael.Christensen@Sun.COM _NOTE(ARGUNUSED(port))
4217697SMichael.Christensen@Sun.COM }
4227697SMichael.Christensen@Sun.COM
4237697SMichael.Christensen@Sun.COM /*
4247697SMichael.Christensen@Sun.COM * System specific port initalization.
4257697SMichael.Christensen@Sun.COM */
4267697SMichael.Christensen@Sun.COM void
ds_sys_port_init(ds_port_t * port)4277697SMichael.Christensen@Sun.COM ds_sys_port_init(ds_port_t *port)
4287697SMichael.Christensen@Sun.COM {
4297697SMichael.Christensen@Sun.COM _NOTE(ARGUNUSED(port))
4307697SMichael.Christensen@Sun.COM }
4317697SMichael.Christensen@Sun.COM
4327697SMichael.Christensen@Sun.COM /*
4337697SMichael.Christensen@Sun.COM * System specific port teardown.
4347697SMichael.Christensen@Sun.COM */
4357697SMichael.Christensen@Sun.COM void
ds_sys_port_fini(ds_port_t * port)4367697SMichael.Christensen@Sun.COM ds_sys_port_fini(ds_port_t *port)
4377697SMichael.Christensen@Sun.COM {
4387697SMichael.Christensen@Sun.COM _NOTE(ARGUNUSED(port))
4397697SMichael.Christensen@Sun.COM }
4407697SMichael.Christensen@Sun.COM
4417697SMichael.Christensen@Sun.COM /*
4427697SMichael.Christensen@Sun.COM * System specific LDC channel initialization.
4437697SMichael.Christensen@Sun.COM */
4447697SMichael.Christensen@Sun.COM void
ds_sys_ldc_init(ds_port_t * port)4457697SMichael.Christensen@Sun.COM ds_sys_ldc_init(ds_port_t *port)
4467697SMichael.Christensen@Sun.COM {
4477697SMichael.Christensen@Sun.COM int rv;
4487697SMichael.Christensen@Sun.COM char ebuf[DS_EBUFSIZE];
4497697SMichael.Christensen@Sun.COM
4507697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&port->lock));
4517697SMichael.Christensen@Sun.COM
4527697SMichael.Christensen@Sun.COM if ((rv = ldc_open(port->ldc.hdl)) != 0) {
4537697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "ds@%lx: %s: ldc_open: %s",
4547697SMichael.Christensen@Sun.COM PORTID(port), __func__, ds_errno_to_str(rv, ebuf));
4557697SMichael.Christensen@Sun.COM return;
4567697SMichael.Christensen@Sun.COM }
4577697SMichael.Christensen@Sun.COM
4587697SMichael.Christensen@Sun.COM (void) ldc_up(port->ldc.hdl);
4597697SMichael.Christensen@Sun.COM
4607697SMichael.Christensen@Sun.COM (void) ldc_status(port->ldc.hdl, &port->ldc.state);
4617697SMichael.Christensen@Sun.COM
4627697SMichael.Christensen@Sun.COM DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: initial LDC state 0x%x",
4637697SMichael.Christensen@Sun.COM PORTID(port), __func__, port->ldc.state);
4647697SMichael.Christensen@Sun.COM
4657697SMichael.Christensen@Sun.COM port->state = DS_PORT_LDC_INIT;
4667697SMichael.Christensen@Sun.COM }
4677697SMichael.Christensen@Sun.COM
4687697SMichael.Christensen@Sun.COM /*
4697697SMichael.Christensen@Sun.COM * DS message log
4707697SMichael.Christensen@Sun.COM *
4717697SMichael.Christensen@Sun.COM * Locking: The message log is protected by a single mutex. This
4727697SMichael.Christensen@Sun.COM * protects all fields in the log structure itself as well as
4737697SMichael.Christensen@Sun.COM * everything in the entry structures on both the log and the
4747697SMichael.Christensen@Sun.COM * free list.
4757697SMichael.Christensen@Sun.COM */
4767697SMichael.Christensen@Sun.COM static struct log {
4777697SMichael.Christensen@Sun.COM ds_log_entry_t *head; /* head of the log */
4787697SMichael.Christensen@Sun.COM ds_log_entry_t *freelist; /* head of the free list */
4797697SMichael.Christensen@Sun.COM size_t size; /* size of the log in bytes */
4807697SMichael.Christensen@Sun.COM uint32_t nentry; /* number of entries */
4817697SMichael.Christensen@Sun.COM kmutex_t lock; /* log lock */
4827697SMichael.Christensen@Sun.COM } ds_log;
4837697SMichael.Christensen@Sun.COM
4847697SMichael.Christensen@Sun.COM /* log soft limit */
4857697SMichael.Christensen@Sun.COM uint_t ds_log_sz = DS_LOG_DEFAULT_SZ;
4867697SMichael.Christensen@Sun.COM
4877697SMichael.Christensen@Sun.COM /* initial pool of log entry structures */
4887697SMichael.Christensen@Sun.COM static ds_log_entry_t ds_log_entry_pool[DS_LOG_NPOOL];
4897697SMichael.Christensen@Sun.COM
4907697SMichael.Christensen@Sun.COM /*
4917697SMichael.Christensen@Sun.COM * Logging Support
4927697SMichael.Christensen@Sun.COM */
4937697SMichael.Christensen@Sun.COM static void
ds_log_init(void)4947697SMichael.Christensen@Sun.COM ds_log_init(void)
4957697SMichael.Christensen@Sun.COM {
4967697SMichael.Christensen@Sun.COM ds_log_entry_t *new;
4977697SMichael.Christensen@Sun.COM
4987697SMichael.Christensen@Sun.COM /* initialize global lock */
4997697SMichael.Christensen@Sun.COM mutex_init(&ds_log.lock, NULL, MUTEX_DRIVER, NULL);
5007697SMichael.Christensen@Sun.COM
5017697SMichael.Christensen@Sun.COM mutex_enter(&ds_log.lock);
5027697SMichael.Christensen@Sun.COM
5037697SMichael.Christensen@Sun.COM /* initialize the log */
5047697SMichael.Christensen@Sun.COM ds_log.head = NULL;
5057697SMichael.Christensen@Sun.COM ds_log.size = 0;
5067697SMichael.Christensen@Sun.COM ds_log.nentry = 0;
5077697SMichael.Christensen@Sun.COM
5087697SMichael.Christensen@Sun.COM /* initialize the free list */
5097697SMichael.Christensen@Sun.COM for (new = ds_log_entry_pool; new < DS_LOG_POOL_END; new++) {
5107697SMichael.Christensen@Sun.COM new->next = ds_log.freelist;
5117697SMichael.Christensen@Sun.COM ds_log.freelist = new;
5127697SMichael.Christensen@Sun.COM }
5137697SMichael.Christensen@Sun.COM
5147697SMichael.Christensen@Sun.COM mutex_exit(&ds_log.lock);
5157697SMichael.Christensen@Sun.COM
5167697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "ds_log initialized: size=%d bytes, "
5177697SMichael.Christensen@Sun.COM " limit=%d bytes, ninit=%ld", ds_log_sz, DS_LOG_LIMIT,
5187697SMichael.Christensen@Sun.COM DS_LOG_NPOOL);
5197697SMichael.Christensen@Sun.COM }
5207697SMichael.Christensen@Sun.COM
5217697SMichael.Christensen@Sun.COM static void
ds_log_fini(void)5227697SMichael.Christensen@Sun.COM ds_log_fini(void)
5237697SMichael.Christensen@Sun.COM {
5247697SMichael.Christensen@Sun.COM ds_log_entry_t *next;
5257697SMichael.Christensen@Sun.COM
5267697SMichael.Christensen@Sun.COM mutex_enter(&ds_log.lock);
5277697SMichael.Christensen@Sun.COM
5287697SMichael.Christensen@Sun.COM /* clear out the log */
5297697SMichael.Christensen@Sun.COM while (ds_log.nentry > 0)
5307697SMichael.Christensen@Sun.COM (void) ds_log_remove();
5317697SMichael.Christensen@Sun.COM
5327697SMichael.Christensen@Sun.COM /*
5337697SMichael.Christensen@Sun.COM * Now all the entries are on the free list.
5347697SMichael.Christensen@Sun.COM * Clear out the free list, deallocating any
5357697SMichael.Christensen@Sun.COM * entry that was dynamically allocated.
5367697SMichael.Christensen@Sun.COM */
5377697SMichael.Christensen@Sun.COM while (ds_log.freelist != NULL) {
5387697SMichael.Christensen@Sun.COM next = ds_log.freelist->next;
5397697SMichael.Christensen@Sun.COM
5407697SMichael.Christensen@Sun.COM if (!DS_IS_POOL_ENTRY(ds_log.freelist)) {
5417697SMichael.Christensen@Sun.COM kmem_free(ds_log.freelist, sizeof (ds_log_entry_t));
5427697SMichael.Christensen@Sun.COM }
5437697SMichael.Christensen@Sun.COM
5447697SMichael.Christensen@Sun.COM ds_log.freelist = next;
5457697SMichael.Christensen@Sun.COM }
5467697SMichael.Christensen@Sun.COM
5477697SMichael.Christensen@Sun.COM mutex_exit(&ds_log.lock);
5487697SMichael.Christensen@Sun.COM
5497697SMichael.Christensen@Sun.COM mutex_destroy(&ds_log.lock);
5507697SMichael.Christensen@Sun.COM }
5517697SMichael.Christensen@Sun.COM
5527697SMichael.Christensen@Sun.COM static ds_log_entry_t *
ds_log_entry_alloc(void)5537697SMichael.Christensen@Sun.COM ds_log_entry_alloc(void)
5547697SMichael.Christensen@Sun.COM {
5557697SMichael.Christensen@Sun.COM ds_log_entry_t *new = NULL;
5567697SMichael.Christensen@Sun.COM
5577697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&ds_log.lock));
5587697SMichael.Christensen@Sun.COM
5597697SMichael.Christensen@Sun.COM if (ds_log.freelist != NULL) {
5607697SMichael.Christensen@Sun.COM new = ds_log.freelist;
5617697SMichael.Christensen@Sun.COM ds_log.freelist = ds_log.freelist->next;
5627697SMichael.Christensen@Sun.COM }
5637697SMichael.Christensen@Sun.COM
5647697SMichael.Christensen@Sun.COM if (new == NULL) {
5657697SMichael.Christensen@Sun.COM /* free list was empty */
5667697SMichael.Christensen@Sun.COM new = kmem_zalloc(sizeof (ds_log_entry_t), KM_SLEEP);
5677697SMichael.Christensen@Sun.COM }
5687697SMichael.Christensen@Sun.COM
5697697SMichael.Christensen@Sun.COM ASSERT(new);
5707697SMichael.Christensen@Sun.COM
5717697SMichael.Christensen@Sun.COM return (new);
5727697SMichael.Christensen@Sun.COM }
5737697SMichael.Christensen@Sun.COM
5747697SMichael.Christensen@Sun.COM static void
ds_log_entry_free(ds_log_entry_t * entry)5757697SMichael.Christensen@Sun.COM ds_log_entry_free(ds_log_entry_t *entry)
5767697SMichael.Christensen@Sun.COM {
5777697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&ds_log.lock));
5787697SMichael.Christensen@Sun.COM
5797697SMichael.Christensen@Sun.COM if (entry == NULL)
5807697SMichael.Christensen@Sun.COM return;
5817697SMichael.Christensen@Sun.COM
5827697SMichael.Christensen@Sun.COM if (entry->data != NULL) {
5837697SMichael.Christensen@Sun.COM kmem_free(entry->data, entry->datasz);
5847697SMichael.Christensen@Sun.COM entry->data = NULL;
5857697SMichael.Christensen@Sun.COM }
5867697SMichael.Christensen@Sun.COM
5877697SMichael.Christensen@Sun.COM /* place entry on the free list */
5887697SMichael.Christensen@Sun.COM entry->next = ds_log.freelist;
5897697SMichael.Christensen@Sun.COM ds_log.freelist = entry;
5907697SMichael.Christensen@Sun.COM }
5917697SMichael.Christensen@Sun.COM
5927697SMichael.Christensen@Sun.COM /*
5937697SMichael.Christensen@Sun.COM * Add a message to the end of the log
5947697SMichael.Christensen@Sun.COM */
5957697SMichael.Christensen@Sun.COM static int
ds_log_add(ds_log_entry_t * new)5967697SMichael.Christensen@Sun.COM ds_log_add(ds_log_entry_t *new)
5977697SMichael.Christensen@Sun.COM {
5987697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&ds_log.lock));
5997697SMichael.Christensen@Sun.COM
6007697SMichael.Christensen@Sun.COM if (ds_log.head == NULL) {
6017697SMichael.Christensen@Sun.COM
6027697SMichael.Christensen@Sun.COM new->prev = new;
6037697SMichael.Christensen@Sun.COM new->next = new;
6047697SMichael.Christensen@Sun.COM
6057697SMichael.Christensen@Sun.COM ds_log.head = new;
6067697SMichael.Christensen@Sun.COM } else {
6077697SMichael.Christensen@Sun.COM ds_log_entry_t *head = ds_log.head;
6087697SMichael.Christensen@Sun.COM ds_log_entry_t *tail = ds_log.head->prev;
6097697SMichael.Christensen@Sun.COM
6107697SMichael.Christensen@Sun.COM new->next = head;
6117697SMichael.Christensen@Sun.COM new->prev = tail;
6127697SMichael.Christensen@Sun.COM tail->next = new;
6137697SMichael.Christensen@Sun.COM head->prev = new;
6147697SMichael.Christensen@Sun.COM }
6157697SMichael.Christensen@Sun.COM
6167697SMichael.Christensen@Sun.COM /* increase the log size, including the metadata size */
6177697SMichael.Christensen@Sun.COM ds_log.size += DS_LOG_ENTRY_SZ(new);
6187697SMichael.Christensen@Sun.COM ds_log.nentry++;
6197697SMichael.Christensen@Sun.COM
6207697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "ds_log: added %ld data bytes, %ld total bytes",
6217697SMichael.Christensen@Sun.COM new->datasz, DS_LOG_ENTRY_SZ(new));
6227697SMichael.Christensen@Sun.COM
6237697SMichael.Christensen@Sun.COM return (0);
6247697SMichael.Christensen@Sun.COM }
6257697SMichael.Christensen@Sun.COM
6267697SMichael.Christensen@Sun.COM /*
6277697SMichael.Christensen@Sun.COM * Remove an entry from the head of the log
6287697SMichael.Christensen@Sun.COM */
6297697SMichael.Christensen@Sun.COM static int
ds_log_remove(void)6307697SMichael.Christensen@Sun.COM ds_log_remove(void)
6317697SMichael.Christensen@Sun.COM {
6327697SMichael.Christensen@Sun.COM ds_log_entry_t *head;
6337697SMichael.Christensen@Sun.COM
6347697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&ds_log.lock));
6357697SMichael.Christensen@Sun.COM
6367697SMichael.Christensen@Sun.COM head = ds_log.head;
6377697SMichael.Christensen@Sun.COM
6387697SMichael.Christensen@Sun.COM /* empty list */
6397697SMichael.Christensen@Sun.COM if (head == NULL)
6407697SMichael.Christensen@Sun.COM return (0);
6417697SMichael.Christensen@Sun.COM
6427697SMichael.Christensen@Sun.COM if (head->next == ds_log.head) {
6437697SMichael.Christensen@Sun.COM /* one element list */
6447697SMichael.Christensen@Sun.COM ds_log.head = NULL;
6457697SMichael.Christensen@Sun.COM } else {
6467697SMichael.Christensen@Sun.COM head->next->prev = head->prev;
6477697SMichael.Christensen@Sun.COM head->prev->next = head->next;
6487697SMichael.Christensen@Sun.COM ds_log.head = head->next;
6497697SMichael.Christensen@Sun.COM }
6507697SMichael.Christensen@Sun.COM
6517697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "ds_log: removed %ld data bytes, %ld total bytes",
6527697SMichael.Christensen@Sun.COM head->datasz, DS_LOG_ENTRY_SZ(head));
6537697SMichael.Christensen@Sun.COM
6547697SMichael.Christensen@Sun.COM ds_log.size -= DS_LOG_ENTRY_SZ(head);
6557697SMichael.Christensen@Sun.COM ds_log.nentry--;
6567697SMichael.Christensen@Sun.COM
6577697SMichael.Christensen@Sun.COM ds_log_entry_free(head);
6587697SMichael.Christensen@Sun.COM
6597697SMichael.Christensen@Sun.COM return (0);
6607697SMichael.Christensen@Sun.COM }
6617697SMichael.Christensen@Sun.COM
6627697SMichael.Christensen@Sun.COM /*
6637697SMichael.Christensen@Sun.COM * Replace the data in the entry at the front of the list with then
6647697SMichael.Christensen@Sun.COM * new data. This has the effect of removing the oldest entry and
6657697SMichael.Christensen@Sun.COM * adding the new entry.
6667697SMichael.Christensen@Sun.COM */
6677697SMichael.Christensen@Sun.COM static int
ds_log_replace(int32_t dest,uint8_t * msg,size_t sz)6687697SMichael.Christensen@Sun.COM ds_log_replace(int32_t dest, uint8_t *msg, size_t sz)
6697697SMichael.Christensen@Sun.COM {
6707697SMichael.Christensen@Sun.COM ds_log_entry_t *head;
6717697SMichael.Christensen@Sun.COM
6727697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&ds_log.lock));
6737697SMichael.Christensen@Sun.COM
6747697SMichael.Christensen@Sun.COM head = ds_log.head;
6757697SMichael.Christensen@Sun.COM
6767697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "ds_log: replaced %ld data bytes (%ld total) with "
6777697SMichael.Christensen@Sun.COM " %ld data bytes (%ld total)", head->datasz,
6787697SMichael.Christensen@Sun.COM DS_LOG_ENTRY_SZ(head), sz, sz + sizeof (ds_log_entry_t));
6797697SMichael.Christensen@Sun.COM
6807697SMichael.Christensen@Sun.COM ds_log.size -= DS_LOG_ENTRY_SZ(head);
6817697SMichael.Christensen@Sun.COM
6827697SMichael.Christensen@Sun.COM kmem_free(head->data, head->datasz);
6837697SMichael.Christensen@Sun.COM
6847697SMichael.Christensen@Sun.COM head->data = msg;
6857697SMichael.Christensen@Sun.COM head->datasz = sz;
6867697SMichael.Christensen@Sun.COM head->timestamp = ddi_get_time();
6877697SMichael.Christensen@Sun.COM head->dest = dest;
6887697SMichael.Christensen@Sun.COM
6897697SMichael.Christensen@Sun.COM ds_log.size += DS_LOG_ENTRY_SZ(head);
6907697SMichael.Christensen@Sun.COM
6917697SMichael.Christensen@Sun.COM ds_log.head = head->next;
6927697SMichael.Christensen@Sun.COM
6937697SMichael.Christensen@Sun.COM return (0);
6947697SMichael.Christensen@Sun.COM }
6957697SMichael.Christensen@Sun.COM
6967697SMichael.Christensen@Sun.COM static void
ds_log_purge(void * arg)6977697SMichael.Christensen@Sun.COM ds_log_purge(void *arg)
6987697SMichael.Christensen@Sun.COM {
6997697SMichael.Christensen@Sun.COM _NOTE(ARGUNUSED(arg))
7007697SMichael.Christensen@Sun.COM
7017697SMichael.Christensen@Sun.COM mutex_enter(&ds_log.lock);
7027697SMichael.Christensen@Sun.COM
7037697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "ds_log: purging oldest log entries");
7047697SMichael.Christensen@Sun.COM
7057697SMichael.Christensen@Sun.COM while ((ds_log.nentry) && (ds_log.size >= ds_log_sz)) {
7067697SMichael.Christensen@Sun.COM (void) ds_log_remove();
7077697SMichael.Christensen@Sun.COM }
7087697SMichael.Christensen@Sun.COM
7097697SMichael.Christensen@Sun.COM mutex_exit(&ds_log.lock);
7107697SMichael.Christensen@Sun.COM }
7117697SMichael.Christensen@Sun.COM
7127697SMichael.Christensen@Sun.COM int
ds_log_add_msg(int32_t dest,uint8_t * msg,size_t sz)7137697SMichael.Christensen@Sun.COM ds_log_add_msg(int32_t dest, uint8_t *msg, size_t sz)
7147697SMichael.Christensen@Sun.COM {
7157697SMichael.Christensen@Sun.COM int rv = 0;
7167697SMichael.Christensen@Sun.COM void *data;
7177697SMichael.Christensen@Sun.COM
7187697SMichael.Christensen@Sun.COM mutex_enter(&ds_log.lock);
7197697SMichael.Christensen@Sun.COM
7207697SMichael.Christensen@Sun.COM /* allocate a local copy of the data */
7217697SMichael.Christensen@Sun.COM data = kmem_alloc(sz, KM_SLEEP);
7227697SMichael.Christensen@Sun.COM bcopy(msg, data, sz);
7237697SMichael.Christensen@Sun.COM
7247697SMichael.Christensen@Sun.COM /* check if the log is larger than the soft limit */
7257697SMichael.Christensen@Sun.COM if ((ds_log.nentry) && ((ds_log.size + sz) >= ds_log_sz)) {
7267697SMichael.Christensen@Sun.COM /*
7277697SMichael.Christensen@Sun.COM * The log is larger than the soft limit.
7287697SMichael.Christensen@Sun.COM * Swap the oldest entry for the newest.
7297697SMichael.Christensen@Sun.COM */
7307697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "%s: replacing oldest entry with new entry",
7317697SMichael.Christensen@Sun.COM __func__);
7327697SMichael.Christensen@Sun.COM (void) ds_log_replace(dest, data, sz);
7337697SMichael.Christensen@Sun.COM } else {
7347697SMichael.Christensen@Sun.COM /*
7357697SMichael.Christensen@Sun.COM * Still have headroom under the soft limit.
7367697SMichael.Christensen@Sun.COM * Add the new entry to the log.
7377697SMichael.Christensen@Sun.COM */
7387697SMichael.Christensen@Sun.COM ds_log_entry_t *new;
7397697SMichael.Christensen@Sun.COM
7407697SMichael.Christensen@Sun.COM new = ds_log_entry_alloc();
7417697SMichael.Christensen@Sun.COM
7427697SMichael.Christensen@Sun.COM /* fill in message data */
7437697SMichael.Christensen@Sun.COM new->data = data;
7447697SMichael.Christensen@Sun.COM new->datasz = sz;
7457697SMichael.Christensen@Sun.COM new->timestamp = ddi_get_time();
7467697SMichael.Christensen@Sun.COM new->dest = dest;
7477697SMichael.Christensen@Sun.COM
7487697SMichael.Christensen@Sun.COM rv = ds_log_add(new);
7497697SMichael.Christensen@Sun.COM }
7507697SMichael.Christensen@Sun.COM
7517697SMichael.Christensen@Sun.COM /* check if the log is larger than the hard limit */
7527697SMichael.Christensen@Sun.COM if ((ds_log.nentry > 1) && (ds_log.size >= DS_LOG_LIMIT)) {
7537697SMichael.Christensen@Sun.COM /*
7547697SMichael.Christensen@Sun.COM * Wakeup the thread to remove entries
7557697SMichael.Christensen@Sun.COM * from the log until it is smaller than
7567697SMichael.Christensen@Sun.COM * the soft limit.
7577697SMichael.Christensen@Sun.COM */
7587697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "%s: log exceeded %d bytes, scheduling"
7597697SMichael.Christensen@Sun.COM " a purge...", __func__, DS_LOG_LIMIT);
7607697SMichael.Christensen@Sun.COM
7617697SMichael.Christensen@Sun.COM if (DS_DISPATCH(ds_log_purge, NULL) == NULL) {
7627697SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "%s: purge thread failed to start",
7637697SMichael.Christensen@Sun.COM __func__);
7647697SMichael.Christensen@Sun.COM }
7657697SMichael.Christensen@Sun.COM }
7667697SMichael.Christensen@Sun.COM
7677697SMichael.Christensen@Sun.COM mutex_exit(&ds_log.lock);
7687697SMichael.Christensen@Sun.COM
7697697SMichael.Christensen@Sun.COM return (rv);
7707697SMichael.Christensen@Sun.COM }
7717697SMichael.Christensen@Sun.COM
7727697SMichael.Christensen@Sun.COM int
ds_add_port(uint64_t port_id,uint64_t ldc_id,ds_domain_hdl_t dhdl,char * dom_name,int verbose)7737697SMichael.Christensen@Sun.COM ds_add_port(uint64_t port_id, uint64_t ldc_id, ds_domain_hdl_t dhdl,
7747697SMichael.Christensen@Sun.COM char *dom_name, int verbose)
7757697SMichael.Christensen@Sun.COM {
7767697SMichael.Christensen@Sun.COM ds_port_t *newport;
7777697SMichael.Christensen@Sun.COM
7787697SMichael.Christensen@Sun.COM /* sanity check the port id */
7797697SMichael.Christensen@Sun.COM if (port_id > DS_MAX_PORT_ID) {
7807697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "%s: port ID %ld out of range",
7817697SMichael.Christensen@Sun.COM __func__, port_id);
7827697SMichael.Christensen@Sun.COM return (EINVAL);
7837697SMichael.Christensen@Sun.COM }
7847697SMichael.Christensen@Sun.COM
7858172SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "%s: adding port ds@%ld, LDC: 0x%lx, dhdl: 0x%lx "
7868172SMichael.Christensen@Sun.COM "name: '%s'", __func__, port_id, ldc_id, dhdl,
7878172SMichael.Christensen@Sun.COM dom_name == NULL ? "NULL" : dom_name);
7887697SMichael.Christensen@Sun.COM
7897697SMichael.Christensen@Sun.COM /* get the port structure from the array of ports */
7907697SMichael.Christensen@Sun.COM newport = &ds_ports[port_id];
7917697SMichael.Christensen@Sun.COM
7927697SMichael.Christensen@Sun.COM /* check for a duplicate port in the MD */
7937697SMichael.Christensen@Sun.COM if (newport->state != DS_PORT_FREE) {
7947697SMichael.Christensen@Sun.COM if (verbose) {
7957697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "ds@%lx: %s: port already exists",
7967697SMichael.Christensen@Sun.COM port_id, __func__);
7977697SMichael.Christensen@Sun.COM }
7987697SMichael.Christensen@Sun.COM if (newport->domain_hdl == DS_DHDL_INVALID) {
7997697SMichael.Christensen@Sun.COM newport->domain_hdl = dhdl;
8007697SMichael.Christensen@Sun.COM }
8017697SMichael.Christensen@Sun.COM if (newport->domain_name == NULL && dom_name != NULL) {
8027697SMichael.Christensen@Sun.COM newport->domain_name = ds_strdup(dom_name);
8037697SMichael.Christensen@Sun.COM }
8047697SMichael.Christensen@Sun.COM return (EBUSY);
8057697SMichael.Christensen@Sun.COM }
8067697SMichael.Christensen@Sun.COM
8077697SMichael.Christensen@Sun.COM /* initialize the port */
8087697SMichael.Christensen@Sun.COM newport->id = port_id;
8097697SMichael.Christensen@Sun.COM newport->ldc.id = ldc_id;
8107697SMichael.Christensen@Sun.COM newport->domain_hdl = dhdl;
8117697SMichael.Christensen@Sun.COM if (dom_name) {
8127697SMichael.Christensen@Sun.COM newport->domain_name = ds_strdup(dom_name);
8137697SMichael.Christensen@Sun.COM } else
8147697SMichael.Christensen@Sun.COM newport->domain_name = NULL;
8157697SMichael.Christensen@Sun.COM ds_port_common_init(newport);
8167697SMichael.Christensen@Sun.COM
8177697SMichael.Christensen@Sun.COM return (0);
8187697SMichael.Christensen@Sun.COM }
8197697SMichael.Christensen@Sun.COM
820*9916SMichael.Christensen@Sun.COM /* ARGSUSED */
8217697SMichael.Christensen@Sun.COM int
ds_remove_port(uint64_t port_id,int is_fini)8227697SMichael.Christensen@Sun.COM ds_remove_port(uint64_t port_id, int is_fini)
8237697SMichael.Christensen@Sun.COM {
8247697SMichael.Christensen@Sun.COM ds_port_t *port;
8257697SMichael.Christensen@Sun.COM
8267697SMichael.Christensen@Sun.COM if (port_id >= DS_MAX_PORTS || !DS_PORT_IN_SET(ds_allports, port_id)) {
8277697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "%s: invalid port %lx", __func__,
8287697SMichael.Christensen@Sun.COM port_id);
8297697SMichael.Christensen@Sun.COM return (EINVAL);
8307697SMichael.Christensen@Sun.COM }
8317697SMichael.Christensen@Sun.COM
8327697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "%s: removing port ds@%lx", __func__, port_id);
8337697SMichael.Christensen@Sun.COM
8347697SMichael.Christensen@Sun.COM port = &ds_ports[port_id];
8357697SMichael.Christensen@Sun.COM
8367697SMichael.Christensen@Sun.COM mutex_enter(&port->lock);
8377697SMichael.Christensen@Sun.COM
8387697SMichael.Christensen@Sun.COM if (port->state >= DS_PORT_LDC_INIT) {
8397697SMichael.Christensen@Sun.COM /* shut down the LDC for this port */
8407697SMichael.Christensen@Sun.COM (void) ds_ldc_fini(port);
8417697SMichael.Christensen@Sun.COM }
8427697SMichael.Christensen@Sun.COM
8437697SMichael.Christensen@Sun.COM if (port->domain_name) {
8447697SMichael.Christensen@Sun.COM DS_FREE(port->domain_name, strlen(port->domain_name) + 1);
8457697SMichael.Christensen@Sun.COM port->domain_name = NULL;
8467697SMichael.Christensen@Sun.COM }
8477697SMichael.Christensen@Sun.COM port->domain_hdl = DS_DHDL_INVALID;
8487697SMichael.Christensen@Sun.COM
8497697SMichael.Christensen@Sun.COM /* clean up the port structure */
850*9916SMichael.Christensen@Sun.COM ds_port_common_fini(port);
851*9916SMichael.Christensen@Sun.COM
852*9916SMichael.Christensen@Sun.COM mutex_exit(&port->lock);
8537697SMichael.Christensen@Sun.COM return (0);
8547697SMichael.Christensen@Sun.COM }
8557697SMichael.Christensen@Sun.COM
8567697SMichael.Christensen@Sun.COM /*
8577697SMichael.Christensen@Sun.COM * Interface for ds_service_lookup in lds driver.
8587697SMichael.Christensen@Sun.COM */
8597697SMichael.Christensen@Sun.COM int
ds_service_lookup(ds_svc_hdl_t hdl,char ** servicep,uint_t * is_client)8607697SMichael.Christensen@Sun.COM ds_service_lookup(ds_svc_hdl_t hdl, char **servicep, uint_t *is_client)
8617697SMichael.Christensen@Sun.COM {
8627697SMichael.Christensen@Sun.COM ds_svc_t *svc;
8637697SMichael.Christensen@Sun.COM
8647697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock);
8657697SMichael.Christensen@Sun.COM if ((svc = ds_get_svc(hdl)) == NULL) {
8667697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
8677697SMichael.Christensen@Sun.COM DS_DBG(CE_NOTE, "%s: handle 0x%llx not found", __func__,
8687697SMichael.Christensen@Sun.COM (u_longlong_t)hdl);
8697697SMichael.Christensen@Sun.COM return (ENXIO);
8707697SMichael.Christensen@Sun.COM }
8717697SMichael.Christensen@Sun.COM *servicep = svc->cap.svc_id;
8727697SMichael.Christensen@Sun.COM *is_client = svc->flags & DSSF_ISCLIENT;
8737697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
8747697SMichael.Christensen@Sun.COM return (0);
8757697SMichael.Christensen@Sun.COM }
8767697SMichael.Christensen@Sun.COM
8777697SMichael.Christensen@Sun.COM /*
8787697SMichael.Christensen@Sun.COM * Interface for ds_domain_lookup in lds driver.
8797697SMichael.Christensen@Sun.COM */
8807697SMichael.Christensen@Sun.COM int
ds_domain_lookup(ds_svc_hdl_t hdl,ds_domain_hdl_t * dhdlp)8817697SMichael.Christensen@Sun.COM ds_domain_lookup(ds_svc_hdl_t hdl, ds_domain_hdl_t *dhdlp)
8827697SMichael.Christensen@Sun.COM {
8837697SMichael.Christensen@Sun.COM ds_svc_t *svc;
8847697SMichael.Christensen@Sun.COM
8857697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock);
8867697SMichael.Christensen@Sun.COM if ((svc = ds_get_svc(hdl)) == NULL) {
8877697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
8887697SMichael.Christensen@Sun.COM DS_DBG(CE_NOTE, "%s: handle 0x%llx not found", __func__,
8897697SMichael.Christensen@Sun.COM (u_longlong_t)hdl);
8907697SMichael.Christensen@Sun.COM return (ENXIO);
8917697SMichael.Christensen@Sun.COM }
8927697SMichael.Christensen@Sun.COM if (svc->port == NULL)
8937697SMichael.Christensen@Sun.COM *dhdlp = ds_my_domain_hdl;
8947697SMichael.Christensen@Sun.COM else
8957697SMichael.Christensen@Sun.COM *dhdlp = svc->port->domain_hdl;
8967697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
8977697SMichael.Christensen@Sun.COM return (0);
8987697SMichael.Christensen@Sun.COM }
8997697SMichael.Christensen@Sun.COM
9007697SMichael.Christensen@Sun.COM /*
9017697SMichael.Christensen@Sun.COM * Interface for ds_hdl_isready in lds driver.
9027697SMichael.Christensen@Sun.COM */
9037697SMichael.Christensen@Sun.COM int
ds_hdl_isready(ds_svc_hdl_t hdl,uint_t * is_ready)9047697SMichael.Christensen@Sun.COM ds_hdl_isready(ds_svc_hdl_t hdl, uint_t *is_ready)
9057697SMichael.Christensen@Sun.COM {
9067697SMichael.Christensen@Sun.COM ds_svc_t *svc;
9077697SMichael.Christensen@Sun.COM
9087697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock);
9097697SMichael.Christensen@Sun.COM if ((svc = ds_get_svc(hdl)) == NULL) {
9107697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
9117697SMichael.Christensen@Sun.COM DS_DBG(CE_NOTE, "%s: handle 0x%llx not found", __func__,
9127697SMichael.Christensen@Sun.COM (u_longlong_t)hdl);
9137697SMichael.Christensen@Sun.COM return (ENXIO);
9147697SMichael.Christensen@Sun.COM }
9157697SMichael.Christensen@Sun.COM *is_ready = (svc->state == DS_SVC_ACTIVE);
9167697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
9177697SMichael.Christensen@Sun.COM return (0);
9187697SMichael.Christensen@Sun.COM }
9197697SMichael.Christensen@Sun.COM
9207697SMichael.Christensen@Sun.COM /*
9217697SMichael.Christensen@Sun.COM * Interface for ds_dom_name_to_hdl in lds driver.
9227697SMichael.Christensen@Sun.COM */
9237697SMichael.Christensen@Sun.COM int
ds_dom_name_to_hdl(char * domain_name,ds_domain_hdl_t * dhdlp)9247697SMichael.Christensen@Sun.COM ds_dom_name_to_hdl(char *domain_name, ds_domain_hdl_t *dhdlp)
9257697SMichael.Christensen@Sun.COM {
9267697SMichael.Christensen@Sun.COM int i;
9277697SMichael.Christensen@Sun.COM ds_port_t *port;
9287697SMichael.Christensen@Sun.COM
9298172SMichael.Christensen@Sun.COM if (domain_name == NULL) {
9308172SMichael.Christensen@Sun.COM return (ENXIO);
9318172SMichael.Christensen@Sun.COM }
9328172SMichael.Christensen@Sun.COM if (ds_my_domain_name != NULL &&
9338172SMichael.Christensen@Sun.COM strcmp(ds_my_domain_name, domain_name) == 0) {
9348172SMichael.Christensen@Sun.COM *dhdlp = ds_my_domain_hdl;
9358172SMichael.Christensen@Sun.COM return (0);
9368172SMichael.Christensen@Sun.COM }
9377697SMichael.Christensen@Sun.COM for (i = 0, port = ds_ports; i < DS_MAX_PORTS; i++, port++) {
9387697SMichael.Christensen@Sun.COM if (port->state != DS_PORT_FREE &&
9397697SMichael.Christensen@Sun.COM port->domain_name != NULL &&
9407697SMichael.Christensen@Sun.COM strcmp(port->domain_name, domain_name) == 0) {
9417697SMichael.Christensen@Sun.COM *dhdlp = port->domain_hdl;
9427697SMichael.Christensen@Sun.COM return (0);
9437697SMichael.Christensen@Sun.COM }
9447697SMichael.Christensen@Sun.COM }
9457697SMichael.Christensen@Sun.COM return (ENXIO);
9467697SMichael.Christensen@Sun.COM }
9477697SMichael.Christensen@Sun.COM
9487697SMichael.Christensen@Sun.COM /*
9497697SMichael.Christensen@Sun.COM * Interface for ds_dom_hdl_to_name in lds driver.
9507697SMichael.Christensen@Sun.COM */
9517697SMichael.Christensen@Sun.COM int
ds_dom_hdl_to_name(ds_domain_hdl_t dhdl,char ** domain_namep)9527697SMichael.Christensen@Sun.COM ds_dom_hdl_to_name(ds_domain_hdl_t dhdl, char **domain_namep)
9537697SMichael.Christensen@Sun.COM {
9547697SMichael.Christensen@Sun.COM int i;
9557697SMichael.Christensen@Sun.COM ds_port_t *port;
9567697SMichael.Christensen@Sun.COM
9578172SMichael.Christensen@Sun.COM if (dhdl == ds_my_domain_hdl) {
9588172SMichael.Christensen@Sun.COM if (ds_my_domain_name != NULL) {
9598172SMichael.Christensen@Sun.COM *domain_namep = ds_my_domain_name;
9608172SMichael.Christensen@Sun.COM return (0);
9618172SMichael.Christensen@Sun.COM }
9628172SMichael.Christensen@Sun.COM return (ENXIO);
9638172SMichael.Christensen@Sun.COM }
9647697SMichael.Christensen@Sun.COM for (i = 0, port = ds_ports; i < DS_MAX_PORTS; i++, port++) {
9657697SMichael.Christensen@Sun.COM if (port->state != DS_PORT_FREE &&
9667697SMichael.Christensen@Sun.COM port->domain_hdl == dhdl) {
9677697SMichael.Christensen@Sun.COM *domain_namep = port->domain_name;
9687697SMichael.Christensen@Sun.COM return (0);
9697697SMichael.Christensen@Sun.COM }
9707697SMichael.Christensen@Sun.COM }
9717697SMichael.Christensen@Sun.COM return (ENXIO);
9727697SMichael.Christensen@Sun.COM }
9737697SMichael.Christensen@Sun.COM
9747697SMichael.Christensen@Sun.COM /*
9757697SMichael.Christensen@Sun.COM * Unregister all handles related to device open instance.
9767697SMichael.Christensen@Sun.COM */
9777697SMichael.Christensen@Sun.COM void
ds_unreg_all(int instance)9787697SMichael.Christensen@Sun.COM ds_unreg_all(int instance)
9797697SMichael.Christensen@Sun.COM {
9807697SMichael.Christensen@Sun.COM int idx;
9817697SMichael.Christensen@Sun.COM ds_svc_t *svc;
9827697SMichael.Christensen@Sun.COM ds_svc_hdl_t hdl;
9837697SMichael.Christensen@Sun.COM
9847697SMichael.Christensen@Sun.COM DS_DBG_USR(CE_NOTE, "%s: entered", __func__);
9857697SMichael.Christensen@Sun.COM
9867697SMichael.Christensen@Sun.COM /* walk every table entry */
9877697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock);
9887697SMichael.Christensen@Sun.COM for (idx = 0; idx < ds_svcs.maxsvcs; idx++) {
9897697SMichael.Christensen@Sun.COM svc = ds_svcs.tbl[idx];
9907697SMichael.Christensen@Sun.COM if (DS_SVC_ISFREE(svc))
9917697SMichael.Christensen@Sun.COM continue;
9927697SMichael.Christensen@Sun.COM if ((svc->flags & DSSF_ISUSER) != 0 && svc->drvi == instance) {
9937697SMichael.Christensen@Sun.COM hdl = svc->hdl;
9947697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
9957697SMichael.Christensen@Sun.COM (void) ds_unreg_hdl(hdl);
9967697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock);
9977697SMichael.Christensen@Sun.COM DS_DBG_USR(CE_NOTE, "%s: ds_unreg_hdl(0x%llx):",
9987697SMichael.Christensen@Sun.COM __func__, (u_longlong_t)hdl);
9997697SMichael.Christensen@Sun.COM }
10007697SMichael.Christensen@Sun.COM }
10017697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
10027697SMichael.Christensen@Sun.COM }
10037697SMichael.Christensen@Sun.COM
10047697SMichael.Christensen@Sun.COM /*
10057697SMichael.Christensen@Sun.COM * Special callbacks to allow the lds module revision-independent access
10067697SMichael.Christensen@Sun.COM * to service structure data in the callback routines. This assumes that
10077697SMichael.Christensen@Sun.COM * we put a special "cookie" in the arg argument passed to those
10087697SMichael.Christensen@Sun.COM * routines (for now, a ptr to the svc structure, but it could be a svc
10097697SMichael.Christensen@Sun.COM * table index or something that we could get back to the svc table entry).
10107697SMichael.Christensen@Sun.COM */
10117697SMichael.Christensen@Sun.COM void
ds_cbarg_get_hdl(ds_cb_arg_t arg,ds_svc_hdl_t * hdlp)10127697SMichael.Christensen@Sun.COM ds_cbarg_get_hdl(ds_cb_arg_t arg, ds_svc_hdl_t *hdlp)
10137697SMichael.Christensen@Sun.COM {
10147697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg;
10157697SMichael.Christensen@Sun.COM
10167697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
10177697SMichael.Christensen@Sun.COM *hdlp = svc->hdl;
10187697SMichael.Christensen@Sun.COM }
10197697SMichael.Christensen@Sun.COM
10207697SMichael.Christensen@Sun.COM void
ds_cbarg_get_flags(ds_cb_arg_t arg,uint32_t * flagsp)10217697SMichael.Christensen@Sun.COM ds_cbarg_get_flags(ds_cb_arg_t arg, uint32_t *flagsp)
10227697SMichael.Christensen@Sun.COM {
10237697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg;
10247697SMichael.Christensen@Sun.COM
10257697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
10267697SMichael.Christensen@Sun.COM *flagsp = svc->flags;
10277697SMichael.Christensen@Sun.COM }
10287697SMichael.Christensen@Sun.COM
10297697SMichael.Christensen@Sun.COM void
ds_cbarg_get_drv_info(ds_cb_arg_t arg,int * drvip)10307697SMichael.Christensen@Sun.COM ds_cbarg_get_drv_info(ds_cb_arg_t arg, int *drvip)
10317697SMichael.Christensen@Sun.COM {
10327697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg;
10337697SMichael.Christensen@Sun.COM
10347697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
10357697SMichael.Christensen@Sun.COM *drvip = svc->drvi;
10367697SMichael.Christensen@Sun.COM }
10377697SMichael.Christensen@Sun.COM
10387697SMichael.Christensen@Sun.COM void
ds_cbarg_get_drv_per_svc_ptr(ds_cb_arg_t arg,void ** dpspp)10397697SMichael.Christensen@Sun.COM ds_cbarg_get_drv_per_svc_ptr(ds_cb_arg_t arg, void **dpspp)
10407697SMichael.Christensen@Sun.COM {
10417697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg;
10427697SMichael.Christensen@Sun.COM
10437697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
10447697SMichael.Christensen@Sun.COM *dpspp = svc->drv_psp;
10457697SMichael.Christensen@Sun.COM }
10467697SMichael.Christensen@Sun.COM
10477697SMichael.Christensen@Sun.COM void
ds_cbarg_get_domain(ds_cb_arg_t arg,ds_domain_hdl_t * dhdlp)10487697SMichael.Christensen@Sun.COM ds_cbarg_get_domain(ds_cb_arg_t arg, ds_domain_hdl_t *dhdlp)
10497697SMichael.Christensen@Sun.COM {
10507697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg;
10517697SMichael.Christensen@Sun.COM
10527697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
10537697SMichael.Christensen@Sun.COM if (svc->port == NULL)
10547697SMichael.Christensen@Sun.COM *dhdlp = ds_my_domain_hdl;
10557697SMichael.Christensen@Sun.COM else
10567697SMichael.Christensen@Sun.COM *dhdlp = svc->port->domain_hdl;
10577697SMichael.Christensen@Sun.COM }
10587697SMichael.Christensen@Sun.COM
10597697SMichael.Christensen@Sun.COM void
ds_cbarg_get_service_id(ds_cb_arg_t arg,char ** servicep)10607697SMichael.Christensen@Sun.COM ds_cbarg_get_service_id(ds_cb_arg_t arg, char **servicep)
10617697SMichael.Christensen@Sun.COM {
10627697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg;
10637697SMichael.Christensen@Sun.COM
10647697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
10657697SMichael.Christensen@Sun.COM *servicep = svc->cap.svc_id;
10667697SMichael.Christensen@Sun.COM }
10677697SMichael.Christensen@Sun.COM
10687697SMichael.Christensen@Sun.COM void
ds_cbarg_set_drv_per_svc_ptr(ds_cb_arg_t arg,void * dpsp)10697697SMichael.Christensen@Sun.COM ds_cbarg_set_drv_per_svc_ptr(ds_cb_arg_t arg, void *dpsp)
10707697SMichael.Christensen@Sun.COM {
10717697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg;
10727697SMichael.Christensen@Sun.COM
10737697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
10747697SMichael.Christensen@Sun.COM svc->drv_psp = dpsp;
10757697SMichael.Christensen@Sun.COM }
10767697SMichael.Christensen@Sun.COM
10777697SMichael.Christensen@Sun.COM void
ds_cbarg_set_cookie(ds_svc_t * svc)10787697SMichael.Christensen@Sun.COM ds_cbarg_set_cookie(ds_svc_t *svc)
10797697SMichael.Christensen@Sun.COM {
10807697SMichael.Christensen@Sun.COM svc->ops.cb_arg = (ds_cb_arg_t)(svc);
10817697SMichael.Christensen@Sun.COM }
10827697SMichael.Christensen@Sun.COM
10837697SMichael.Christensen@Sun.COM int
ds_hdl_get_cbarg(ds_svc_hdl_t hdl,ds_cb_arg_t * cbargp)10847697SMichael.Christensen@Sun.COM ds_hdl_get_cbarg(ds_svc_hdl_t hdl, ds_cb_arg_t *cbargp)
10857697SMichael.Christensen@Sun.COM {
10867697SMichael.Christensen@Sun.COM ds_svc_t *svc;
10877697SMichael.Christensen@Sun.COM
10887697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock);
10897697SMichael.Christensen@Sun.COM if ((svc = ds_get_svc(hdl)) != NULL &&
10907697SMichael.Christensen@Sun.COM (svc->flags & DSSF_ISUSER) != 0) {
10917697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
10927697SMichael.Christensen@Sun.COM *cbargp = svc->ops.cb_arg;
10937697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
10947697SMichael.Christensen@Sun.COM return (0);
10957697SMichael.Christensen@Sun.COM }
10967697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
10977697SMichael.Christensen@Sun.COM return (ENXIO);
10987697SMichael.Christensen@Sun.COM }
10997697SMichael.Christensen@Sun.COM
11007697SMichael.Christensen@Sun.COM int
ds_is_my_hdl(ds_svc_hdl_t hdl,int instance)11017697SMichael.Christensen@Sun.COM ds_is_my_hdl(ds_svc_hdl_t hdl, int instance)
11027697SMichael.Christensen@Sun.COM {
11037697SMichael.Christensen@Sun.COM ds_svc_t *svc;
11047697SMichael.Christensen@Sun.COM int rv = 0;
11057697SMichael.Christensen@Sun.COM
11067697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock);
11077697SMichael.Christensen@Sun.COM if ((svc = ds_get_svc(hdl)) == NULL) {
11087697SMichael.Christensen@Sun.COM DS_DBG_USR(CE_NOTE, "%s: invalid hdl: 0x%llx\n", __func__,
11097697SMichael.Christensen@Sun.COM (u_longlong_t)hdl);
11107697SMichael.Christensen@Sun.COM rv = ENXIO;
11117697SMichael.Christensen@Sun.COM } else if (instance == DS_INVALID_INSTANCE) {
11127697SMichael.Christensen@Sun.COM if ((svc->flags & DSSF_ISUSER) != 0) {
11137697SMichael.Christensen@Sun.COM DS_DBG_USR(CE_NOTE, "%s: unowned hdl: 0x%llx\n",
11147697SMichael.Christensen@Sun.COM __func__, (u_longlong_t)hdl);
11157697SMichael.Christensen@Sun.COM rv = EACCES;
11167697SMichael.Christensen@Sun.COM }
11177697SMichael.Christensen@Sun.COM } else if ((svc->flags & DSSF_ISUSER) == 0 || svc->drvi != instance) {
11187697SMichael.Christensen@Sun.COM DS_DBG_USR(CE_NOTE, "%s: unowned hdl: 0x%llx\n", __func__,
11197697SMichael.Christensen@Sun.COM (u_longlong_t)hdl);
11207697SMichael.Christensen@Sun.COM rv = EACCES;
11217697SMichael.Christensen@Sun.COM }
11227697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock);
11237697SMichael.Christensen@Sun.COM return (rv);
11247697SMichael.Christensen@Sun.COM }
1125