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 #define LH_FLAGS_NOTIFY_NOTIFY 0x0002 /* processed once in notify loop */
66 #define LH_FLAGS_NOTIFY_FINALIZE 0x0004 /* processed once in finalize loop */
67
68 /*
69 * LDI initialization function
70 */
71 void ldi_init(void);
72
73 /*
74 * LDI streams linking interfaces
75 */
76 extern int ldi_mlink_lh(vnode_t *, int, intptr_t, cred_t *, int *);
77 extern void ldi_mlink_fp(struct stdata *, struct file *, int, int);
78 extern void ldi_munlink_fp(struct stdata *, struct file *, int);
79
80 /*
81 * LDI module identifier
82 */
83 struct ldi_ident {
84 /* protected by ldi_ident_hash_lock */
85 struct ldi_ident *li_next;
86 uint_t li_ref;
87
88 /* unique/static fields in the ident */
89 char li_modname[MODMAXNAMELEN];
90 modid_t li_modid;
91 major_t li_major;
92 dev_info_t *li_dip;
93 dev_t li_dev;
94 };
95
96 /*
97 * LDI handle
98 */
99 struct ldi_handle {
100 /* protected by ldi_handle_hash_lock */
101 struct ldi_handle *lh_next;
102 uint_t lh_ref;
103 uint_t lh_flags;
104
105 /* unique/static fields in the handle */
106 uint_t lh_type;
107 struct ldi_ident *lh_ident;
108 vnode_t *lh_vp;
109
110 #ifdef LDI_OBSOLETE_EVENT
111 /* fields protected by lh_lock */
112 kmutex_t lh_lock[1];
113 struct ldi_event *lh_events;
114 #endif
115 };
116
117 /*
118 * LDI event information
119 */
120 #ifdef LDI_OBSOLETE_EVENT
121 typedef struct ldi_event {
122 /* fields protected by le_lhp->lh_lock */
123 struct ldi_event *le_next;
124 struct ldi_event *le_prev;
125
126 /* unique/static fields in the handle */
127 struct ldi_handle *le_lhp;
128 void (*le_handler)();
129 void *le_arg;
130 ddi_callback_id_t le_id;
131 } ldi_event_t;
132 #endif
133
134 typedef struct ldi_ev_callback_impl {
135 struct ldi_handle *lec_lhp;
136 dev_info_t *lec_dip;
137 dev_t lec_dev;
138 int lec_spec;
139 int (*lec_notify)();
140 void (*lec_finalize)();
141 void *lec_arg;
142 void *lec_cookie;
143 void *lec_id;
144 list_node_t lec_list;
145 } ldi_ev_callback_impl_t;
146
147 /*
148 * Members of "struct ldi_ev_callback_list" are protected by their le_lock
149 * member. The struct is currently only used once, as a file-level global,
150 * and the locking protocol is currently implemented in ldi_ev_lock() and
151 * ldi_ev_unlock().
152 *
153 * When delivering events to subscribers, ldi_invoke_notify() and
154 * ldi_invoke_finalize() will walk the list of callbacks: le_head. It is
155 * possible that an invoked callback function will need to unregister an
156 * arbitrary number of callbacks from this list.
157 *
158 * To enable ldi_ev_remove_callbacks() to remove elements from the list
159 * without breaking the walk-in-progress, we store the next element in the
160 * walk direction on the struct as le_walker_next and le_walker_prev.
161 */
162 struct ldi_ev_callback_list {
163 kmutex_t le_lock;
164 kcondvar_t le_cv;
165 int le_busy;
166 void *le_thread;
167 list_t le_head;
168 ldi_ev_callback_impl_t *le_walker_next;
169 ldi_ev_callback_impl_t *le_walker_prev;
170 };
171
172 int ldi_invoke_notify(dev_info_t *dip, dev_t dev, int spec_type, char *event,
173 void *ev_data);
174 void ldi_invoke_finalize(dev_info_t *dip, dev_t dev, int spec_type, char *event,
175 int ldi_result, void *ev_data);
176 int e_ddi_offline_notify(dev_info_t *dip);
177 void e_ddi_offline_finalize(dev_info_t *dip, int result);
178
179
180 /*
181 * LDI device usage interfaces
182 *
183 * ldi_usage_count(), ldi_usage_walker(), and ldi_usage_t
184 *
185 * These functions are used by the devinfo driver and fuser to get a
186 * device usage information from the LDI. These functions along with
187 * the ldi_usage_t data structure allow these other subsystems to have
188 * no knowledge of how the LDI stores it's internal state.
189 *
190 * ldi_usage_count() provides an count of how many kernel
191 * device clients currently exist.
192 *
193 * ldi_usage_walker() reports all kernel device usage information.
194 */
195 #define LDI_USAGE_CONTINUE 0
196 #define LDI_USAGE_TERMINATE 1
197
198 typedef struct ldi_usage {
199 /*
200 * information about the kernel subsystem that is accessing
201 * the target device
202 */
203 modid_t src_modid;
204 char *src_name;
205 dev_info_t *src_dip;
206 dev_t src_devt;
207
208 /*
209 * information about the target device that is open
210 */
211 modid_t tgt_modid;
212 char *tgt_name;
213 dev_info_t *tgt_dip;
214 dev_t tgt_devt;
215 int tgt_spec_type;
216 } ldi_usage_t;
217
218 int ldi_usage_count();
219 void ldi_usage_walker(void *arg,
220 int (*callback)(const ldi_usage_t *ldi_usage, void *arg));
221
222 #ifdef __cplusplus
223 }
224 #endif
225
226 #endif /* _SYS_SUNLDI_IMPL_H */