xref: /onnv-gate/usr/src/uts/sun4v/io/ds_drv.c (revision 7697:ef43d2dd0b19)
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