1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /*
26  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
27  */
28 
29 #ifndef _SYS_SUNLDI_IMPL_H
30 #define	_SYS_SUNLDI_IMPL_H
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 #include <sys/dditypes.h>
37 #include <sys/vnode.h>
38 
39 /*
40  * NOTE
41  *
42  * The contents of this file are private to this implementation
43  * of Solaris and are subject to change at any time without notice.
44  *
45  * Applications and drivers using these interfaces will fail
46  * to run on future releases.
47  */
48 
49 /*
50  * LDI hash definitions
51  */
52 #define	LH_HASH_SZ	32
53 #define	LI_HASH_SZ	32
54 
55 /*
56  * Obsolete LDI event interfaces are available for now but are deprecated and a
57  * warning will be issued to consumers.
58  */
59 #define	LDI_OBSOLETE_EVENT	1
60 
61 /*
62  * Flag for LDI handle's lh_flags field
63  */
64 #define	LH_FLAGS_NOTIFY	0x0001		/* invoked in context of a notify */
65 
66 /*
67  * LDI initialization function
68  */
69 void ldi_init(void);
70 
71 /*
72  * LDI streams linking interfaces
73  */
74 extern int ldi_mlink_lh(vnode_t *, int, intptr_t, cred_t *, int *);
75 extern int ldi_mlink_fp(struct stdata *, struct file *, int, int);
76 extern int ldi_munlink_fp(struct stdata *, struct file *, int);
77 
78 /*
79  * LDI module identifier
80  */
81 struct ldi_ident {
82 	/* protected by ldi_ident_hash_lock */
83 	struct ldi_ident		*li_next;
84 	uint_t				li_ref;
85 
86 	/* unique/static fields in the ident */
87 	char				li_modname[MODMAXNAMELEN];
88 	modid_t				li_modid;
89 	major_t				li_major;
90 	dev_info_t			*li_dip;
91 	dev_t				li_dev;
92 };
93 
94 /*
95  * LDI handle
96  */
97 struct ldi_handle {
98 	/* protected by ldi_handle_hash_lock */
99 	struct ldi_handle		*lh_next;
100 	uint_t				lh_ref;
101 	uint_t				lh_flags;
102 
103 	/* unique/static fields in the handle */
104 	uint_t				lh_type;
105 	struct ldi_ident		*lh_ident;
106 	vnode_t				*lh_vp;
107 
108 #ifdef	LDI_OBSOLETE_EVENT
109 	/* fields protected by lh_lock */
110 	kmutex_t			lh_lock[1];
111 	struct ldi_event		*lh_events;
112 #endif
113 };
114 
115 /*
116  * LDI event information
117  */
118 #ifdef	LDI_OBSOLETE_EVENT
119 typedef struct ldi_event {
120 	/* fields protected by le_lhp->lh_lock */
121 	struct ldi_event	*le_next;
122 	struct ldi_event	*le_prev;
123 
124 	/* unique/static fields in the handle */
125 	struct ldi_handle	*le_lhp;
126 	void			(*le_handler)();
127 	void			*le_arg;
128 	ddi_callback_id_t	le_id;
129 } ldi_event_t;
130 #endif
131 
132 typedef struct ldi_ev_callback_impl {
133 	struct ldi_handle	*lec_lhp;
134 	dev_info_t		*lec_dip;
135 	dev_t			lec_dev;
136 	int			lec_spec;
137 	int			(*lec_notify)();
138 	void			(*lec_finalize)();
139 	void			*lec_arg;
140 	void			*lec_cookie;
141 	void			*lec_id;
142 	list_node_t		lec_list;
143 } ldi_ev_callback_impl_t;
144 
145 /*
146  * Members of "struct ldi_ev_callback_list" are protected by their le_lock
147  * member.  The struct is currently only used once, as a file-level global,
148  * and the locking protocol is currently implemented in ldi_ev_lock() and
149  * ldi_ev_unlock().
150  *
151  * When delivering events to subscribers, ldi_invoke_notify() and
152  * ldi_invoke_finalize() will walk the list of callbacks: le_head.  It is
153  * possible that an invoked callback function will need to unregister an
154  * arbitrary number of callbacks from this list.
155  *
156  * To enable ldi_ev_remove_callbacks() to remove elements from the list
157  * without breaking the walk-in-progress, we store the next element in the
158  * walk direction on the struct as le_walker_next and le_walker_prev.
159  */
160 struct ldi_ev_callback_list {
161 	kmutex_t		le_lock;
162 	kcondvar_t		le_cv;
163 	int			le_busy;
164 	void			*le_thread;
165 	list_t			le_head;
166 	ldi_ev_callback_impl_t	*le_walker_next;
167 	ldi_ev_callback_impl_t	*le_walker_prev;
168 };
169 
170 int ldi_invoke_notify(dev_info_t *dip, dev_t dev, int spec_type, char *event,
171     void *ev_data);
172 void ldi_invoke_finalize(dev_info_t *dip, dev_t dev, int spec_type, char *event,
173     int ldi_result, void *ev_data);
174 int e_ddi_offline_notify(dev_info_t *dip);
175 void e_ddi_offline_finalize(dev_info_t *dip, int result);
176 
177 
178 /*
179  * LDI device usage interfaces
180  *
181  * ldi_usage_count(), ldi_usage_walker(), and ldi_usage_t
182  *
183  * These functions are used by the devinfo driver and fuser to get a
184  * device usage information from the LDI. These functions along with
185  * the ldi_usage_t data structure allow these other subsystems to have
186  * no knowledge of how the LDI stores it's internal state.
187  *
188  * ldi_usage_count() provides an count of how many kernel
189  *	device clients currently exist.
190  *
191  * ldi_usage_walker() reports all kernel device usage information.
192  */
193 #define	LDI_USAGE_CONTINUE	0
194 #define	LDI_USAGE_TERMINATE	1
195 
196 typedef struct ldi_usage {
197 	/*
198 	 * information about the kernel subsystem that is accessing
199 	 * the target device
200 	 */
201 	modid_t		src_modid;
202 	char		*src_name;
203 	dev_info_t	*src_dip;
204 	dev_t		src_devt;
205 
206 	/*
207 	 * information about the target device that is open
208 	 */
209 	modid_t		tgt_modid;
210 	char		*tgt_name;
211 	dev_info_t	*tgt_dip;
212 	dev_t		tgt_devt;
213 	int		tgt_spec_type;
214 } ldi_usage_t;
215 
216 int ldi_usage_count();
217 void ldi_usage_walker(void *arg,
218     int (*callback)(const ldi_usage_t *ldi_usage, void *arg));
219 
220 #ifdef __cplusplus
221 }
222 #endif
223 
224 #endif	/* _SYS_SUNLDI_IMPL_H */
225