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 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/param.h>
29 #include <sys/types.h>
32 #include <sys/vnode.h>
34 #include <sys/stream.h>
35 #include <sys/stropts.h>
36 #include <sys/strsubr.h>
38 #include <sys/vnode.h>
39 #include <sys/socket.h>
40 #include <sys/sockio.h>
41 #include <sys/cmn_err.h>
46 #include <sys/sunddi.h>
47 #include <sys/sunldi.h>
50 #include <sys/sysmacros.h>
52 #include <sys/modctl.h>
55 * Routines to allow strplumb() legitimate access
59 kstr_open(major_t maj
, minor_t min
, vnode_t
**vpp
, int *fd
)
64 vp
= makespecvp(makedevice(maj
, min
), VCHR
);
67 * Fix for 4170365: only allocate file descriptor entry
68 * if file descriptor is to be returned; otherwise VOP_OPEN.
71 error
= fassign(&vp
, FREAD
|FWRITE
, fd
);
73 error
= VOP_OPEN(&vp
, FREAD
|FWRITE
, CRED(), NULL
);
76 * Must set vpp after calling fassign()/VOP_OPEN()
77 * since `vp' might change if it's a clone driver.
86 kstr_plink(vnode_t
*vp
, int fd
, int *mux_id
)
91 if (error
= strioctl(vp
, I_PLINK
, (intptr_t)fd
, 0, K_TO_K
, CRED(), &id
))
99 kstr_unplink(vnode_t
*vp
, int mux_id
)
103 return (strioctl(vp
, I_PUNLINK
, (intptr_t)mux_id
, 0,
104 K_TO_K
, CRED(), &rval
));
108 kstr_push(vnode_t
*vp
, char *mod
)
112 return (strioctl(vp
, I_PUSH
, (intptr_t)mod
, 0, K_TO_K
, CRED(), &rval
));
116 kstr_pop(vnode_t
*vp
)
120 return (strioctl(vp
, I_POP
, 0, 0, K_TO_K
, CRED(), &rval
));
124 kstr_close(vnode_t
*vp
, int fd
)
128 if (vp
== (vnode_t
*)NULL
&& fd
== -1)
132 if (closeandsetf(fd
, NULL
) == 0) {
138 ret
= VOP_CLOSE(vp
, FREAD
|FWRITE
, 1, (offset_t
)0, CRED(), NULL
);
145 kstr_ioctl(struct vnode
*vp
, int cmd
, intptr_t arg
)
149 return (strioctl(vp
, cmd
, arg
, 0, K_TO_K
, CRED(), &rval
));
153 * Optionally send data (if smp set) and optionally receive data (if rmp is
154 * set). If timeo is NULL the reception will sleep until a message is
155 * received; otherwise the sleep is limited to the specified amount of time.
158 kstr_msg(vnode_t
*vp
, mblk_t
*smp
, mblk_t
**rmp
, timestruc_t
*timeo
)
161 clock_t timout
; /* milliseconds */
166 if (rmp
== NULL
&& timeo
!= NULL
&&
167 (timeo
->tv_sec
!= 0 || timeo
->tv_nsec
!= 0))
170 if (smp
== NULL
&& rmp
== NULL
)
174 /* Send message while honoring flow control */
175 (void) kstrputmsg(vp
, smp
, NULL
, 0, 0,
176 MSG_BAND
| MSG_HOLDSIG
| MSG_IGNERROR
, 0);
180 /* No reply wanted by caller */
185 * Convert from nanoseconds to milliseconds.
188 timout
= timeo
->tv_sec
* 1000 + timeo
->tv_nsec
/ 1000000;
189 if (timout
> INT_MAX
)
194 /* Wait for timeout millseconds for a message */
198 error
= kstrgetmsg(vp
, rmp
, NULL
, &pri
, &pflag
, timout
, &rval
);
199 /* Callers use *rmp == NULL to determine that there was a timeout */
205 #define SAD_ADM "/devices/pseudo/sad@0:admin"
206 #define SAD_USR "/devices/pseudo/sad@0:user"
209 * It is the callers responsibility to make sure that "mods"
210 * conforms to what is required. We do not check it here.
212 * "maj", "min", and "lastmin" are value-result parameters.
213 * for SET_AUTOPUSH, "anchor" should be set to the place in the stream
214 * to put the anchor, or NULL if no anchor needs to be set.
215 * for GET_AUTOPUSH, "anchor" should point to a uint_t to store the
216 * position of the anchor at, or NULL if the caller is not interested.
219 kstr_autopush(int op
, major_t
*maj
, minor_t
*min
, minor_t
*lastmin
,
220 uint_t
*anchor
, char *mods
[])
224 struct strapush push
;
227 li
= ldi_ident_from_anon();
228 if (op
== SET_AUTOPUSH
|| op
== CLR_AUTOPUSH
) {
229 error
= ldi_open_by_name(SAD_ADM
, FREAD
|FWRITE
,
232 printf("kstr_autopush: open failed error %d\n", error
);
233 ldi_ident_release(li
);
237 error
= ldi_open_by_name(SAD_USR
, FREAD
|FWRITE
,
240 printf("kstr_autopush: open failed error %d\n", error
);
241 ldi_ident_release(li
);
245 ldi_ident_release(li
);
249 /* Get autopush information */
251 push
.sap_major
= *maj
;
252 push
.sap_minor
= *min
;
254 error
= ldi_ioctl(lh
, SAD_GAP
, (intptr_t)&push
,
255 FKIOCTL
, kcred
, &rval
);
257 printf("kstr_autopush: "
258 "ioctl(GET_AUTOPUSH) failed, error %d\n", error
);
259 (void) ldi_close(lh
, FREAD
|FWRITE
, kcred
);
262 switch (push
.sap_cmd
) {
264 *maj
= push
.sap_major
;
265 *min
= push
.sap_minor
;
270 *maj
= push
.sap_major
;
271 *min
= push
.sap_minor
;
272 *lastmin
= push
.sap_lastminor
;
276 *maj
= push
.sap_major
;
282 *anchor
= push
.sap_anchor
;
284 if (push
.sap_npush
> 1) {
285 for (i
= 0; i
< push
.sap_npush
&&
286 mods
[i
] != NULL
; i
++)
287 (void) strcpy(mods
[i
], push
.sap_list
[i
]);
290 (void) ldi_close(lh
, FREAD
|FWRITE
, kcred
);
294 /* Remove autopush information */
296 push
.sap_cmd
= SAP_CLEAR
;
297 push
.sap_minor
= *min
;
298 push
.sap_major
= *maj
;
300 error
= ldi_ioctl(lh
, SAD_SAP
, (intptr_t)&push
,
301 FKIOCTL
, kcred
, &rval
);
303 printf("kstr_autopush: "
304 "ioctl(CLR_AUTOPUSH) failed, error %d\n", error
);
306 (void) ldi_close(lh
, FREAD
|FWRITE
, kcred
);
310 /* Set autopush information */
312 if (*min
== (minor_t
)-1) {
313 push
.sap_cmd
= SAP_ALL
;
314 } else if (*lastmin
== 0) {
315 push
.sap_cmd
= SAP_ONE
;
317 push
.sap_cmd
= SAP_RANGE
;
321 push
.sap_anchor
= *anchor
;
325 push
.sap_minor
= *min
;
326 push
.sap_major
= *maj
;
328 push
.sap_lastminor
= *lastmin
;
330 push
.sap_lastminor
= 0;
333 for (i
= 0; i
< MAXAPUSH
&& mods
[i
] != (char *)NULL
; i
++) {
334 (void) strcpy(push
.sap_list
[i
], mods
[i
]);
337 push
.sap_list
[i
][0] = '\0';
339 error
= ldi_ioctl(lh
, SAD_SAP
, (intptr_t)&push
,
340 FKIOCTL
, kcred
, &rval
);
342 printf("kstr_autopush: "
343 "ioctl(SET_AUTOPUSH) failed, error %d\n", error
);
345 (void) ldi_close(lh
, FREAD
|FWRITE
, kcred
);
349 (void) ldi_close(lh
, FREAD
|FWRITE
, kcred
);