1*7697SMichael.Christensen@Sun.COM /* 2*7697SMichael.Christensen@Sun.COM * CDDL HEADER START 3*7697SMichael.Christensen@Sun.COM * 4*7697SMichael.Christensen@Sun.COM * The contents of this file are subject to the terms of the 5*7697SMichael.Christensen@Sun.COM * Common Development and Distribution License (the "License"). 6*7697SMichael.Christensen@Sun.COM * You may not use this file except in compliance with the License. 7*7697SMichael.Christensen@Sun.COM * 8*7697SMichael.Christensen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*7697SMichael.Christensen@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*7697SMichael.Christensen@Sun.COM * See the License for the specific language governing permissions 11*7697SMichael.Christensen@Sun.COM * and limitations under the License. 12*7697SMichael.Christensen@Sun.COM * 13*7697SMichael.Christensen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*7697SMichael.Christensen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*7697SMichael.Christensen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*7697SMichael.Christensen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*7697SMichael.Christensen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*7697SMichael.Christensen@Sun.COM * 19*7697SMichael.Christensen@Sun.COM * CDDL HEADER END 20*7697SMichael.Christensen@Sun.COM */ 21*7697SMichael.Christensen@Sun.COM 22*7697SMichael.Christensen@Sun.COM /* 23*7697SMichael.Christensen@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*7697SMichael.Christensen@Sun.COM * Use is subject to license terms. 25*7697SMichael.Christensen@Sun.COM */ 26*7697SMichael.Christensen@Sun.COM 27*7697SMichael.Christensen@Sun.COM 28*7697SMichael.Christensen@Sun.COM /* 29*7697SMichael.Christensen@Sun.COM * Domain Services Module System Specific Code. 30*7697SMichael.Christensen@Sun.COM * 31*7697SMichael.Christensen@Sun.COM * The Domain Services (DS) module is responsible for communication 32*7697SMichael.Christensen@Sun.COM * with external service entities. It provides a kernel API for clients to 33*7697SMichael.Christensen@Sun.COM * publish capabilities and handles the low level communication and 34*7697SMichael.Christensen@Sun.COM * version negotiation required to export those capabilities to any 35*7697SMichael.Christensen@Sun.COM * interested service entity. Once a capability has been successfully 36*7697SMichael.Christensen@Sun.COM * registered with a service entity, the DS module facilitates all 37*7697SMichael.Christensen@Sun.COM * data transfers between the service entity and the client providing 38*7697SMichael.Christensen@Sun.COM * that particular capability. 39*7697SMichael.Christensen@Sun.COM * 40*7697SMichael.Christensen@Sun.COM * This file provides the system interfaces that are required for 41*7697SMichael.Christensen@Sun.COM * the ds.c module, which is common to both Solaris and VBSC (linux). 42*7697SMichael.Christensen@Sun.COM */ 43*7697SMichael.Christensen@Sun.COM 44*7697SMichael.Christensen@Sun.COM #include <sys/modctl.h> 45*7697SMichael.Christensen@Sun.COM #include <sys/ksynch.h> 46*7697SMichael.Christensen@Sun.COM #include <sys/taskq.h> 47*7697SMichael.Christensen@Sun.COM #include <sys/disp.h> 48*7697SMichael.Christensen@Sun.COM #include <sys/cmn_err.h> 49*7697SMichael.Christensen@Sun.COM #include <sys/note.h> 50*7697SMichael.Christensen@Sun.COM #include <sys/mach_descrip.h> 51*7697SMichael.Christensen@Sun.COM #include <sys/mdesc.h> 52*7697SMichael.Christensen@Sun.COM #include <sys/mdeg.h> 53*7697SMichael.Christensen@Sun.COM #include <sys/ldc.h> 54*7697SMichael.Christensen@Sun.COM #include <sys/ds.h> 55*7697SMichael.Christensen@Sun.COM #include <sys/ds_impl.h> 56*7697SMichael.Christensen@Sun.COM 57*7697SMichael.Christensen@Sun.COM /* 58*7697SMichael.Christensen@Sun.COM * All DS ports in the system 59*7697SMichael.Christensen@Sun.COM * 60*7697SMichael.Christensen@Sun.COM * The list of DS ports is read in from the MD when the DS module is 61*7697SMichael.Christensen@Sun.COM * initialized and is never modified. This eliminates the need for 62*7697SMichael.Christensen@Sun.COM * locking to access the port array itself. Access to the individual 63*7697SMichael.Christensen@Sun.COM * ports are synchronized at the port level. 64*7697SMichael.Christensen@Sun.COM */ 65*7697SMichael.Christensen@Sun.COM ds_port_t ds_ports[DS_MAX_PORTS]; 66*7697SMichael.Christensen@Sun.COM ds_portset_t ds_allports; /* all DS ports in the system */ 67*7697SMichael.Christensen@Sun.COM 68*7697SMichael.Christensen@Sun.COM /* 69*7697SMichael.Christensen@Sun.COM * Table of registered services 70*7697SMichael.Christensen@Sun.COM * 71*7697SMichael.Christensen@Sun.COM * Locking: Accesses to the table of services are synchronized using 72*7697SMichael.Christensen@Sun.COM * a mutex lock. The reader lock must be held when looking up service 73*7697SMichael.Christensen@Sun.COM * information in the table. The writer lock must be held when any 74*7697SMichael.Christensen@Sun.COM * service information is being modified. 75*7697SMichael.Christensen@Sun.COM */ 76*7697SMichael.Christensen@Sun.COM ds_svcs_t ds_svcs; 77*7697SMichael.Christensen@Sun.COM 78*7697SMichael.Christensen@Sun.COM /* 79*7697SMichael.Christensen@Sun.COM * Taskq for internal task processing 80*7697SMichael.Christensen@Sun.COM */ 81*7697SMichael.Christensen@Sun.COM static taskq_t *ds_taskq; 82*7697SMichael.Christensen@Sun.COM 83*7697SMichael.Christensen@Sun.COM /* 84*7697SMichael.Christensen@Sun.COM * The actual required number of parallel threads is not expected 85*7697SMichael.Christensen@Sun.COM * to be very large. Use the maximum number of CPUs in the system 86*7697SMichael.Christensen@Sun.COM * as a rough upper bound. 87*7697SMichael.Christensen@Sun.COM */ 88*7697SMichael.Christensen@Sun.COM #define DS_MAX_TASKQ_THR NCPU 89*7697SMichael.Christensen@Sun.COM #define DS_DISPATCH(fn, arg) taskq_dispatch(ds_taskq, fn, arg, TQ_SLEEP) 90*7697SMichael.Christensen@Sun.COM 91*7697SMichael.Christensen@Sun.COM ds_domain_hdl_t ds_my_domain_hdl = NULL; 92*7697SMichael.Christensen@Sun.COM 93*7697SMichael.Christensen@Sun.COM #ifdef DEBUG 94*7697SMichael.Christensen@Sun.COM /* 95*7697SMichael.Christensen@Sun.COM * Debug Flag 96*7697SMichael.Christensen@Sun.COM */ 97*7697SMichael.Christensen@Sun.COM uint_t ds_debug = 0; 98*7697SMichael.Christensen@Sun.COM #endif /* DEBUG */ 99*7697SMichael.Christensen@Sun.COM 100*7697SMichael.Christensen@Sun.COM /* initialization functions */ 101*7697SMichael.Christensen@Sun.COM static void ds_init(void); 102*7697SMichael.Christensen@Sun.COM static void ds_fini(void); 103*7697SMichael.Christensen@Sun.COM static int ds_ports_init(void); 104*7697SMichael.Christensen@Sun.COM static int ds_ports_fini(void); 105*7697SMichael.Christensen@Sun.COM 106*7697SMichael.Christensen@Sun.COM /* port utilities */ 107*7697SMichael.Christensen@Sun.COM static int ds_port_add(md_t *mdp, mde_cookie_t port, mde_cookie_t chan); 108*7697SMichael.Christensen@Sun.COM 109*7697SMichael.Christensen@Sun.COM /* log functions */ 110*7697SMichael.Christensen@Sun.COM static void ds_log_init(void); 111*7697SMichael.Christensen@Sun.COM static void ds_log_fini(void); 112*7697SMichael.Christensen@Sun.COM static int ds_log_remove(void); 113*7697SMichael.Christensen@Sun.COM static void ds_log_purge(void *arg); 114*7697SMichael.Christensen@Sun.COM 115*7697SMichael.Christensen@Sun.COM static struct modlmisc modlmisc = { 116*7697SMichael.Christensen@Sun.COM &mod_miscops, 117*7697SMichael.Christensen@Sun.COM "Domain Services 1.9" 118*7697SMichael.Christensen@Sun.COM }; 119*7697SMichael.Christensen@Sun.COM 120*7697SMichael.Christensen@Sun.COM static struct modlinkage modlinkage = { 121*7697SMichael.Christensen@Sun.COM MODREV_1, 122*7697SMichael.Christensen@Sun.COM (void *)&modlmisc, 123*7697SMichael.Christensen@Sun.COM NULL 124*7697SMichael.Christensen@Sun.COM }; 125*7697SMichael.Christensen@Sun.COM 126*7697SMichael.Christensen@Sun.COM int 127*7697SMichael.Christensen@Sun.COM _init(void) 128*7697SMichael.Christensen@Sun.COM { 129*7697SMichael.Christensen@Sun.COM int rv; 130*7697SMichael.Christensen@Sun.COM 131*7697SMichael.Christensen@Sun.COM /* 132*7697SMichael.Christensen@Sun.COM * Perform all internal setup before initializing 133*7697SMichael.Christensen@Sun.COM * the DS ports. This ensures that events can be 134*7697SMichael.Christensen@Sun.COM * processed as soon as the port comes up. 135*7697SMichael.Christensen@Sun.COM */ 136*7697SMichael.Christensen@Sun.COM ds_init(); 137*7697SMichael.Christensen@Sun.COM 138*7697SMichael.Christensen@Sun.COM /* force attach channel nexus */ 139*7697SMichael.Christensen@Sun.COM (void) i_ddi_attach_hw_nodes("cnex"); 140*7697SMichael.Christensen@Sun.COM 141*7697SMichael.Christensen@Sun.COM if ((rv = ds_ports_init()) != 0) { 142*7697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "Domain Services initialization failed"); 143*7697SMichael.Christensen@Sun.COM ds_fini(); 144*7697SMichael.Christensen@Sun.COM return (rv); 145*7697SMichael.Christensen@Sun.COM } 146*7697SMichael.Christensen@Sun.COM 147*7697SMichael.Christensen@Sun.COM if ((rv = mod_install(&modlinkage)) != 0) { 148*7697SMichael.Christensen@Sun.COM (void) ds_ports_fini(); 149*7697SMichael.Christensen@Sun.COM ds_fini(); 150*7697SMichael.Christensen@Sun.COM } 151*7697SMichael.Christensen@Sun.COM 152*7697SMichael.Christensen@Sun.COM return (rv); 153*7697SMichael.Christensen@Sun.COM } 154*7697SMichael.Christensen@Sun.COM 155*7697SMichael.Christensen@Sun.COM int 156*7697SMichael.Christensen@Sun.COM _info(struct modinfo *modinfop) 157*7697SMichael.Christensen@Sun.COM { 158*7697SMichael.Christensen@Sun.COM return (mod_info(&modlinkage, modinfop)); 159*7697SMichael.Christensen@Sun.COM } 160*7697SMichael.Christensen@Sun.COM 161*7697SMichael.Christensen@Sun.COM int 162*7697SMichael.Christensen@Sun.COM _fini(void) 163*7697SMichael.Christensen@Sun.COM { 164*7697SMichael.Christensen@Sun.COM int rv; 165*7697SMichael.Christensen@Sun.COM 166*7697SMichael.Christensen@Sun.COM if ((rv = mod_remove(&modlinkage)) == 0) { 167*7697SMichael.Christensen@Sun.COM (void) ds_ports_fini(); 168*7697SMichael.Christensen@Sun.COM ds_fini(); 169*7697SMichael.Christensen@Sun.COM } 170*7697SMichael.Christensen@Sun.COM 171*7697SMichael.Christensen@Sun.COM return (rv); 172*7697SMichael.Christensen@Sun.COM } 173*7697SMichael.Christensen@Sun.COM 174*7697SMichael.Christensen@Sun.COM static void 175*7697SMichael.Christensen@Sun.COM ds_fini(void) 176*7697SMichael.Christensen@Sun.COM { 177*7697SMichael.Christensen@Sun.COM /* 178*7697SMichael.Christensen@Sun.COM * Flip the enabled switch to make sure that no 179*7697SMichael.Christensen@Sun.COM * incoming events get dispatched while things 180*7697SMichael.Christensen@Sun.COM * are being torn down. 181*7697SMichael.Christensen@Sun.COM */ 182*7697SMichael.Christensen@Sun.COM ds_enabled = B_FALSE; 183*7697SMichael.Christensen@Sun.COM 184*7697SMichael.Christensen@Sun.COM /* 185*7697SMichael.Christensen@Sun.COM * Destroy the taskq. 186*7697SMichael.Christensen@Sun.COM */ 187*7697SMichael.Christensen@Sun.COM taskq_destroy(ds_taskq); 188*7697SMichael.Christensen@Sun.COM 189*7697SMichael.Christensen@Sun.COM /* 190*7697SMichael.Christensen@Sun.COM * Destroy the message log. 191*7697SMichael.Christensen@Sun.COM */ 192*7697SMichael.Christensen@Sun.COM ds_log_fini(); 193*7697SMichael.Christensen@Sun.COM 194*7697SMichael.Christensen@Sun.COM /* 195*7697SMichael.Christensen@Sun.COM * Deallocate the table of registered services 196*7697SMichael.Christensen@Sun.COM */ 197*7697SMichael.Christensen@Sun.COM 198*7697SMichael.Christensen@Sun.COM /* clear out all entries */ 199*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock); 200*7697SMichael.Christensen@Sun.COM (void) ds_walk_svcs(ds_svc_free, NULL); 201*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 202*7697SMichael.Christensen@Sun.COM 203*7697SMichael.Christensen@Sun.COM /* destroy the table itself */ 204*7697SMichael.Christensen@Sun.COM DS_FREE(ds_svcs.tbl, ds_svcs.maxsvcs * sizeof (ds_svc_t *)); 205*7697SMichael.Christensen@Sun.COM mutex_destroy(&ds_svcs.lock); 206*7697SMichael.Christensen@Sun.COM bzero(&ds_svcs, sizeof (ds_svcs)); 207*7697SMichael.Christensen@Sun.COM } 208*7697SMichael.Christensen@Sun.COM 209*7697SMichael.Christensen@Sun.COM /* 210*7697SMichael.Christensen@Sun.COM * Initialize the list of ports based on the MD. 211*7697SMichael.Christensen@Sun.COM */ 212*7697SMichael.Christensen@Sun.COM static int 213*7697SMichael.Christensen@Sun.COM ds_ports_init(void) 214*7697SMichael.Christensen@Sun.COM { 215*7697SMichael.Christensen@Sun.COM int idx; 216*7697SMichael.Christensen@Sun.COM int rv = 0; 217*7697SMichael.Christensen@Sun.COM md_t *mdp; 218*7697SMichael.Christensen@Sun.COM int num_nodes; 219*7697SMichael.Christensen@Sun.COM int listsz; 220*7697SMichael.Christensen@Sun.COM mde_cookie_t rootnode; 221*7697SMichael.Christensen@Sun.COM mde_cookie_t dsnode; 222*7697SMichael.Christensen@Sun.COM mde_cookie_t *portp = NULL; 223*7697SMichael.Christensen@Sun.COM mde_cookie_t *chanp = NULL; 224*7697SMichael.Christensen@Sun.COM int nport; 225*7697SMichael.Christensen@Sun.COM int nchan; 226*7697SMichael.Christensen@Sun.COM 227*7697SMichael.Christensen@Sun.COM if ((mdp = md_get_handle()) == NULL) { 228*7697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "Unable to initialize machine description"); 229*7697SMichael.Christensen@Sun.COM return (-1); 230*7697SMichael.Christensen@Sun.COM } 231*7697SMichael.Christensen@Sun.COM 232*7697SMichael.Christensen@Sun.COM num_nodes = md_node_count(mdp); 233*7697SMichael.Christensen@Sun.COM ASSERT(num_nodes > 0); 234*7697SMichael.Christensen@Sun.COM 235*7697SMichael.Christensen@Sun.COM listsz = num_nodes * sizeof (mde_cookie_t); 236*7697SMichael.Christensen@Sun.COM 237*7697SMichael.Christensen@Sun.COM /* allocate temporary storage for MD scans */ 238*7697SMichael.Christensen@Sun.COM portp = kmem_zalloc(listsz, KM_SLEEP); 239*7697SMichael.Christensen@Sun.COM chanp = kmem_zalloc(listsz, KM_SLEEP); 240*7697SMichael.Christensen@Sun.COM 241*7697SMichael.Christensen@Sun.COM rootnode = md_root_node(mdp); 242*7697SMichael.Christensen@Sun.COM ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE); 243*7697SMichael.Christensen@Sun.COM 244*7697SMichael.Christensen@Sun.COM /* 245*7697SMichael.Christensen@Sun.COM * The root of the search for DS port nodes is the 246*7697SMichael.Christensen@Sun.COM * DS node. Perform a scan to find that node. 247*7697SMichael.Christensen@Sun.COM */ 248*7697SMichael.Christensen@Sun.COM nport = md_scan_dag(mdp, rootnode, md_find_name(mdp, DS_MD_ROOT_NAME), 249*7697SMichael.Christensen@Sun.COM md_find_name(mdp, "fwd"), portp); 250*7697SMichael.Christensen@Sun.COM 251*7697SMichael.Christensen@Sun.COM if (nport <= 0) { 252*7697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "No '%s' node in MD", DS_MD_ROOT_NAME); 253*7697SMichael.Christensen@Sun.COM goto done; 254*7697SMichael.Christensen@Sun.COM } 255*7697SMichael.Christensen@Sun.COM 256*7697SMichael.Christensen@Sun.COM /* expecting only one DS node */ 257*7697SMichael.Christensen@Sun.COM if (nport != 1) { 258*7697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "Expected one '%s' node in the MD, found %d", 259*7697SMichael.Christensen@Sun.COM DS_MD_ROOT_NAME, nport); 260*7697SMichael.Christensen@Sun.COM } 261*7697SMichael.Christensen@Sun.COM 262*7697SMichael.Christensen@Sun.COM dsnode = portp[0]; 263*7697SMichael.Christensen@Sun.COM 264*7697SMichael.Christensen@Sun.COM /* find all the DS ports in the MD */ 265*7697SMichael.Christensen@Sun.COM nport = md_scan_dag(mdp, dsnode, md_find_name(mdp, DS_MD_PORT_NAME), 266*7697SMichael.Christensen@Sun.COM md_find_name(mdp, "fwd"), portp); 267*7697SMichael.Christensen@Sun.COM 268*7697SMichael.Christensen@Sun.COM if (nport <= 0) { 269*7697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "No '%s' nodes in MD", DS_MD_PORT_NAME); 270*7697SMichael.Christensen@Sun.COM goto done; 271*7697SMichael.Christensen@Sun.COM } 272*7697SMichael.Christensen@Sun.COM 273*7697SMichael.Christensen@Sun.COM /* 274*7697SMichael.Christensen@Sun.COM * Initialize all the ports found in the MD. 275*7697SMichael.Christensen@Sun.COM */ 276*7697SMichael.Christensen@Sun.COM for (idx = 0; idx < nport; idx++) { 277*7697SMichael.Christensen@Sun.COM 278*7697SMichael.Christensen@Sun.COM /* get the channels for this port */ 279*7697SMichael.Christensen@Sun.COM nchan = md_scan_dag(mdp, portp[idx], 280*7697SMichael.Christensen@Sun.COM md_find_name(mdp, DS_MD_CHAN_NAME), 281*7697SMichael.Christensen@Sun.COM md_find_name(mdp, "fwd"), chanp); 282*7697SMichael.Christensen@Sun.COM 283*7697SMichael.Christensen@Sun.COM if (nchan <= 0) { 284*7697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "No '%s' node for DS port", 285*7697SMichael.Christensen@Sun.COM DS_MD_CHAN_NAME); 286*7697SMichael.Christensen@Sun.COM rv = -1; 287*7697SMichael.Christensen@Sun.COM goto done; 288*7697SMichael.Christensen@Sun.COM } 289*7697SMichael.Christensen@Sun.COM 290*7697SMichael.Christensen@Sun.COM /* expecting only one channel */ 291*7697SMichael.Christensen@Sun.COM if (nchan != 1) { 292*7697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "Expected one '%s' node for DS " 293*7697SMichael.Christensen@Sun.COM " port, found %d", DS_MD_CHAN_NAME, nchan); 294*7697SMichael.Christensen@Sun.COM } 295*7697SMichael.Christensen@Sun.COM 296*7697SMichael.Christensen@Sun.COM if (ds_port_add(mdp, portp[idx], chanp[0]) != 0) { 297*7697SMichael.Christensen@Sun.COM rv = -1; 298*7697SMichael.Christensen@Sun.COM goto done; 299*7697SMichael.Christensen@Sun.COM } 300*7697SMichael.Christensen@Sun.COM } 301*7697SMichael.Christensen@Sun.COM 302*7697SMichael.Christensen@Sun.COM done: 303*7697SMichael.Christensen@Sun.COM if (rv != 0) 304*7697SMichael.Christensen@Sun.COM (void) ds_ports_fini(); 305*7697SMichael.Christensen@Sun.COM 306*7697SMichael.Christensen@Sun.COM DS_FREE(portp, listsz); 307*7697SMichael.Christensen@Sun.COM DS_FREE(chanp, listsz); 308*7697SMichael.Christensen@Sun.COM 309*7697SMichael.Christensen@Sun.COM (void) md_fini_handle(mdp); 310*7697SMichael.Christensen@Sun.COM 311*7697SMichael.Christensen@Sun.COM return (rv); 312*7697SMichael.Christensen@Sun.COM } 313*7697SMichael.Christensen@Sun.COM 314*7697SMichael.Christensen@Sun.COM static int 315*7697SMichael.Christensen@Sun.COM ds_ports_fini(void) 316*7697SMichael.Christensen@Sun.COM { 317*7697SMichael.Christensen@Sun.COM int idx; 318*7697SMichael.Christensen@Sun.COM 319*7697SMichael.Christensen@Sun.COM /* 320*7697SMichael.Christensen@Sun.COM * Tear down each initialized port. 321*7697SMichael.Christensen@Sun.COM */ 322*7697SMichael.Christensen@Sun.COM for (idx = 0; idx < DS_MAX_PORTS; idx++) { 323*7697SMichael.Christensen@Sun.COM if (DS_PORT_IN_SET(ds_allports, idx)) { 324*7697SMichael.Christensen@Sun.COM (void) ds_remove_port(idx, 1); 325*7697SMichael.Christensen@Sun.COM } 326*7697SMichael.Christensen@Sun.COM } 327*7697SMichael.Christensen@Sun.COM 328*7697SMichael.Christensen@Sun.COM return (0); 329*7697SMichael.Christensen@Sun.COM } 330*7697SMichael.Christensen@Sun.COM 331*7697SMichael.Christensen@Sun.COM static int 332*7697SMichael.Christensen@Sun.COM ds_port_add(md_t *mdp, mde_cookie_t port, mde_cookie_t chan) 333*7697SMichael.Christensen@Sun.COM { 334*7697SMichael.Christensen@Sun.COM uint64_t port_id; 335*7697SMichael.Christensen@Sun.COM uint64_t ldc_id; 336*7697SMichael.Christensen@Sun.COM uint64_t dhdl; 337*7697SMichael.Christensen@Sun.COM char *dom_name; 338*7697SMichael.Christensen@Sun.COM 339*7697SMichael.Christensen@Sun.COM /* get the ID for this port */ 340*7697SMichael.Christensen@Sun.COM if (md_get_prop_val(mdp, port, "id", &port_id) != 0) { 341*7697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "%s: port 'id' property not found", 342*7697SMichael.Christensen@Sun.COM __func__); 343*7697SMichael.Christensen@Sun.COM return (-1); 344*7697SMichael.Christensen@Sun.COM } 345*7697SMichael.Christensen@Sun.COM 346*7697SMichael.Christensen@Sun.COM /* sanity check the port id */ 347*7697SMichael.Christensen@Sun.COM if (port_id > DS_MAX_PORT_ID) { 348*7697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "%s: port ID %ld out of range", 349*7697SMichael.Christensen@Sun.COM __func__, port_id); 350*7697SMichael.Christensen@Sun.COM return (-1); 351*7697SMichael.Christensen@Sun.COM } 352*7697SMichael.Christensen@Sun.COM 353*7697SMichael.Christensen@Sun.COM /* get the channel ID for this port */ 354*7697SMichael.Christensen@Sun.COM if (md_get_prop_val(mdp, chan, "id", &ldc_id) != 0) { 355*7697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "ds@%lx: %s: no channel 'id' property", 356*7697SMichael.Christensen@Sun.COM port_id, __func__); 357*7697SMichael.Christensen@Sun.COM return (-1); 358*7697SMichael.Christensen@Sun.COM } 359*7697SMichael.Christensen@Sun.COM 360*7697SMichael.Christensen@Sun.COM /* get the remote-domain-id property if it's there */ 361*7697SMichael.Christensen@Sun.COM if (md_get_prop_val(mdp, port, "remote-domain-id", &dhdl) != 0) { 362*7697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "ds@%lx: %s: 'remote-domain-id' prop " 363*7697SMichael.Christensen@Sun.COM " not found", port_id, __func__); 364*7697SMichael.Christensen@Sun.COM dhdl = DS_DHDL_INVALID; 365*7697SMichael.Christensen@Sun.COM } 366*7697SMichael.Christensen@Sun.COM 367*7697SMichael.Christensen@Sun.COM /* get the remote-domain-name property if it's there */ 368*7697SMichael.Christensen@Sun.COM if (md_get_prop_str(mdp, port, "remote-domain-name", &dom_name) != 0) { 369*7697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "ds@%lx: %s: 'remote-domain-name' prop " 370*7697SMichael.Christensen@Sun.COM " not found", port_id, __func__); 371*7697SMichael.Christensen@Sun.COM dom_name = NULL; 372*7697SMichael.Christensen@Sun.COM } 373*7697SMichael.Christensen@Sun.COM 374*7697SMichael.Christensen@Sun.COM if (ds_add_port(port_id, ldc_id, dhdl, dom_name, 1) != 0) 375*7697SMichael.Christensen@Sun.COM return (-1); 376*7697SMichael.Christensen@Sun.COM 377*7697SMichael.Christensen@Sun.COM return (0); 378*7697SMichael.Christensen@Sun.COM } 379*7697SMichael.Christensen@Sun.COM 380*7697SMichael.Christensen@Sun.COM void 381*7697SMichael.Christensen@Sun.COM ds_init() 382*7697SMichael.Christensen@Sun.COM { 383*7697SMichael.Christensen@Sun.COM ds_common_init(); 384*7697SMichael.Christensen@Sun.COM 385*7697SMichael.Christensen@Sun.COM /* 386*7697SMichael.Christensen@Sun.COM * Create taskq for internal processing threads. This 387*7697SMichael.Christensen@Sun.COM * includes processing incoming request messages and 388*7697SMichael.Christensen@Sun.COM * sending out of band registration messages. 389*7697SMichael.Christensen@Sun.COM */ 390*7697SMichael.Christensen@Sun.COM ds_taskq = taskq_create("ds_taskq", 1, minclsyspri, 1, 391*7697SMichael.Christensen@Sun.COM DS_MAX_TASKQ_THR, TASKQ_PREPOPULATE | TASKQ_DYNAMIC); 392*7697SMichael.Christensen@Sun.COM 393*7697SMichael.Christensen@Sun.COM /* 394*7697SMichael.Christensen@Sun.COM * Initialize the message log. 395*7697SMichael.Christensen@Sun.COM */ 396*7697SMichael.Christensen@Sun.COM ds_log_init(); 397*7697SMichael.Christensen@Sun.COM } 398*7697SMichael.Christensen@Sun.COM 399*7697SMichael.Christensen@Sun.COM int 400*7697SMichael.Christensen@Sun.COM ds_sys_dispatch_func(void (func)(void *), void *arg) 401*7697SMichael.Christensen@Sun.COM { 402*7697SMichael.Christensen@Sun.COM return (DS_DISPATCH(func, arg) == NULL); 403*7697SMichael.Christensen@Sun.COM } 404*7697SMichael.Christensen@Sun.COM 405*7697SMichael.Christensen@Sun.COM /* 406*7697SMichael.Christensen@Sun.COM * Drain event queue, if necessary. 407*7697SMichael.Christensen@Sun.COM */ 408*7697SMichael.Christensen@Sun.COM void 409*7697SMichael.Christensen@Sun.COM ds_sys_drain_events(ds_port_t *port) 410*7697SMichael.Christensen@Sun.COM { 411*7697SMichael.Christensen@Sun.COM _NOTE(ARGUNUSED(port)) 412*7697SMichael.Christensen@Sun.COM } 413*7697SMichael.Christensen@Sun.COM 414*7697SMichael.Christensen@Sun.COM /* 415*7697SMichael.Christensen@Sun.COM * System specific port initalization. 416*7697SMichael.Christensen@Sun.COM */ 417*7697SMichael.Christensen@Sun.COM void 418*7697SMichael.Christensen@Sun.COM ds_sys_port_init(ds_port_t *port) 419*7697SMichael.Christensen@Sun.COM { 420*7697SMichael.Christensen@Sun.COM _NOTE(ARGUNUSED(port)) 421*7697SMichael.Christensen@Sun.COM } 422*7697SMichael.Christensen@Sun.COM 423*7697SMichael.Christensen@Sun.COM /* 424*7697SMichael.Christensen@Sun.COM * System specific port teardown. 425*7697SMichael.Christensen@Sun.COM */ 426*7697SMichael.Christensen@Sun.COM void 427*7697SMichael.Christensen@Sun.COM ds_sys_port_fini(ds_port_t *port) 428*7697SMichael.Christensen@Sun.COM { 429*7697SMichael.Christensen@Sun.COM _NOTE(ARGUNUSED(port)) 430*7697SMichael.Christensen@Sun.COM } 431*7697SMichael.Christensen@Sun.COM 432*7697SMichael.Christensen@Sun.COM /* 433*7697SMichael.Christensen@Sun.COM * System specific LDC channel initialization. 434*7697SMichael.Christensen@Sun.COM */ 435*7697SMichael.Christensen@Sun.COM void 436*7697SMichael.Christensen@Sun.COM ds_sys_ldc_init(ds_port_t *port) 437*7697SMichael.Christensen@Sun.COM { 438*7697SMichael.Christensen@Sun.COM int rv; 439*7697SMichael.Christensen@Sun.COM char ebuf[DS_EBUFSIZE]; 440*7697SMichael.Christensen@Sun.COM 441*7697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&port->lock)); 442*7697SMichael.Christensen@Sun.COM 443*7697SMichael.Christensen@Sun.COM if ((rv = ldc_open(port->ldc.hdl)) != 0) { 444*7697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "ds@%lx: %s: ldc_open: %s", 445*7697SMichael.Christensen@Sun.COM PORTID(port), __func__, ds_errno_to_str(rv, ebuf)); 446*7697SMichael.Christensen@Sun.COM return; 447*7697SMichael.Christensen@Sun.COM } 448*7697SMichael.Christensen@Sun.COM 449*7697SMichael.Christensen@Sun.COM (void) ldc_up(port->ldc.hdl); 450*7697SMichael.Christensen@Sun.COM 451*7697SMichael.Christensen@Sun.COM (void) ldc_status(port->ldc.hdl, &port->ldc.state); 452*7697SMichael.Christensen@Sun.COM 453*7697SMichael.Christensen@Sun.COM DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: initial LDC state 0x%x", 454*7697SMichael.Christensen@Sun.COM PORTID(port), __func__, port->ldc.state); 455*7697SMichael.Christensen@Sun.COM 456*7697SMichael.Christensen@Sun.COM port->state = DS_PORT_LDC_INIT; 457*7697SMichael.Christensen@Sun.COM } 458*7697SMichael.Christensen@Sun.COM 459*7697SMichael.Christensen@Sun.COM /* 460*7697SMichael.Christensen@Sun.COM * DS message log 461*7697SMichael.Christensen@Sun.COM * 462*7697SMichael.Christensen@Sun.COM * Locking: The message log is protected by a single mutex. This 463*7697SMichael.Christensen@Sun.COM * protects all fields in the log structure itself as well as 464*7697SMichael.Christensen@Sun.COM * everything in the entry structures on both the log and the 465*7697SMichael.Christensen@Sun.COM * free list. 466*7697SMichael.Christensen@Sun.COM */ 467*7697SMichael.Christensen@Sun.COM static struct log { 468*7697SMichael.Christensen@Sun.COM ds_log_entry_t *head; /* head of the log */ 469*7697SMichael.Christensen@Sun.COM ds_log_entry_t *freelist; /* head of the free list */ 470*7697SMichael.Christensen@Sun.COM size_t size; /* size of the log in bytes */ 471*7697SMichael.Christensen@Sun.COM uint32_t nentry; /* number of entries */ 472*7697SMichael.Christensen@Sun.COM kmutex_t lock; /* log lock */ 473*7697SMichael.Christensen@Sun.COM } ds_log; 474*7697SMichael.Christensen@Sun.COM 475*7697SMichael.Christensen@Sun.COM /* log soft limit */ 476*7697SMichael.Christensen@Sun.COM uint_t ds_log_sz = DS_LOG_DEFAULT_SZ; 477*7697SMichael.Christensen@Sun.COM 478*7697SMichael.Christensen@Sun.COM /* initial pool of log entry structures */ 479*7697SMichael.Christensen@Sun.COM static ds_log_entry_t ds_log_entry_pool[DS_LOG_NPOOL]; 480*7697SMichael.Christensen@Sun.COM 481*7697SMichael.Christensen@Sun.COM /* 482*7697SMichael.Christensen@Sun.COM * Logging Support 483*7697SMichael.Christensen@Sun.COM */ 484*7697SMichael.Christensen@Sun.COM static void 485*7697SMichael.Christensen@Sun.COM ds_log_init(void) 486*7697SMichael.Christensen@Sun.COM { 487*7697SMichael.Christensen@Sun.COM ds_log_entry_t *new; 488*7697SMichael.Christensen@Sun.COM 489*7697SMichael.Christensen@Sun.COM /* initialize global lock */ 490*7697SMichael.Christensen@Sun.COM mutex_init(&ds_log.lock, NULL, MUTEX_DRIVER, NULL); 491*7697SMichael.Christensen@Sun.COM 492*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_log.lock); 493*7697SMichael.Christensen@Sun.COM 494*7697SMichael.Christensen@Sun.COM /* initialize the log */ 495*7697SMichael.Christensen@Sun.COM ds_log.head = NULL; 496*7697SMichael.Christensen@Sun.COM ds_log.size = 0; 497*7697SMichael.Christensen@Sun.COM ds_log.nentry = 0; 498*7697SMichael.Christensen@Sun.COM 499*7697SMichael.Christensen@Sun.COM /* initialize the free list */ 500*7697SMichael.Christensen@Sun.COM for (new = ds_log_entry_pool; new < DS_LOG_POOL_END; new++) { 501*7697SMichael.Christensen@Sun.COM new->next = ds_log.freelist; 502*7697SMichael.Christensen@Sun.COM ds_log.freelist = new; 503*7697SMichael.Christensen@Sun.COM } 504*7697SMichael.Christensen@Sun.COM 505*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_log.lock); 506*7697SMichael.Christensen@Sun.COM 507*7697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "ds_log initialized: size=%d bytes, " 508*7697SMichael.Christensen@Sun.COM " limit=%d bytes, ninit=%ld", ds_log_sz, DS_LOG_LIMIT, 509*7697SMichael.Christensen@Sun.COM DS_LOG_NPOOL); 510*7697SMichael.Christensen@Sun.COM } 511*7697SMichael.Christensen@Sun.COM 512*7697SMichael.Christensen@Sun.COM static void 513*7697SMichael.Christensen@Sun.COM ds_log_fini(void) 514*7697SMichael.Christensen@Sun.COM { 515*7697SMichael.Christensen@Sun.COM ds_log_entry_t *next; 516*7697SMichael.Christensen@Sun.COM 517*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_log.lock); 518*7697SMichael.Christensen@Sun.COM 519*7697SMichael.Christensen@Sun.COM /* clear out the log */ 520*7697SMichael.Christensen@Sun.COM while (ds_log.nentry > 0) 521*7697SMichael.Christensen@Sun.COM (void) ds_log_remove(); 522*7697SMichael.Christensen@Sun.COM 523*7697SMichael.Christensen@Sun.COM /* 524*7697SMichael.Christensen@Sun.COM * Now all the entries are on the free list. 525*7697SMichael.Christensen@Sun.COM * Clear out the free list, deallocating any 526*7697SMichael.Christensen@Sun.COM * entry that was dynamically allocated. 527*7697SMichael.Christensen@Sun.COM */ 528*7697SMichael.Christensen@Sun.COM while (ds_log.freelist != NULL) { 529*7697SMichael.Christensen@Sun.COM next = ds_log.freelist->next; 530*7697SMichael.Christensen@Sun.COM 531*7697SMichael.Christensen@Sun.COM if (!DS_IS_POOL_ENTRY(ds_log.freelist)) { 532*7697SMichael.Christensen@Sun.COM kmem_free(ds_log.freelist, sizeof (ds_log_entry_t)); 533*7697SMichael.Christensen@Sun.COM } 534*7697SMichael.Christensen@Sun.COM 535*7697SMichael.Christensen@Sun.COM ds_log.freelist = next; 536*7697SMichael.Christensen@Sun.COM } 537*7697SMichael.Christensen@Sun.COM 538*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_log.lock); 539*7697SMichael.Christensen@Sun.COM 540*7697SMichael.Christensen@Sun.COM mutex_destroy(&ds_log.lock); 541*7697SMichael.Christensen@Sun.COM } 542*7697SMichael.Christensen@Sun.COM 543*7697SMichael.Christensen@Sun.COM static ds_log_entry_t * 544*7697SMichael.Christensen@Sun.COM ds_log_entry_alloc(void) 545*7697SMichael.Christensen@Sun.COM { 546*7697SMichael.Christensen@Sun.COM ds_log_entry_t *new = NULL; 547*7697SMichael.Christensen@Sun.COM 548*7697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&ds_log.lock)); 549*7697SMichael.Christensen@Sun.COM 550*7697SMichael.Christensen@Sun.COM if (ds_log.freelist != NULL) { 551*7697SMichael.Christensen@Sun.COM new = ds_log.freelist; 552*7697SMichael.Christensen@Sun.COM ds_log.freelist = ds_log.freelist->next; 553*7697SMichael.Christensen@Sun.COM } 554*7697SMichael.Christensen@Sun.COM 555*7697SMichael.Christensen@Sun.COM if (new == NULL) { 556*7697SMichael.Christensen@Sun.COM /* free list was empty */ 557*7697SMichael.Christensen@Sun.COM new = kmem_zalloc(sizeof (ds_log_entry_t), KM_SLEEP); 558*7697SMichael.Christensen@Sun.COM } 559*7697SMichael.Christensen@Sun.COM 560*7697SMichael.Christensen@Sun.COM ASSERT(new); 561*7697SMichael.Christensen@Sun.COM 562*7697SMichael.Christensen@Sun.COM return (new); 563*7697SMichael.Christensen@Sun.COM } 564*7697SMichael.Christensen@Sun.COM 565*7697SMichael.Christensen@Sun.COM static void 566*7697SMichael.Christensen@Sun.COM ds_log_entry_free(ds_log_entry_t *entry) 567*7697SMichael.Christensen@Sun.COM { 568*7697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&ds_log.lock)); 569*7697SMichael.Christensen@Sun.COM 570*7697SMichael.Christensen@Sun.COM if (entry == NULL) 571*7697SMichael.Christensen@Sun.COM return; 572*7697SMichael.Christensen@Sun.COM 573*7697SMichael.Christensen@Sun.COM if (entry->data != NULL) { 574*7697SMichael.Christensen@Sun.COM kmem_free(entry->data, entry->datasz); 575*7697SMichael.Christensen@Sun.COM entry->data = NULL; 576*7697SMichael.Christensen@Sun.COM } 577*7697SMichael.Christensen@Sun.COM 578*7697SMichael.Christensen@Sun.COM /* place entry on the free list */ 579*7697SMichael.Christensen@Sun.COM entry->next = ds_log.freelist; 580*7697SMichael.Christensen@Sun.COM ds_log.freelist = entry; 581*7697SMichael.Christensen@Sun.COM } 582*7697SMichael.Christensen@Sun.COM 583*7697SMichael.Christensen@Sun.COM /* 584*7697SMichael.Christensen@Sun.COM * Add a message to the end of the log 585*7697SMichael.Christensen@Sun.COM */ 586*7697SMichael.Christensen@Sun.COM static int 587*7697SMichael.Christensen@Sun.COM ds_log_add(ds_log_entry_t *new) 588*7697SMichael.Christensen@Sun.COM { 589*7697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&ds_log.lock)); 590*7697SMichael.Christensen@Sun.COM 591*7697SMichael.Christensen@Sun.COM if (ds_log.head == NULL) { 592*7697SMichael.Christensen@Sun.COM 593*7697SMichael.Christensen@Sun.COM new->prev = new; 594*7697SMichael.Christensen@Sun.COM new->next = new; 595*7697SMichael.Christensen@Sun.COM 596*7697SMichael.Christensen@Sun.COM ds_log.head = new; 597*7697SMichael.Christensen@Sun.COM } else { 598*7697SMichael.Christensen@Sun.COM ds_log_entry_t *head = ds_log.head; 599*7697SMichael.Christensen@Sun.COM ds_log_entry_t *tail = ds_log.head->prev; 600*7697SMichael.Christensen@Sun.COM 601*7697SMichael.Christensen@Sun.COM new->next = head; 602*7697SMichael.Christensen@Sun.COM new->prev = tail; 603*7697SMichael.Christensen@Sun.COM tail->next = new; 604*7697SMichael.Christensen@Sun.COM head->prev = new; 605*7697SMichael.Christensen@Sun.COM } 606*7697SMichael.Christensen@Sun.COM 607*7697SMichael.Christensen@Sun.COM /* increase the log size, including the metadata size */ 608*7697SMichael.Christensen@Sun.COM ds_log.size += DS_LOG_ENTRY_SZ(new); 609*7697SMichael.Christensen@Sun.COM ds_log.nentry++; 610*7697SMichael.Christensen@Sun.COM 611*7697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "ds_log: added %ld data bytes, %ld total bytes", 612*7697SMichael.Christensen@Sun.COM new->datasz, DS_LOG_ENTRY_SZ(new)); 613*7697SMichael.Christensen@Sun.COM 614*7697SMichael.Christensen@Sun.COM return (0); 615*7697SMichael.Christensen@Sun.COM } 616*7697SMichael.Christensen@Sun.COM 617*7697SMichael.Christensen@Sun.COM /* 618*7697SMichael.Christensen@Sun.COM * Remove an entry from the head of the log 619*7697SMichael.Christensen@Sun.COM */ 620*7697SMichael.Christensen@Sun.COM static int 621*7697SMichael.Christensen@Sun.COM ds_log_remove(void) 622*7697SMichael.Christensen@Sun.COM { 623*7697SMichael.Christensen@Sun.COM ds_log_entry_t *head; 624*7697SMichael.Christensen@Sun.COM 625*7697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&ds_log.lock)); 626*7697SMichael.Christensen@Sun.COM 627*7697SMichael.Christensen@Sun.COM head = ds_log.head; 628*7697SMichael.Christensen@Sun.COM 629*7697SMichael.Christensen@Sun.COM /* empty list */ 630*7697SMichael.Christensen@Sun.COM if (head == NULL) 631*7697SMichael.Christensen@Sun.COM return (0); 632*7697SMichael.Christensen@Sun.COM 633*7697SMichael.Christensen@Sun.COM if (head->next == ds_log.head) { 634*7697SMichael.Christensen@Sun.COM /* one element list */ 635*7697SMichael.Christensen@Sun.COM ds_log.head = NULL; 636*7697SMichael.Christensen@Sun.COM } else { 637*7697SMichael.Christensen@Sun.COM head->next->prev = head->prev; 638*7697SMichael.Christensen@Sun.COM head->prev->next = head->next; 639*7697SMichael.Christensen@Sun.COM ds_log.head = head->next; 640*7697SMichael.Christensen@Sun.COM } 641*7697SMichael.Christensen@Sun.COM 642*7697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "ds_log: removed %ld data bytes, %ld total bytes", 643*7697SMichael.Christensen@Sun.COM head->datasz, DS_LOG_ENTRY_SZ(head)); 644*7697SMichael.Christensen@Sun.COM 645*7697SMichael.Christensen@Sun.COM ds_log.size -= DS_LOG_ENTRY_SZ(head); 646*7697SMichael.Christensen@Sun.COM ds_log.nentry--; 647*7697SMichael.Christensen@Sun.COM 648*7697SMichael.Christensen@Sun.COM ds_log_entry_free(head); 649*7697SMichael.Christensen@Sun.COM 650*7697SMichael.Christensen@Sun.COM return (0); 651*7697SMichael.Christensen@Sun.COM } 652*7697SMichael.Christensen@Sun.COM 653*7697SMichael.Christensen@Sun.COM /* 654*7697SMichael.Christensen@Sun.COM * Replace the data in the entry at the front of the list with then 655*7697SMichael.Christensen@Sun.COM * new data. This has the effect of removing the oldest entry and 656*7697SMichael.Christensen@Sun.COM * adding the new entry. 657*7697SMichael.Christensen@Sun.COM */ 658*7697SMichael.Christensen@Sun.COM static int 659*7697SMichael.Christensen@Sun.COM ds_log_replace(int32_t dest, uint8_t *msg, size_t sz) 660*7697SMichael.Christensen@Sun.COM { 661*7697SMichael.Christensen@Sun.COM ds_log_entry_t *head; 662*7697SMichael.Christensen@Sun.COM 663*7697SMichael.Christensen@Sun.COM ASSERT(MUTEX_HELD(&ds_log.lock)); 664*7697SMichael.Christensen@Sun.COM 665*7697SMichael.Christensen@Sun.COM head = ds_log.head; 666*7697SMichael.Christensen@Sun.COM 667*7697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "ds_log: replaced %ld data bytes (%ld total) with " 668*7697SMichael.Christensen@Sun.COM " %ld data bytes (%ld total)", head->datasz, 669*7697SMichael.Christensen@Sun.COM DS_LOG_ENTRY_SZ(head), sz, sz + sizeof (ds_log_entry_t)); 670*7697SMichael.Christensen@Sun.COM 671*7697SMichael.Christensen@Sun.COM ds_log.size -= DS_LOG_ENTRY_SZ(head); 672*7697SMichael.Christensen@Sun.COM 673*7697SMichael.Christensen@Sun.COM kmem_free(head->data, head->datasz); 674*7697SMichael.Christensen@Sun.COM 675*7697SMichael.Christensen@Sun.COM head->data = msg; 676*7697SMichael.Christensen@Sun.COM head->datasz = sz; 677*7697SMichael.Christensen@Sun.COM head->timestamp = ddi_get_time(); 678*7697SMichael.Christensen@Sun.COM head->dest = dest; 679*7697SMichael.Christensen@Sun.COM 680*7697SMichael.Christensen@Sun.COM ds_log.size += DS_LOG_ENTRY_SZ(head); 681*7697SMichael.Christensen@Sun.COM 682*7697SMichael.Christensen@Sun.COM ds_log.head = head->next; 683*7697SMichael.Christensen@Sun.COM 684*7697SMichael.Christensen@Sun.COM return (0); 685*7697SMichael.Christensen@Sun.COM } 686*7697SMichael.Christensen@Sun.COM 687*7697SMichael.Christensen@Sun.COM static void 688*7697SMichael.Christensen@Sun.COM ds_log_purge(void *arg) 689*7697SMichael.Christensen@Sun.COM { 690*7697SMichael.Christensen@Sun.COM _NOTE(ARGUNUSED(arg)) 691*7697SMichael.Christensen@Sun.COM 692*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_log.lock); 693*7697SMichael.Christensen@Sun.COM 694*7697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "ds_log: purging oldest log entries"); 695*7697SMichael.Christensen@Sun.COM 696*7697SMichael.Christensen@Sun.COM while ((ds_log.nentry) && (ds_log.size >= ds_log_sz)) { 697*7697SMichael.Christensen@Sun.COM (void) ds_log_remove(); 698*7697SMichael.Christensen@Sun.COM } 699*7697SMichael.Christensen@Sun.COM 700*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_log.lock); 701*7697SMichael.Christensen@Sun.COM } 702*7697SMichael.Christensen@Sun.COM 703*7697SMichael.Christensen@Sun.COM int 704*7697SMichael.Christensen@Sun.COM ds_log_add_msg(int32_t dest, uint8_t *msg, size_t sz) 705*7697SMichael.Christensen@Sun.COM { 706*7697SMichael.Christensen@Sun.COM int rv = 0; 707*7697SMichael.Christensen@Sun.COM void *data; 708*7697SMichael.Christensen@Sun.COM 709*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_log.lock); 710*7697SMichael.Christensen@Sun.COM 711*7697SMichael.Christensen@Sun.COM /* allocate a local copy of the data */ 712*7697SMichael.Christensen@Sun.COM data = kmem_alloc(sz, KM_SLEEP); 713*7697SMichael.Christensen@Sun.COM bcopy(msg, data, sz); 714*7697SMichael.Christensen@Sun.COM 715*7697SMichael.Christensen@Sun.COM /* check if the log is larger than the soft limit */ 716*7697SMichael.Christensen@Sun.COM if ((ds_log.nentry) && ((ds_log.size + sz) >= ds_log_sz)) { 717*7697SMichael.Christensen@Sun.COM /* 718*7697SMichael.Christensen@Sun.COM * The log is larger than the soft limit. 719*7697SMichael.Christensen@Sun.COM * Swap the oldest entry for the newest. 720*7697SMichael.Christensen@Sun.COM */ 721*7697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "%s: replacing oldest entry with new entry", 722*7697SMichael.Christensen@Sun.COM __func__); 723*7697SMichael.Christensen@Sun.COM (void) ds_log_replace(dest, data, sz); 724*7697SMichael.Christensen@Sun.COM } else { 725*7697SMichael.Christensen@Sun.COM /* 726*7697SMichael.Christensen@Sun.COM * Still have headroom under the soft limit. 727*7697SMichael.Christensen@Sun.COM * Add the new entry to the log. 728*7697SMichael.Christensen@Sun.COM */ 729*7697SMichael.Christensen@Sun.COM ds_log_entry_t *new; 730*7697SMichael.Christensen@Sun.COM 731*7697SMichael.Christensen@Sun.COM new = ds_log_entry_alloc(); 732*7697SMichael.Christensen@Sun.COM 733*7697SMichael.Christensen@Sun.COM /* fill in message data */ 734*7697SMichael.Christensen@Sun.COM new->data = data; 735*7697SMichael.Christensen@Sun.COM new->datasz = sz; 736*7697SMichael.Christensen@Sun.COM new->timestamp = ddi_get_time(); 737*7697SMichael.Christensen@Sun.COM new->dest = dest; 738*7697SMichael.Christensen@Sun.COM 739*7697SMichael.Christensen@Sun.COM rv = ds_log_add(new); 740*7697SMichael.Christensen@Sun.COM } 741*7697SMichael.Christensen@Sun.COM 742*7697SMichael.Christensen@Sun.COM /* check if the log is larger than the hard limit */ 743*7697SMichael.Christensen@Sun.COM if ((ds_log.nentry > 1) && (ds_log.size >= DS_LOG_LIMIT)) { 744*7697SMichael.Christensen@Sun.COM /* 745*7697SMichael.Christensen@Sun.COM * Wakeup the thread to remove entries 746*7697SMichael.Christensen@Sun.COM * from the log until it is smaller than 747*7697SMichael.Christensen@Sun.COM * the soft limit. 748*7697SMichael.Christensen@Sun.COM */ 749*7697SMichael.Christensen@Sun.COM DS_DBG_LOG(CE_NOTE, "%s: log exceeded %d bytes, scheduling" 750*7697SMichael.Christensen@Sun.COM " a purge...", __func__, DS_LOG_LIMIT); 751*7697SMichael.Christensen@Sun.COM 752*7697SMichael.Christensen@Sun.COM if (DS_DISPATCH(ds_log_purge, NULL) == NULL) { 753*7697SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "%s: purge thread failed to start", 754*7697SMichael.Christensen@Sun.COM __func__); 755*7697SMichael.Christensen@Sun.COM } 756*7697SMichael.Christensen@Sun.COM } 757*7697SMichael.Christensen@Sun.COM 758*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_log.lock); 759*7697SMichael.Christensen@Sun.COM 760*7697SMichael.Christensen@Sun.COM return (rv); 761*7697SMichael.Christensen@Sun.COM } 762*7697SMichael.Christensen@Sun.COM 763*7697SMichael.Christensen@Sun.COM int 764*7697SMichael.Christensen@Sun.COM ds_add_port(uint64_t port_id, uint64_t ldc_id, ds_domain_hdl_t dhdl, 765*7697SMichael.Christensen@Sun.COM char *dom_name, int verbose) 766*7697SMichael.Christensen@Sun.COM { 767*7697SMichael.Christensen@Sun.COM ds_port_t *newport; 768*7697SMichael.Christensen@Sun.COM 769*7697SMichael.Christensen@Sun.COM /* sanity check the port id */ 770*7697SMichael.Christensen@Sun.COM if (port_id > DS_MAX_PORT_ID) { 771*7697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "%s: port ID %ld out of range", 772*7697SMichael.Christensen@Sun.COM __func__, port_id); 773*7697SMichael.Christensen@Sun.COM return (EINVAL); 774*7697SMichael.Christensen@Sun.COM } 775*7697SMichael.Christensen@Sun.COM 776*7697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "%s: adding port ds@%ld, LDC: 0x%lx, dhdl: 0x%lx", 777*7697SMichael.Christensen@Sun.COM __func__, port_id, ldc_id, dhdl); 778*7697SMichael.Christensen@Sun.COM 779*7697SMichael.Christensen@Sun.COM /* get the port structure from the array of ports */ 780*7697SMichael.Christensen@Sun.COM newport = &ds_ports[port_id]; 781*7697SMichael.Christensen@Sun.COM 782*7697SMichael.Christensen@Sun.COM /* check for a duplicate port in the MD */ 783*7697SMichael.Christensen@Sun.COM if (newport->state != DS_PORT_FREE) { 784*7697SMichael.Christensen@Sun.COM if (verbose) { 785*7697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "ds@%lx: %s: port already exists", 786*7697SMichael.Christensen@Sun.COM port_id, __func__); 787*7697SMichael.Christensen@Sun.COM } 788*7697SMichael.Christensen@Sun.COM if (newport->domain_hdl == DS_DHDL_INVALID) { 789*7697SMichael.Christensen@Sun.COM newport->domain_hdl = dhdl; 790*7697SMichael.Christensen@Sun.COM } 791*7697SMichael.Christensen@Sun.COM if (newport->domain_name == NULL && dom_name != NULL) { 792*7697SMichael.Christensen@Sun.COM newport->domain_name = ds_strdup(dom_name); 793*7697SMichael.Christensen@Sun.COM } 794*7697SMichael.Christensen@Sun.COM return (EBUSY); 795*7697SMichael.Christensen@Sun.COM } 796*7697SMichael.Christensen@Sun.COM 797*7697SMichael.Christensen@Sun.COM /* initialize the port */ 798*7697SMichael.Christensen@Sun.COM newport->id = port_id; 799*7697SMichael.Christensen@Sun.COM newport->ldc.id = ldc_id; 800*7697SMichael.Christensen@Sun.COM newport->domain_hdl = dhdl; 801*7697SMichael.Christensen@Sun.COM if (dom_name) { 802*7697SMichael.Christensen@Sun.COM newport->domain_name = ds_strdup(dom_name); 803*7697SMichael.Christensen@Sun.COM } else 804*7697SMichael.Christensen@Sun.COM newport->domain_name = NULL; 805*7697SMichael.Christensen@Sun.COM ds_port_common_init(newport); 806*7697SMichael.Christensen@Sun.COM 807*7697SMichael.Christensen@Sun.COM return (0); 808*7697SMichael.Christensen@Sun.COM } 809*7697SMichael.Christensen@Sun.COM 810*7697SMichael.Christensen@Sun.COM int 811*7697SMichael.Christensen@Sun.COM ds_remove_port(uint64_t port_id, int is_fini) 812*7697SMichael.Christensen@Sun.COM { 813*7697SMichael.Christensen@Sun.COM ds_port_t *port; 814*7697SMichael.Christensen@Sun.COM 815*7697SMichael.Christensen@Sun.COM if (port_id >= DS_MAX_PORTS || !DS_PORT_IN_SET(ds_allports, port_id)) { 816*7697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "%s: invalid port %lx", __func__, 817*7697SMichael.Christensen@Sun.COM port_id); 818*7697SMichael.Christensen@Sun.COM return (EINVAL); 819*7697SMichael.Christensen@Sun.COM } 820*7697SMichael.Christensen@Sun.COM 821*7697SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "%s: removing port ds@%lx", __func__, port_id); 822*7697SMichael.Christensen@Sun.COM 823*7697SMichael.Christensen@Sun.COM port = &ds_ports[port_id]; 824*7697SMichael.Christensen@Sun.COM 825*7697SMichael.Christensen@Sun.COM mutex_enter(&port->lock); 826*7697SMichael.Christensen@Sun.COM 827*7697SMichael.Christensen@Sun.COM if (port->state >= DS_PORT_LDC_INIT) { 828*7697SMichael.Christensen@Sun.COM /* shut down the LDC for this port */ 829*7697SMichael.Christensen@Sun.COM (void) ds_ldc_fini(port); 830*7697SMichael.Christensen@Sun.COM } 831*7697SMichael.Christensen@Sun.COM 832*7697SMichael.Christensen@Sun.COM mutex_exit(&port->lock); 833*7697SMichael.Christensen@Sun.COM 834*7697SMichael.Christensen@Sun.COM if (port->domain_name) { 835*7697SMichael.Christensen@Sun.COM DS_FREE(port->domain_name, strlen(port->domain_name) + 1); 836*7697SMichael.Christensen@Sun.COM port->domain_name = NULL; 837*7697SMichael.Christensen@Sun.COM } 838*7697SMichael.Christensen@Sun.COM port->domain_hdl = DS_DHDL_INVALID; 839*7697SMichael.Christensen@Sun.COM 840*7697SMichael.Christensen@Sun.COM /* clean up the port structure */ 841*7697SMichael.Christensen@Sun.COM ds_port_common_fini(port, is_fini); 842*7697SMichael.Christensen@Sun.COM return (0); 843*7697SMichael.Christensen@Sun.COM } 844*7697SMichael.Christensen@Sun.COM 845*7697SMichael.Christensen@Sun.COM /* 846*7697SMichael.Christensen@Sun.COM * Interface for ds_service_lookup in lds driver. 847*7697SMichael.Christensen@Sun.COM */ 848*7697SMichael.Christensen@Sun.COM int 849*7697SMichael.Christensen@Sun.COM ds_service_lookup(ds_svc_hdl_t hdl, char **servicep, uint_t *is_client) 850*7697SMichael.Christensen@Sun.COM { 851*7697SMichael.Christensen@Sun.COM ds_svc_t *svc; 852*7697SMichael.Christensen@Sun.COM 853*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock); 854*7697SMichael.Christensen@Sun.COM if ((svc = ds_get_svc(hdl)) == NULL) { 855*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 856*7697SMichael.Christensen@Sun.COM DS_DBG(CE_NOTE, "%s: handle 0x%llx not found", __func__, 857*7697SMichael.Christensen@Sun.COM (u_longlong_t)hdl); 858*7697SMichael.Christensen@Sun.COM return (ENXIO); 859*7697SMichael.Christensen@Sun.COM } 860*7697SMichael.Christensen@Sun.COM *servicep = svc->cap.svc_id; 861*7697SMichael.Christensen@Sun.COM *is_client = svc->flags & DSSF_ISCLIENT; 862*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 863*7697SMichael.Christensen@Sun.COM return (0); 864*7697SMichael.Christensen@Sun.COM } 865*7697SMichael.Christensen@Sun.COM 866*7697SMichael.Christensen@Sun.COM /* 867*7697SMichael.Christensen@Sun.COM * Interface for ds_domain_lookup in lds driver. 868*7697SMichael.Christensen@Sun.COM */ 869*7697SMichael.Christensen@Sun.COM int 870*7697SMichael.Christensen@Sun.COM ds_domain_lookup(ds_svc_hdl_t hdl, ds_domain_hdl_t *dhdlp) 871*7697SMichael.Christensen@Sun.COM { 872*7697SMichael.Christensen@Sun.COM ds_svc_t *svc; 873*7697SMichael.Christensen@Sun.COM 874*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock); 875*7697SMichael.Christensen@Sun.COM if ((svc = ds_get_svc(hdl)) == NULL) { 876*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 877*7697SMichael.Christensen@Sun.COM DS_DBG(CE_NOTE, "%s: handle 0x%llx not found", __func__, 878*7697SMichael.Christensen@Sun.COM (u_longlong_t)hdl); 879*7697SMichael.Christensen@Sun.COM return (ENXIO); 880*7697SMichael.Christensen@Sun.COM } 881*7697SMichael.Christensen@Sun.COM if (svc->port == NULL) 882*7697SMichael.Christensen@Sun.COM *dhdlp = ds_my_domain_hdl; 883*7697SMichael.Christensen@Sun.COM else 884*7697SMichael.Christensen@Sun.COM *dhdlp = svc->port->domain_hdl; 885*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 886*7697SMichael.Christensen@Sun.COM return (0); 887*7697SMichael.Christensen@Sun.COM } 888*7697SMichael.Christensen@Sun.COM 889*7697SMichael.Christensen@Sun.COM /* 890*7697SMichael.Christensen@Sun.COM * Interface for ds_hdl_isready in lds driver. 891*7697SMichael.Christensen@Sun.COM */ 892*7697SMichael.Christensen@Sun.COM int 893*7697SMichael.Christensen@Sun.COM ds_hdl_isready(ds_svc_hdl_t hdl, uint_t *is_ready) 894*7697SMichael.Christensen@Sun.COM { 895*7697SMichael.Christensen@Sun.COM ds_svc_t *svc; 896*7697SMichael.Christensen@Sun.COM 897*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock); 898*7697SMichael.Christensen@Sun.COM if ((svc = ds_get_svc(hdl)) == NULL) { 899*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 900*7697SMichael.Christensen@Sun.COM DS_DBG(CE_NOTE, "%s: handle 0x%llx not found", __func__, 901*7697SMichael.Christensen@Sun.COM (u_longlong_t)hdl); 902*7697SMichael.Christensen@Sun.COM return (ENXIO); 903*7697SMichael.Christensen@Sun.COM } 904*7697SMichael.Christensen@Sun.COM *is_ready = (svc->state == DS_SVC_ACTIVE); 905*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 906*7697SMichael.Christensen@Sun.COM return (0); 907*7697SMichael.Christensen@Sun.COM } 908*7697SMichael.Christensen@Sun.COM 909*7697SMichael.Christensen@Sun.COM /* 910*7697SMichael.Christensen@Sun.COM * Interface for ds_dom_name_to_hdl in lds driver. 911*7697SMichael.Christensen@Sun.COM */ 912*7697SMichael.Christensen@Sun.COM int 913*7697SMichael.Christensen@Sun.COM ds_dom_name_to_hdl(char *domain_name, ds_domain_hdl_t *dhdlp) 914*7697SMichael.Christensen@Sun.COM { 915*7697SMichael.Christensen@Sun.COM int i; 916*7697SMichael.Christensen@Sun.COM ds_port_t *port; 917*7697SMichael.Christensen@Sun.COM 918*7697SMichael.Christensen@Sun.COM for (i = 0, port = ds_ports; i < DS_MAX_PORTS; i++, port++) { 919*7697SMichael.Christensen@Sun.COM if (port->state != DS_PORT_FREE && 920*7697SMichael.Christensen@Sun.COM port->domain_name != NULL && 921*7697SMichael.Christensen@Sun.COM strcmp(port->domain_name, domain_name) == 0) { 922*7697SMichael.Christensen@Sun.COM *dhdlp = port->domain_hdl; 923*7697SMichael.Christensen@Sun.COM return (0); 924*7697SMichael.Christensen@Sun.COM } 925*7697SMichael.Christensen@Sun.COM } 926*7697SMichael.Christensen@Sun.COM return (ENXIO); 927*7697SMichael.Christensen@Sun.COM } 928*7697SMichael.Christensen@Sun.COM 929*7697SMichael.Christensen@Sun.COM /* 930*7697SMichael.Christensen@Sun.COM * Interface for ds_dom_hdl_to_name in lds driver. 931*7697SMichael.Christensen@Sun.COM */ 932*7697SMichael.Christensen@Sun.COM int 933*7697SMichael.Christensen@Sun.COM ds_dom_hdl_to_name(ds_domain_hdl_t dhdl, char **domain_namep) 934*7697SMichael.Christensen@Sun.COM { 935*7697SMichael.Christensen@Sun.COM int i; 936*7697SMichael.Christensen@Sun.COM ds_port_t *port; 937*7697SMichael.Christensen@Sun.COM 938*7697SMichael.Christensen@Sun.COM for (i = 0, port = ds_ports; i < DS_MAX_PORTS; i++, port++) { 939*7697SMichael.Christensen@Sun.COM if (port->state != DS_PORT_FREE && 940*7697SMichael.Christensen@Sun.COM port->domain_hdl == dhdl) { 941*7697SMichael.Christensen@Sun.COM *domain_namep = port->domain_name; 942*7697SMichael.Christensen@Sun.COM return (0); 943*7697SMichael.Christensen@Sun.COM } 944*7697SMichael.Christensen@Sun.COM } 945*7697SMichael.Christensen@Sun.COM return (ENXIO); 946*7697SMichael.Christensen@Sun.COM } 947*7697SMichael.Christensen@Sun.COM 948*7697SMichael.Christensen@Sun.COM /* 949*7697SMichael.Christensen@Sun.COM * Unregister all handles related to device open instance. 950*7697SMichael.Christensen@Sun.COM */ 951*7697SMichael.Christensen@Sun.COM void 952*7697SMichael.Christensen@Sun.COM ds_unreg_all(int instance) 953*7697SMichael.Christensen@Sun.COM { 954*7697SMichael.Christensen@Sun.COM int idx; 955*7697SMichael.Christensen@Sun.COM ds_svc_t *svc; 956*7697SMichael.Christensen@Sun.COM ds_svc_hdl_t hdl; 957*7697SMichael.Christensen@Sun.COM 958*7697SMichael.Christensen@Sun.COM DS_DBG_USR(CE_NOTE, "%s: entered", __func__); 959*7697SMichael.Christensen@Sun.COM 960*7697SMichael.Christensen@Sun.COM /* walk every table entry */ 961*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock); 962*7697SMichael.Christensen@Sun.COM for (idx = 0; idx < ds_svcs.maxsvcs; idx++) { 963*7697SMichael.Christensen@Sun.COM svc = ds_svcs.tbl[idx]; 964*7697SMichael.Christensen@Sun.COM if (DS_SVC_ISFREE(svc)) 965*7697SMichael.Christensen@Sun.COM continue; 966*7697SMichael.Christensen@Sun.COM if ((svc->flags & DSSF_ISUSER) != 0 && svc->drvi == instance) { 967*7697SMichael.Christensen@Sun.COM hdl = svc->hdl; 968*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 969*7697SMichael.Christensen@Sun.COM (void) ds_unreg_hdl(hdl); 970*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock); 971*7697SMichael.Christensen@Sun.COM DS_DBG_USR(CE_NOTE, "%s: ds_unreg_hdl(0x%llx):", 972*7697SMichael.Christensen@Sun.COM __func__, (u_longlong_t)hdl); 973*7697SMichael.Christensen@Sun.COM } 974*7697SMichael.Christensen@Sun.COM } 975*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 976*7697SMichael.Christensen@Sun.COM } 977*7697SMichael.Christensen@Sun.COM 978*7697SMichael.Christensen@Sun.COM /* 979*7697SMichael.Christensen@Sun.COM * Special callbacks to allow the lds module revision-independent access 980*7697SMichael.Christensen@Sun.COM * to service structure data in the callback routines. This assumes that 981*7697SMichael.Christensen@Sun.COM * we put a special "cookie" in the arg argument passed to those 982*7697SMichael.Christensen@Sun.COM * routines (for now, a ptr to the svc structure, but it could be a svc 983*7697SMichael.Christensen@Sun.COM * table index or something that we could get back to the svc table entry). 984*7697SMichael.Christensen@Sun.COM */ 985*7697SMichael.Christensen@Sun.COM void 986*7697SMichael.Christensen@Sun.COM ds_cbarg_get_hdl(ds_cb_arg_t arg, ds_svc_hdl_t *hdlp) 987*7697SMichael.Christensen@Sun.COM { 988*7697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg; 989*7697SMichael.Christensen@Sun.COM 990*7697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 991*7697SMichael.Christensen@Sun.COM *hdlp = svc->hdl; 992*7697SMichael.Christensen@Sun.COM } 993*7697SMichael.Christensen@Sun.COM 994*7697SMichael.Christensen@Sun.COM void 995*7697SMichael.Christensen@Sun.COM ds_cbarg_get_flags(ds_cb_arg_t arg, uint32_t *flagsp) 996*7697SMichael.Christensen@Sun.COM { 997*7697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg; 998*7697SMichael.Christensen@Sun.COM 999*7697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 1000*7697SMichael.Christensen@Sun.COM *flagsp = svc->flags; 1001*7697SMichael.Christensen@Sun.COM } 1002*7697SMichael.Christensen@Sun.COM 1003*7697SMichael.Christensen@Sun.COM void 1004*7697SMichael.Christensen@Sun.COM ds_cbarg_get_drv_info(ds_cb_arg_t arg, int *drvip) 1005*7697SMichael.Christensen@Sun.COM { 1006*7697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg; 1007*7697SMichael.Christensen@Sun.COM 1008*7697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 1009*7697SMichael.Christensen@Sun.COM *drvip = svc->drvi; 1010*7697SMichael.Christensen@Sun.COM } 1011*7697SMichael.Christensen@Sun.COM 1012*7697SMichael.Christensen@Sun.COM void 1013*7697SMichael.Christensen@Sun.COM ds_cbarg_get_drv_per_svc_ptr(ds_cb_arg_t arg, void **dpspp) 1014*7697SMichael.Christensen@Sun.COM { 1015*7697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg; 1016*7697SMichael.Christensen@Sun.COM 1017*7697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 1018*7697SMichael.Christensen@Sun.COM *dpspp = svc->drv_psp; 1019*7697SMichael.Christensen@Sun.COM } 1020*7697SMichael.Christensen@Sun.COM 1021*7697SMichael.Christensen@Sun.COM void 1022*7697SMichael.Christensen@Sun.COM ds_cbarg_get_domain(ds_cb_arg_t arg, ds_domain_hdl_t *dhdlp) 1023*7697SMichael.Christensen@Sun.COM { 1024*7697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg; 1025*7697SMichael.Christensen@Sun.COM 1026*7697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 1027*7697SMichael.Christensen@Sun.COM if (svc->port == NULL) 1028*7697SMichael.Christensen@Sun.COM *dhdlp = ds_my_domain_hdl; 1029*7697SMichael.Christensen@Sun.COM else 1030*7697SMichael.Christensen@Sun.COM *dhdlp = svc->port->domain_hdl; 1031*7697SMichael.Christensen@Sun.COM } 1032*7697SMichael.Christensen@Sun.COM 1033*7697SMichael.Christensen@Sun.COM void 1034*7697SMichael.Christensen@Sun.COM ds_cbarg_get_service_id(ds_cb_arg_t arg, char **servicep) 1035*7697SMichael.Christensen@Sun.COM { 1036*7697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg; 1037*7697SMichael.Christensen@Sun.COM 1038*7697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 1039*7697SMichael.Christensen@Sun.COM *servicep = svc->cap.svc_id; 1040*7697SMichael.Christensen@Sun.COM } 1041*7697SMichael.Christensen@Sun.COM 1042*7697SMichael.Christensen@Sun.COM void 1043*7697SMichael.Christensen@Sun.COM ds_cbarg_set_drv_per_svc_ptr(ds_cb_arg_t arg, void *dpsp) 1044*7697SMichael.Christensen@Sun.COM { 1045*7697SMichael.Christensen@Sun.COM ds_svc_t *svc = (ds_svc_t *)arg; 1046*7697SMichael.Christensen@Sun.COM 1047*7697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 1048*7697SMichael.Christensen@Sun.COM svc->drv_psp = dpsp; 1049*7697SMichael.Christensen@Sun.COM } 1050*7697SMichael.Christensen@Sun.COM 1051*7697SMichael.Christensen@Sun.COM void 1052*7697SMichael.Christensen@Sun.COM ds_cbarg_set_cookie(ds_svc_t *svc) 1053*7697SMichael.Christensen@Sun.COM { 1054*7697SMichael.Christensen@Sun.COM svc->ops.cb_arg = (ds_cb_arg_t)(svc); 1055*7697SMichael.Christensen@Sun.COM } 1056*7697SMichael.Christensen@Sun.COM 1057*7697SMichael.Christensen@Sun.COM int 1058*7697SMichael.Christensen@Sun.COM ds_hdl_get_cbarg(ds_svc_hdl_t hdl, ds_cb_arg_t *cbargp) 1059*7697SMichael.Christensen@Sun.COM { 1060*7697SMichael.Christensen@Sun.COM ds_svc_t *svc; 1061*7697SMichael.Christensen@Sun.COM 1062*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock); 1063*7697SMichael.Christensen@Sun.COM if ((svc = ds_get_svc(hdl)) != NULL && 1064*7697SMichael.Christensen@Sun.COM (svc->flags & DSSF_ISUSER) != 0) { 1065*7697SMichael.Christensen@Sun.COM ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 1066*7697SMichael.Christensen@Sun.COM *cbargp = svc->ops.cb_arg; 1067*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 1068*7697SMichael.Christensen@Sun.COM return (0); 1069*7697SMichael.Christensen@Sun.COM } 1070*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 1071*7697SMichael.Christensen@Sun.COM return (ENXIO); 1072*7697SMichael.Christensen@Sun.COM } 1073*7697SMichael.Christensen@Sun.COM 1074*7697SMichael.Christensen@Sun.COM int 1075*7697SMichael.Christensen@Sun.COM ds_is_my_hdl(ds_svc_hdl_t hdl, int instance) 1076*7697SMichael.Christensen@Sun.COM { 1077*7697SMichael.Christensen@Sun.COM ds_svc_t *svc; 1078*7697SMichael.Christensen@Sun.COM int rv = 0; 1079*7697SMichael.Christensen@Sun.COM 1080*7697SMichael.Christensen@Sun.COM mutex_enter(&ds_svcs.lock); 1081*7697SMichael.Christensen@Sun.COM if ((svc = ds_get_svc(hdl)) == NULL) { 1082*7697SMichael.Christensen@Sun.COM DS_DBG_USR(CE_NOTE, "%s: invalid hdl: 0x%llx\n", __func__, 1083*7697SMichael.Christensen@Sun.COM (u_longlong_t)hdl); 1084*7697SMichael.Christensen@Sun.COM rv = ENXIO; 1085*7697SMichael.Christensen@Sun.COM } else if (instance == DS_INVALID_INSTANCE) { 1086*7697SMichael.Christensen@Sun.COM if ((svc->flags & DSSF_ISUSER) != 0) { 1087*7697SMichael.Christensen@Sun.COM DS_DBG_USR(CE_NOTE, "%s: unowned hdl: 0x%llx\n", 1088*7697SMichael.Christensen@Sun.COM __func__, (u_longlong_t)hdl); 1089*7697SMichael.Christensen@Sun.COM rv = EACCES; 1090*7697SMichael.Christensen@Sun.COM } 1091*7697SMichael.Christensen@Sun.COM } else if ((svc->flags & DSSF_ISUSER) == 0 || svc->drvi != instance) { 1092*7697SMichael.Christensen@Sun.COM DS_DBG_USR(CE_NOTE, "%s: unowned hdl: 0x%llx\n", __func__, 1093*7697SMichael.Christensen@Sun.COM (u_longlong_t)hdl); 1094*7697SMichael.Christensen@Sun.COM rv = EACCES; 1095*7697SMichael.Christensen@Sun.COM } 1096*7697SMichael.Christensen@Sun.COM mutex_exit(&ds_svcs.lock); 1097*7697SMichael.Christensen@Sun.COM return (rv); 1098*7697SMichael.Christensen@Sun.COM } 1099