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.
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.
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]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/param.h>
27 #include <sys/types.h>
30 #include <sys/vnode.h>
32 #include <sys/stream.h>
33 #include <sys/stropts.h>
34 #include <sys/strsubr.h>
36 #include <sys/vnode.h>
37 #include <sys/socket.h>
38 #include <sys/sockio.h>
39 #include <sys/cmn_err.h>
44 #include <sys/sunddi.h>
45 #include <sys/sunldi.h>
48 #include <sys/sysmacros.h>
50 #include <sys/modctl.h>
53 * Routines to allow strplumb() legitimate access
57 kstr_open(major_t maj
, minor_t min
, vnode_t
**vpp
, int *fd
)
62 vp
= makespecvp(makedevice(maj
, min
), VCHR
);
65 * Fix for 4170365: only allocate file descriptor entry
66 * if file descriptor is to be returned; otherwise VOP_OPEN.
69 error
= fassign(&vp
, FREAD
|FWRITE
, fd
);
71 error
= VOP_OPEN(&vp
, FREAD
|FWRITE
, CRED(), NULL
);
74 * Must set vpp after calling fassign()/VOP_OPEN()
75 * since `vp' might change if it's a clone driver.
84 kstr_plink(vnode_t
*vp
, int fd
, int *mux_id
)
89 if (error
= strioctl(vp
, I_PLINK
, (intptr_t)fd
, 0, K_TO_K
, CRED(), &id
))
97 kstr_unplink(vnode_t
*vp
, int mux_id
)
101 return (strioctl(vp
, I_PUNLINK
, (intptr_t)mux_id
, 0,
102 K_TO_K
, CRED(), &rval
));
106 kstr_push(vnode_t
*vp
, char *mod
)
110 return (strioctl(vp
, I_PUSH
, (intptr_t)mod
, 0, K_TO_K
, CRED(), &rval
));
114 kstr_pop(vnode_t
*vp
)
118 return (strioctl(vp
, I_POP
, 0, 0, K_TO_K
, CRED(), &rval
));
122 kstr_close(vnode_t
*vp
, int fd
)
126 if (vp
== (vnode_t
*)NULL
&& fd
== -1)
130 if (closeandsetf(fd
, NULL
) == 0) {
136 ret
= VOP_CLOSE(vp
, FREAD
|FWRITE
, 1, (offset_t
)0, CRED(), NULL
);
143 kstr_ioctl(struct vnode
*vp
, int cmd
, intptr_t arg
)
147 return (strioctl(vp
, cmd
, arg
, 0, K_TO_K
, CRED(), &rval
));
151 * Optionally send data (if smp set) and optionally receive data (if rmp is
152 * set). If timeo is NULL the reception will sleep until a message is
153 * received; otherwise the sleep is limited to the specified amount of time.
156 kstr_msg(vnode_t
*vp
, mblk_t
*smp
, mblk_t
**rmp
, timestruc_t
*timeo
)
159 clock_t timout
; /* milliseconds */
164 if (rmp
== NULL
&& timeo
!= NULL
&&
165 (timeo
->tv_sec
!= 0 || timeo
->tv_nsec
!= 0))
168 if (smp
== NULL
&& rmp
== NULL
)
172 /* Send message while honoring flow control */
173 (void) kstrputmsg(vp
, smp
, NULL
, 0, 0,
174 MSG_BAND
| MSG_HOLDSIG
| MSG_IGNERROR
, 0);
178 /* No reply wanted by caller */
183 * Convert from nanoseconds to milliseconds.
186 timout
= timeo
->tv_sec
* 1000 + timeo
->tv_nsec
/ 1000000;
187 if (timout
> INT_MAX
)
192 /* Wait for timeout millseconds for a message */
196 error
= kstrgetmsg(vp
, rmp
, NULL
, &pri
, &pflag
, timout
, &rval
);
197 /* Callers use *rmp == NULL to determine that there was a timeout */
203 #define SAD_ADM "/devices/pseudo/sad@0:admin"
204 #define SAD_USR "/devices/pseudo/sad@0:user"
207 * It is the callers responsibility to make sure that "mods"
208 * conforms to what is required. We do not check it here.
210 * "maj", "min", and "lastmin" are value-result parameters.
211 * for SET_AUTOPUSH, "anchor" should be set to the place in the stream
212 * to put the anchor, or NULL if no anchor needs to be set.
213 * for GET_AUTOPUSH, "anchor" should point to a uint_t to store the
214 * position of the anchor at, or NULL if the caller is not interested.
217 kstr_autopush(int op
, major_t
*maj
, minor_t
*min
, minor_t
*lastmin
,
218 uint_t
*anchor
, char *mods
[])
222 struct strapush push
;
225 li
= ldi_ident_from_anon();
226 if (op
== SET_AUTOPUSH
|| op
== CLR_AUTOPUSH
) {
227 error
= ldi_open_by_name(SAD_ADM
, FREAD
|FWRITE
,
230 printf("kstr_autopush: open failed error %d\n", error
);
231 ldi_ident_release(li
);
235 error
= ldi_open_by_name(SAD_USR
, FREAD
|FWRITE
,
238 printf("kstr_autopush: open failed error %d\n", error
);
239 ldi_ident_release(li
);
243 ldi_ident_release(li
);
247 /* Get autopush information */
249 push
.sap_major
= *maj
;
250 push
.sap_minor
= *min
;
252 error
= ldi_ioctl(lh
, SAD_GAP
, (intptr_t)&push
,
253 FKIOCTL
, kcred
, &rval
);
255 printf("kstr_autopush: "
256 "ioctl(GET_AUTOPUSH) failed, error %d\n", error
);
257 (void) ldi_close(lh
, FREAD
|FWRITE
, kcred
);
260 switch (push
.sap_cmd
) {
262 *maj
= push
.sap_major
;
263 *min
= push
.sap_minor
;
268 *maj
= push
.sap_major
;
269 *min
= push
.sap_minor
;
270 *lastmin
= push
.sap_lastminor
;
274 *maj
= push
.sap_major
;
280 *anchor
= push
.sap_anchor
;
282 if (push
.sap_npush
> 1) {
283 for (i
= 0; i
< push
.sap_npush
&&
284 mods
[i
] != NULL
; i
++)
285 (void) strcpy(mods
[i
], push
.sap_list
[i
]);
288 (void) ldi_close(lh
, FREAD
|FWRITE
, kcred
);
292 /* Remove autopush information */
294 push
.sap_cmd
= SAP_CLEAR
;
295 push
.sap_minor
= *min
;
296 push
.sap_major
= *maj
;
298 error
= ldi_ioctl(lh
, SAD_SAP
, (intptr_t)&push
,
299 FKIOCTL
, kcred
, &rval
);
301 printf("kstr_autopush: "
302 "ioctl(CLR_AUTOPUSH) failed, error %d\n", error
);
304 (void) ldi_close(lh
, FREAD
|FWRITE
, kcred
);
308 /* Set autopush information */
310 if (*min
== (minor_t
)-1) {
311 push
.sap_cmd
= SAP_ALL
;
312 } else if (*lastmin
== 0) {
313 push
.sap_cmd
= SAP_ONE
;
315 push
.sap_cmd
= SAP_RANGE
;
319 push
.sap_anchor
= *anchor
;
323 push
.sap_minor
= *min
;
324 push
.sap_major
= *maj
;
326 push
.sap_lastminor
= *lastmin
;
328 push
.sap_lastminor
= 0;
331 for (i
= 0; i
< MAXAPUSH
&& mods
[i
] != (char *)NULL
; i
++) {
332 (void) strcpy(push
.sap_list
[i
], mods
[i
]);
335 push
.sap_list
[i
][0] = '\0';
337 error
= ldi_ioctl(lh
, SAD_SAP
, (intptr_t)&push
,
338 FKIOCTL
, kcred
, &rval
);
340 printf("kstr_autopush: "
341 "ioctl(SET_AUTOPUSH) failed, error %d\n", error
);
343 (void) ldi_close(lh
, FREAD
|FWRITE
, kcred
);
347 (void) ldi_close(lh
, FREAD
|FWRITE
, kcred
);