2 * sppp_mod.c - modload support for PPP pseudo-device driver.
4 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5 * Use is subject to license terms.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation is hereby granted, provided that the above copyright
9 * notice appears in all copies.
11 * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
12 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
13 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
15 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
16 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
18 * Copyright (c) 1994 The Australian National University.
19 * All rights reserved.
21 * Permission to use, copy, modify, and distribute this software and its
22 * documentation is hereby granted, provided that the above copyright
23 * notice appears in all copies. This software is provided without any
24 * warranty, express or implied. The Australian National University
25 * makes no representations about the suitability of this software for
28 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
29 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
30 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
31 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
34 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
35 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
36 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
37 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
38 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
41 * This driver is derived from the original SVR4 STREAMS PPP driver
42 * originally written by Paul Mackerras <paul.mackerras@cs.anu.edu.au>.
44 * Adi Masputra <adi.masputra@sun.com> rewrote and restructured the code
45 * for improved performance and scalability.
48 #define RCSID " $Id: sppp_mod.c,v 1.0 2000/05/08 10:53:28 masputra Exp $"
50 #include <sys/types.h>
51 #include <sys/systm.h>
54 #include <sys/sunddi.h>
56 #include <sys/kstat.h>
57 #include <net/pppio.h>
58 #include <sys/modctl.h>
63 static int _mi_driver_attach(dev_info_t
*, ddi_attach_cmd_t
);
64 static int _mi_driver_detach(dev_info_t
*, ddi_detach_cmd_t
);
65 static int _mi_driver_info(dev_info_t
*, ddi_info_cmd_t
, void *, void **);
68 * Globals for PPP multiplexer module wrapper
70 extern const char sppp_module_description
[];
71 static dev_info_t
*_mi_dip
;
73 #define PPP_MI_HIWAT (PPP_MTU * 16) /* XXX find more meaningful value */
74 #define PPP_MI_LOWAT (PPP_MTU * 14) /* XXX find more meaningful value */
76 static struct module_info sppp_modinfo
= {
77 PPP_MOD_ID
, /* mi_idnum */
78 PPP_DRV_NAME
, /* mi_idname */
80 PPP_MAXMTU
, /* mi_maxpsz */
81 PPP_MI_HIWAT
, /* mi_hiwat */
82 PPP_MI_LOWAT
/* mi_lowat */
85 static struct qinit sppp_urinit
= {
88 sppp_open
, /* qi_qopen */
89 sppp_close
, /* qi_qclose */
91 &sppp_modinfo
, /* qi_minfo */
95 static struct qinit sppp_uwinit
= {
96 (int (*)())sppp_uwput
, /* qi_putp */
97 (int (*)())sppp_uwsrv
, /* qi_srvp */
100 NULL
, /* qi_qadmin */
101 &sppp_modinfo
, /* qi_minfo */
105 static struct qinit sppp_lrinit
= {
106 (int (*)())sppp_lrput
, /* qi_putp */
107 (int (*)())sppp_lrsrv
, /* qi_srvp */
109 NULL
, /* qi_qclose */
110 NULL
, /* qi_qadmin */
111 &sppp_modinfo
, /* qi_minfo */
115 static struct qinit sppp_lwinit
= {
117 (int (*)())sppp_lwsrv
, /* qi_srvp */
119 NULL
, /* qi_qclose */
120 NULL
, /* qi_qadmin */
121 &sppp_modinfo
, /* qi_minfo */
125 static struct streamtab sppp_tab
= {
126 &sppp_urinit
, /* st_rdinit */
127 &sppp_uwinit
, /* st_wrinit */
128 &sppp_lrinit
, /* st_muxrinit */
129 &sppp_lwinit
/* st_muxwrinit */
133 * Descriptions for flags values in cb_flags field:
136 * An inner perimeter that spans the queue pair.
138 * An outer perimeter that spans over all queues in the module.
140 * Open & close procedures are entered exclusively at outer perimeter.
142 * Entry to put procedures are done with SHARED (reader) acess
143 * and not EXCLUSIVE (writer) access.
147 * 1. Open and close procedures are entered with EXCLUSIVE (writer)
148 * access at the inner perimeter, and with EXCLUSIVE (writer) access at
149 * the outer perimeter.
151 * 2. Put procedures are entered with SHARED (reader) access at the inner
152 * perimeter, and with SHARED (reader) access at the outer perimeter.
154 * 3. Service procedures are entered with EXCLUSIVE (writer) access at
155 * the inner perimeter, and with SHARED (reader) access at the
158 * Do not attempt to modify these flags unless the entire corresponding
159 * driver code is changed to accomodate the newly represented MT-STREAMS
160 * flags. Doing so without making proper modifications to the driver code
161 * will severely impact the intended driver behavior, and thus may affect
162 * the system's stability and performance.
164 DDI_DEFINE_STREAM_OPS(sppp_ops
, \
166 _mi_driver_attach
, _mi_driver_detach
, nodev
, _mi_driver_info
, \
167 D_NEW
| D_MP
| D_MTQPAIR
| D_MTOUTPERIM
| D_MTOCEXCL
| D_MTPUTSHARED
, \
168 &sppp_tab
, ddi_quiesce_not_supported
);
170 static struct modldrv modldrv
= {
171 &mod_driverops
, /* drv_modops */
172 (char *)sppp_module_description
, /* drv_linkinfo */
173 &sppp_ops
/* drv_dev_ops */
176 static struct modlinkage modlinkage
= {
177 MODREV_1
, /* ml_rev, has to be MODREV_1 */
178 &modldrv
, /* ml_linkage, NULL-terminated list */
179 NULL
/* of linkage structures */
185 return (mod_install(&modlinkage
));
191 return (mod_remove(&modlinkage
));
195 _info(struct modinfo
*modinfop
)
197 return (mod_info(&modlinkage
, modinfop
));
201 * _mi_driver_attach()
204 * Attach a point-to-point interface to the system.
207 _mi_driver_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
209 if (cmd
!= DDI_ATTACH
) {
210 return (DDI_FAILURE
);
213 if (ddi_create_minor_node(dip
, PPP_DRV_NAME
, S_IFCHR
,
214 0, DDI_PSEUDO
, CLONE_DEV
) == DDI_FAILURE
) {
215 ddi_remove_minor_node(dip
, NULL
);
216 return (DDI_FAILURE
);
218 sppp_dlpi_pinfoinit();
219 return (DDI_SUCCESS
);
223 * _mi_driver_detach()
226 * Detach an interface to the system.
229 _mi_driver_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
231 if (cmd
!= DDI_DETACH
) {
232 return (DDI_FAILURE
);
234 ddi_remove_minor_node(dip
, NULL
);
236 return (DDI_SUCCESS
);
243 * Translate "dev_t" to a pointer to the associated "dev_info_t".
247 _mi_driver_info(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
,
253 case DDI_INFO_DEVT2DEVINFO
:
254 if (_mi_dip
== NULL
) {
257 *result
= (void *)_mi_dip
;
261 case DDI_INFO_DEVT2INSTANCE
: