1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * sppp_mod.c - modload support for PPP pseudo-device driver.
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
5*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
6*7c478bd9Sstevel@tonic-gate  *
7*7c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software and its
8*7c478bd9Sstevel@tonic-gate  * documentation is hereby granted, provided that the above copyright
9*7c478bd9Sstevel@tonic-gate  * notice appears in all copies.
10*7c478bd9Sstevel@tonic-gate  *
11*7c478bd9Sstevel@tonic-gate  * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
12*7c478bd9Sstevel@tonic-gate  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
13*7c478bd9Sstevel@tonic-gate  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14*7c478bd9Sstevel@tonic-gate  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  SUN SHALL NOT BE LIABLE FOR
15*7c478bd9Sstevel@tonic-gate  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
16*7c478bd9Sstevel@tonic-gate  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
17*7c478bd9Sstevel@tonic-gate  *
18*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1994 The Australian National University.
19*7c478bd9Sstevel@tonic-gate  * All rights reserved.
20*7c478bd9Sstevel@tonic-gate  *
21*7c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software and its
22*7c478bd9Sstevel@tonic-gate  * documentation is hereby granted, provided that the above copyright
23*7c478bd9Sstevel@tonic-gate  * notice appears in all copies.  This software is provided without any
24*7c478bd9Sstevel@tonic-gate  * warranty, express or implied. The Australian National University
25*7c478bd9Sstevel@tonic-gate  * makes no representations about the suitability of this software for
26*7c478bd9Sstevel@tonic-gate  * any purpose.
27*7c478bd9Sstevel@tonic-gate  *
28*7c478bd9Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
29*7c478bd9Sstevel@tonic-gate  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
30*7c478bd9Sstevel@tonic-gate  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
31*7c478bd9Sstevel@tonic-gate  * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
32*7c478bd9Sstevel@tonic-gate  * OF SUCH DAMAGE.
33*7c478bd9Sstevel@tonic-gate  *
34*7c478bd9Sstevel@tonic-gate  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
35*7c478bd9Sstevel@tonic-gate  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
36*7c478bd9Sstevel@tonic-gate  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
37*7c478bd9Sstevel@tonic-gate  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
38*7c478bd9Sstevel@tonic-gate  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
39*7c478bd9Sstevel@tonic-gate  * OR MODIFICATIONS.
40*7c478bd9Sstevel@tonic-gate  *
41*7c478bd9Sstevel@tonic-gate  * This driver is derived from the original SVR4 STREAMS PPP driver
42*7c478bd9Sstevel@tonic-gate  * originally written by Paul Mackerras <paul.mackerras@cs.anu.edu.au>.
43*7c478bd9Sstevel@tonic-gate  *
44*7c478bd9Sstevel@tonic-gate  * Adi Masputra <adi.masputra@sun.com> rewrote and restructured the code
45*7c478bd9Sstevel@tonic-gate  * for improved performance and scalability.
46*7c478bd9Sstevel@tonic-gate  */
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
49*7c478bd9Sstevel@tonic-gate #define	RCSID	" $Id: sppp_mod.c,v 1.0 2000/05/08 10:53:28 masputra Exp $"
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/strlog.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
58*7c478bd9Sstevel@tonic-gate #include <sys/ksynch.h>
59*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
60*7c478bd9Sstevel@tonic-gate #include <sys/kstat.h>
61*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
62*7c478bd9Sstevel@tonic-gate #include <net/pppio.h>
63*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #include "s_common.h"
66*7c478bd9Sstevel@tonic-gate #include "sppp.h"
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate static int	_mi_driver_attach(dev_info_t *, ddi_attach_cmd_t);
69*7c478bd9Sstevel@tonic-gate static int	_mi_driver_detach(dev_info_t *, ddi_detach_cmd_t);
70*7c478bd9Sstevel@tonic-gate static int	_mi_driver_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate /*
73*7c478bd9Sstevel@tonic-gate  * Globals for PPP multiplexer module wrapper
74*7c478bd9Sstevel@tonic-gate  */
75*7c478bd9Sstevel@tonic-gate extern const char sppp_module_description[];
76*7c478bd9Sstevel@tonic-gate static dev_info_t *_mi_dip;
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate #define	PPP_MI_HIWAT	(PPP_MTU * 16)	/* XXX find more meaningful value */
79*7c478bd9Sstevel@tonic-gate #define	PPP_MI_LOWAT	(PPP_MTU * 14)	/* XXX find more meaningful value */
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate static struct module_info sppp_modinfo = {
82*7c478bd9Sstevel@tonic-gate 	PPP_MOD_ID,		/* mi_idnum */
83*7c478bd9Sstevel@tonic-gate 	PPP_DRV_NAME,		/* mi_idname */
84*7c478bd9Sstevel@tonic-gate 	0,			/* mi_minpsz */
85*7c478bd9Sstevel@tonic-gate 	PPP_MAXMTU,		/* mi_maxpsz */
86*7c478bd9Sstevel@tonic-gate 	PPP_MI_HIWAT,		/* mi_hiwat */
87*7c478bd9Sstevel@tonic-gate 	PPP_MI_LOWAT		/* mi_lowat */
88*7c478bd9Sstevel@tonic-gate };
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate static struct qinit sppp_urinit = {
91*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_putp */
92*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_srvp */
93*7c478bd9Sstevel@tonic-gate 	sppp_open,		/* qi_qopen */
94*7c478bd9Sstevel@tonic-gate 	sppp_close,		/* qi_qclose */
95*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qadmin */
96*7c478bd9Sstevel@tonic-gate 	&sppp_modinfo,		/* qi_minfo */
97*7c478bd9Sstevel@tonic-gate 	NULL			/* qi_mstat */
98*7c478bd9Sstevel@tonic-gate };
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate static struct qinit sppp_uwinit = {
101*7c478bd9Sstevel@tonic-gate 	sppp_uwput,		/* qi_putp */
102*7c478bd9Sstevel@tonic-gate 	sppp_uwsrv,		/* qi_srvp */
103*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qopen */
104*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qclose */
105*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qadmin */
106*7c478bd9Sstevel@tonic-gate 	&sppp_modinfo,		/* qi_minfo */
107*7c478bd9Sstevel@tonic-gate 	NULL			/* qi_mstat */
108*7c478bd9Sstevel@tonic-gate };
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate static struct qinit sppp_lrinit = {
111*7c478bd9Sstevel@tonic-gate 	sppp_lrput,		/* qi_putp */
112*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_srvp */
113*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qopen */
114*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qclose */
115*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qadmin */
116*7c478bd9Sstevel@tonic-gate 	&sppp_modinfo,		/* qi_minfo */
117*7c478bd9Sstevel@tonic-gate 	NULL			/* qi_mstat */
118*7c478bd9Sstevel@tonic-gate };
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate static struct qinit sppp_lwinit = {
121*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_putp */
122*7c478bd9Sstevel@tonic-gate 	sppp_lwsrv,		/* qi_srvp */
123*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qopen */
124*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qclose */
125*7c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qadmin */
126*7c478bd9Sstevel@tonic-gate 	&sppp_modinfo,		/* qi_minfo */
127*7c478bd9Sstevel@tonic-gate 	NULL			/* qi_mstat */
128*7c478bd9Sstevel@tonic-gate };
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate static struct streamtab sppp_tab = {
131*7c478bd9Sstevel@tonic-gate 	&sppp_urinit,		/* st_rdinit */
132*7c478bd9Sstevel@tonic-gate 	&sppp_uwinit,		/* st_wrinit */
133*7c478bd9Sstevel@tonic-gate 	&sppp_lrinit,		/* st_muxrinit */
134*7c478bd9Sstevel@tonic-gate 	&sppp_lwinit		/* st_muxwrinit */
135*7c478bd9Sstevel@tonic-gate };
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate /*
138*7c478bd9Sstevel@tonic-gate  * Descriptions for flags values in cb_flags field:
139*7c478bd9Sstevel@tonic-gate  *
140*7c478bd9Sstevel@tonic-gate  * D_MTQPAIR:
141*7c478bd9Sstevel@tonic-gate  *    An inner perimeter that spans the queue pair.
142*7c478bd9Sstevel@tonic-gate  * D_MTOUTPERIM:
143*7c478bd9Sstevel@tonic-gate  *    An outer perimeter that spans over all queues in the module.
144*7c478bd9Sstevel@tonic-gate  * D_MTOCEXCL:
145*7c478bd9Sstevel@tonic-gate  *    Open & close procedures are entered exclusively at outer perimeter.
146*7c478bd9Sstevel@tonic-gate  * D_MTPUTSHARED:
147*7c478bd9Sstevel@tonic-gate  *    Entry to put procedures are done with SHARED (reader) acess
148*7c478bd9Sstevel@tonic-gate  *    and not EXCLUSIVE (writer) access.
149*7c478bd9Sstevel@tonic-gate  *
150*7c478bd9Sstevel@tonic-gate  * Therefore:
151*7c478bd9Sstevel@tonic-gate  *
152*7c478bd9Sstevel@tonic-gate  * 1. Open and close procedures are entered with EXCLUSIVE (writer)
153*7c478bd9Sstevel@tonic-gate  *    access at the inner perimeter, and with EXCLUSIVE (writer) access at
154*7c478bd9Sstevel@tonic-gate  *    the outer perimeter.
155*7c478bd9Sstevel@tonic-gate  *
156*7c478bd9Sstevel@tonic-gate  * 2. Put procedures are entered with SHARED (reader) access at the inner
157*7c478bd9Sstevel@tonic-gate  *    perimeter, and with SHARED (reader) access at the outer perimeter.
158*7c478bd9Sstevel@tonic-gate  *
159*7c478bd9Sstevel@tonic-gate  * 3. Service procedures are entered with EXCLUSIVE (writer) access at
160*7c478bd9Sstevel@tonic-gate  *    the inner perimeter, and with SHARED (reader) access at the
161*7c478bd9Sstevel@tonic-gate  *    outer perimeter.
162*7c478bd9Sstevel@tonic-gate  *
163*7c478bd9Sstevel@tonic-gate  * Do not attempt to modify these flags unless the entire corresponding
164*7c478bd9Sstevel@tonic-gate  * driver code is changed to accomodate the newly represented MT-STREAMS
165*7c478bd9Sstevel@tonic-gate  * flags. Doing so without making proper modifications to the driver code
166*7c478bd9Sstevel@tonic-gate  * will severely impact the intended driver behavior, and thus may affect
167*7c478bd9Sstevel@tonic-gate  * the system's stability and performance.
168*7c478bd9Sstevel@tonic-gate  */
169*7c478bd9Sstevel@tonic-gate DDI_DEFINE_STREAM_OPS(sppp_ops,						\
170*7c478bd9Sstevel@tonic-gate 	nulldev, nulldev,						\
171*7c478bd9Sstevel@tonic-gate 	_mi_driver_attach, _mi_driver_detach, nodev, _mi_driver_info,	\
172*7c478bd9Sstevel@tonic-gate 	D_NEW | D_MP | D_MTQPAIR | D_MTOUTPERIM | D_MTOCEXCL | D_MTPUTSHARED, \
173*7c478bd9Sstevel@tonic-gate 	&sppp_tab);
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
176*7c478bd9Sstevel@tonic-gate 	&mod_driverops,				/* drv_modops */
177*7c478bd9Sstevel@tonic-gate 	(char *)sppp_module_description,	/* drv_linkinfo */
178*7c478bd9Sstevel@tonic-gate 	&sppp_ops				/* drv_dev_ops */
179*7c478bd9Sstevel@tonic-gate };
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
182*7c478bd9Sstevel@tonic-gate 	MODREV_1,			/* ml_rev, has to be MODREV_1 */
183*7c478bd9Sstevel@tonic-gate 	&modldrv,			/* ml_linkage, NULL-terminated list */
184*7c478bd9Sstevel@tonic-gate 	NULL				/*  of linkage structures */
185*7c478bd9Sstevel@tonic-gate };
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate int
188*7c478bd9Sstevel@tonic-gate _init(void)
189*7c478bd9Sstevel@tonic-gate {
190*7c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate int
194*7c478bd9Sstevel@tonic-gate _fini(void)
195*7c478bd9Sstevel@tonic-gate {
196*7c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
197*7c478bd9Sstevel@tonic-gate }
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate int
200*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
201*7c478bd9Sstevel@tonic-gate {
202*7c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
203*7c478bd9Sstevel@tonic-gate }
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate /*
206*7c478bd9Sstevel@tonic-gate  * _mi_driver_attach()
207*7c478bd9Sstevel@tonic-gate  *
208*7c478bd9Sstevel@tonic-gate  * Description:
209*7c478bd9Sstevel@tonic-gate  *    Attach a point-to-point interface to the system.
210*7c478bd9Sstevel@tonic-gate  */
211*7c478bd9Sstevel@tonic-gate static int
212*7c478bd9Sstevel@tonic-gate _mi_driver_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
213*7c478bd9Sstevel@tonic-gate {
214*7c478bd9Sstevel@tonic-gate 	if (cmd != DDI_ATTACH) {
215*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
216*7c478bd9Sstevel@tonic-gate 	}
217*7c478bd9Sstevel@tonic-gate 	if (ddi_create_minor_node(dip, PPP_DRV_NAME, S_IFCHR,
218*7c478bd9Sstevel@tonic-gate 	    0, DDI_PSEUDO, CLONE_DEV) == DDI_FAILURE) {
219*7c478bd9Sstevel@tonic-gate 		ddi_remove_minor_node(dip, NULL);
220*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
221*7c478bd9Sstevel@tonic-gate 	}
222*7c478bd9Sstevel@tonic-gate 	sppp_dlpi_pinfoinit();
223*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
224*7c478bd9Sstevel@tonic-gate }
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate /*
227*7c478bd9Sstevel@tonic-gate  * _mi_driver_detach()
228*7c478bd9Sstevel@tonic-gate  *
229*7c478bd9Sstevel@tonic-gate  * Description:
230*7c478bd9Sstevel@tonic-gate  *    Detach an interface to the system.
231*7c478bd9Sstevel@tonic-gate  */
232*7c478bd9Sstevel@tonic-gate static int
233*7c478bd9Sstevel@tonic-gate _mi_driver_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
234*7c478bd9Sstevel@tonic-gate {
235*7c478bd9Sstevel@tonic-gate 	if (cmd != DDI_DETACH) {
236*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
237*7c478bd9Sstevel@tonic-gate 	}
238*7c478bd9Sstevel@tonic-gate 	ddi_remove_minor_node(dip, NULL);
239*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
240*7c478bd9Sstevel@tonic-gate }
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate /*
243*7c478bd9Sstevel@tonic-gate  * _mi_driver_info()
244*7c478bd9Sstevel@tonic-gate  *
245*7c478bd9Sstevel@tonic-gate  * Description:
246*7c478bd9Sstevel@tonic-gate  *    Translate "dev_t" to a pointer to the associated "dev_info_t".
247*7c478bd9Sstevel@tonic-gate  */
248*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
249*7c478bd9Sstevel@tonic-gate static int
250*7c478bd9Sstevel@tonic-gate _mi_driver_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
251*7c478bd9Sstevel@tonic-gate 	void **result)
252*7c478bd9Sstevel@tonic-gate {
253*7c478bd9Sstevel@tonic-gate 	int	rc;
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 	switch (infocmd) {
256*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
257*7c478bd9Sstevel@tonic-gate 		if (_mi_dip == NULL) {
258*7c478bd9Sstevel@tonic-gate 			rc = DDI_FAILURE;
259*7c478bd9Sstevel@tonic-gate 		} else {
260*7c478bd9Sstevel@tonic-gate 			*result = (void *)_mi_dip;
261*7c478bd9Sstevel@tonic-gate 			rc = DDI_SUCCESS;
262*7c478bd9Sstevel@tonic-gate 		}
263*7c478bd9Sstevel@tonic-gate 		break;
264*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
265*7c478bd9Sstevel@tonic-gate 		*result = NULL;
266*7c478bd9Sstevel@tonic-gate 		rc = DDI_SUCCESS;
267*7c478bd9Sstevel@tonic-gate 		break;
268*7c478bd9Sstevel@tonic-gate 	default:
269*7c478bd9Sstevel@tonic-gate 		rc = DDI_FAILURE;
270*7c478bd9Sstevel@tonic-gate 		break;
271*7c478bd9Sstevel@tonic-gate 	}
272*7c478bd9Sstevel@tonic-gate 	return (rc);
273*7c478bd9Sstevel@tonic-gate }
274