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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * DLPI stub driver; currently supports VNI and IPMP stub devices.
32 #include <sys/sunddi.h>
35 #include <sys/strsun.h>
36 #include <sys/stropts.h>
37 #include <sys/types.h>
38 #include <sys/id_space.h>
39 #include <sys/sysmacros.h>
41 #include <sys/modctl.h>
42 #include <sys/mkdev.h>
45 #include "dlpistub_impl.h"
47 static id_space_t
*ds_minors
;
48 static dev_info_t
*ds_dip
;
51 * DL_INFO_ACK template.
53 static dl_info_ack_t ds_infoack
= {
54 DL_INFO_ACK
, /* dl_primitive */
57 0, /* dl_addr_length */
60 0, /* dl_current_state */
61 0, /* dl_sap_length */
62 DL_CLDLS
, /* dl_service_mode */
63 0, /* dl_qos_length */
64 0, /* dl_qos_offset */
65 0, /* dl_qos_range_length */
66 0, /* dl_qos_range_offset */
67 DL_STYLE2
, /* dl_provider_style */
68 0, /* dl_addr_offset */
69 DL_VERSION_2
, /* dl_version */
70 0, /* dl_brdcst_addr_length */
71 0, /* dl_brdcst_addr_offset */
76 ds_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
78 if (cmd
!= DDI_ATTACH
)
81 if (ddi_create_minor_node(dip
, "vni", S_IFCHR
, DS_MINOR_VNI
,
82 DDI_PSEUDO
, 0) == DDI_FAILURE
||
83 ddi_create_minor_node(dip
, "ipmpstub", S_IFCHR
, DS_MINOR_IPMP
,
84 DDI_PSEUDO
, 0) == DDI_FAILURE
) {
85 ddi_remove_minor_node(dip
, NULL
);
86 cmn_err(CE_NOTE
, "ds_attach: cannot create minor nodes");
91 ds_minors
= id_space_create("ds_minors", DS_MINOR_START
, MAXMIN32
);
96 ds_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
98 if (cmd
!= DDI_DETACH
)
101 id_space_destroy(ds_minors
);
103 ASSERT(dip
== ds_dip
);
104 ddi_remove_minor_node(dip
, NULL
);
106 return (DDI_SUCCESS
);
111 ds_devinfo(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
, void **result
)
113 int error
= DDI_FAILURE
;
116 case DDI_INFO_DEVT2INSTANCE
:
120 case DDI_INFO_DEVT2DEVINFO
:
121 if (ds_dip
!= NULL
) {
132 ds_open(queue_t
*q
, dev_t
*devp
, int flag
, int sflag
, cred_t
*credp
)
137 if (sflag
== CLONEOPEN
|| sflag
== MODOPEN
)
140 if (q
->q_ptr
!= NULL
)
143 switch (getminor(*devp
)) {
154 dsp
= kmem_zalloc(sizeof (dlpistub_t
), KM_SLEEP
);
156 dsp
->ds_minor
= (minor_t
)id_alloc(ds_minors
);
157 dsp
->ds_state
= DL_UNATTACHED
;
158 *devp
= makedevice(getmajor(*devp
), dsp
->ds_minor
);
159 q
->q_ptr
= WR(q
)->q_ptr
= dsp
;
167 ds_close(queue_t
*q
, int flag
, cred_t
*credp
)
169 dlpistub_t
*dsp
= q
->q_ptr
;
172 q
->q_ptr
= WR(q
)->q_ptr
= NULL
;
174 id_free(ds_minors
, dsp
->ds_minor
);
175 kmem_free(dsp
, sizeof (dlpistub_t
));
181 ds_badprim(queue_t
*q
, mblk_t
*mp
, t_scalar_t prim
)
183 dlerrorack(q
, mp
, prim
, DL_BADPRIM
, 0);
188 ds_outstate(queue_t
*q
, mblk_t
*mp
, t_scalar_t prim
)
190 dlerrorack(q
, mp
, prim
, DL_OUTSTATE
, 0);
195 ds_wput(queue_t
*q
, mblk_t
*mp
)
197 union DL_primitives
*dlp
;
199 dlpistub_t
*dsp
= q
->q_ptr
;
202 switch (DB_TYPE(mp
)) {
205 if (MBLKL(mp
) < sizeof (t_scalar_t
)) {
206 dlerrorack(q
, mp
, DL_PRIM_INVAL
, DL_UNSUPPORTED
, 0);
210 dlp
= (void *)mp
->b_rptr
;
211 prim
= dlp
->dl_primitive
;
214 if (MBLKL(mp
) < DL_ATTACH_REQ_SIZE
)
215 return (ds_badprim(q
, mp
, prim
));
217 if (dsp
->ds_state
!= DL_UNATTACHED
)
218 return (ds_outstate(q
, mp
, prim
));
220 dsp
->ds_state
= DL_UNBOUND
;
221 dlokack(q
, mp
, DL_ATTACH_REQ
);
225 if (MBLKL(mp
) < DL_BIND_REQ_SIZE
)
226 return (ds_badprim(q
, mp
, prim
));
228 if (dsp
->ds_state
!= DL_UNBOUND
)
229 return (ds_outstate(q
, mp
, prim
));
231 dsp
->ds_state
= DL_IDLE
;
232 dlbindack(q
, mp
, dlp
->bind_req
.dl_sap
, NULL
, 0, 0, 0);
236 if (MBLKL(mp
) < DL_INFO_REQ_SIZE
)
237 return (ds_badprim(q
, mp
, prim
));
239 mp
= mexchange(q
, mp
, sizeof (dl_info_ack_t
),
240 M_PCPROTO
, DL_INFO_ACK
);
242 dlip
= (void *)mp
->b_rptr
;
244 dlip
->dl_mac_type
= dsp
->ds_type
;
245 dlip
->dl_current_state
= dsp
->ds_state
;
250 case DL_PHYS_ADDR_REQ
:
251 if (MBLKL(mp
) < DL_PHYS_ADDR_REQ_SIZE
)
252 return (ds_badprim(q
, mp
, prim
));
254 dlphysaddrack(q
, mp
, NULL
, 0);
258 if (MBLKL(mp
) < DL_UNBIND_REQ_SIZE
)
259 return (ds_badprim(q
, mp
, prim
));
261 if (dsp
->ds_state
!= DL_IDLE
)
262 return (ds_outstate(q
, mp
, prim
));
264 dsp
->ds_state
= DL_UNBOUND
;
265 dlokack(q
, mp
, DL_UNBIND_REQ
);
269 if (MBLKL(mp
) < DL_DETACH_REQ_SIZE
)
270 return (ds_badprim(q
, mp
, prim
));
272 if (dsp
->ds_state
!= DL_UNBOUND
)
273 return (ds_outstate(q
, mp
, prim
));
275 dsp
->ds_state
= DL_UNATTACHED
;
276 dlokack(q
, mp
, DL_DETACH_REQ
);
279 case DL_UNITDATA_REQ
:
280 DTRACE_PROBE2(dlpistub__data
, dlpistub_t
*, dsp
,
286 dlerrorack(q
, mp
, prim
, DL_UNSUPPORTED
, 0);
291 miocnak(q
, mp
, 0, EINVAL
);
295 *mp
->b_rptr
&= ~FLUSHW
;
296 if (*mp
->b_rptr
& FLUSHR
)
309 static struct module_info ds_minfo
= {
310 DS_IDNUM
, /* mi_idnum */
311 "dlpistub", /* mi_idname */
313 INFPSZ
, /* mi_maxpsz */
318 static struct qinit ds_rinit
= {
321 ds_open
, /* qi_qopen */
322 ds_close
, /* qi_qclose */
323 NULL
, /* qi_qadmin */
324 &ds_minfo
, /* qi_minfo */
327 static struct qinit ds_winit
= {
328 ds_wput
, /* qi_putp */
331 NULL
, /* qi_qclose */
332 NULL
, /* qi_qadmin */
333 &ds_minfo
, /* qi_minfo */
336 static struct streamtab ds_info
= {
337 &ds_rinit
, /* st_rdinit */
338 &ds_winit
/* st_wrinit */
341 DDI_DEFINE_STREAM_OPS(ds_ops
, nulldev
, nulldev
, ds_attach
, ds_detach
,
342 nodev
, ds_devinfo
, D_MP
|D_MTPERMOD
, &ds_info
, ddi_quiesce_not_supported
);
344 static struct modldrv modldrv
= {
350 static struct modlinkage modlinkage
= {
351 MODREV_1
, &modldrv
, NULL
357 return (mod_install(&modlinkage
));
363 return (mod_remove(&modlinkage
));
367 _info(struct modinfo
*modinfop
)
369 return (mod_info(&modlinkage
, modinfop
));