17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * sppp_mod.c - modload support for PPP pseudo-device driver.
37c478bd9Sstevel@tonic-gate  *
4f53eecf5SJames Carlson  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
57c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software and its
87c478bd9Sstevel@tonic-gate  * documentation is hereby granted, provided that the above copyright
97c478bd9Sstevel@tonic-gate  * notice appears in all copies.
107c478bd9Sstevel@tonic-gate  *
117c478bd9Sstevel@tonic-gate  * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
127c478bd9Sstevel@tonic-gate  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
137c478bd9Sstevel@tonic-gate  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
147c478bd9Sstevel@tonic-gate  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  SUN SHALL NOT BE LIABLE FOR
157c478bd9Sstevel@tonic-gate  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
167c478bd9Sstevel@tonic-gate  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
177c478bd9Sstevel@tonic-gate  *
187c478bd9Sstevel@tonic-gate  * Copyright (c) 1994 The Australian National University.
197c478bd9Sstevel@tonic-gate  * All rights reserved.
207c478bd9Sstevel@tonic-gate  *
217c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software and its
227c478bd9Sstevel@tonic-gate  * documentation is hereby granted, provided that the above copyright
237c478bd9Sstevel@tonic-gate  * notice appears in all copies.  This software is provided without any
247c478bd9Sstevel@tonic-gate  * warranty, express or implied. The Australian National University
257c478bd9Sstevel@tonic-gate  * makes no representations about the suitability of this software for
267c478bd9Sstevel@tonic-gate  * any purpose.
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
297c478bd9Sstevel@tonic-gate  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
307c478bd9Sstevel@tonic-gate  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
317c478bd9Sstevel@tonic-gate  * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
327c478bd9Sstevel@tonic-gate  * OF SUCH DAMAGE.
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
357c478bd9Sstevel@tonic-gate  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
367c478bd9Sstevel@tonic-gate  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
377c478bd9Sstevel@tonic-gate  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
387c478bd9Sstevel@tonic-gate  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
397c478bd9Sstevel@tonic-gate  * OR MODIFICATIONS.
407c478bd9Sstevel@tonic-gate  *
417c478bd9Sstevel@tonic-gate  * This driver is derived from the original SVR4 STREAMS PPP driver
427c478bd9Sstevel@tonic-gate  * originally written by Paul Mackerras <paul.mackerras@cs.anu.edu.au>.
437c478bd9Sstevel@tonic-gate  *
447c478bd9Sstevel@tonic-gate  * Adi Masputra <adi.masputra@sun.com> rewrote and restructured the code
457c478bd9Sstevel@tonic-gate  * for improved performance and scalability.
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #define	RCSID	" $Id: sppp_mod.c,v 1.0 2000/05/08 10:53:28 masputra Exp $"
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #include <sys/types.h>
517c478bd9Sstevel@tonic-gate #include <sys/systm.h>
527c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
537c478bd9Sstevel@tonic-gate #include <sys/conf.h>
547c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
557c478bd9Sstevel@tonic-gate #include <sys/stat.h>
567c478bd9Sstevel@tonic-gate #include <sys/kstat.h>
577c478bd9Sstevel@tonic-gate #include <net/pppio.h>
587c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate #include "s_common.h"
617c478bd9Sstevel@tonic-gate #include "sppp.h"
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate static int	_mi_driver_attach(dev_info_t *, ddi_attach_cmd_t);
647c478bd9Sstevel@tonic-gate static int	_mi_driver_detach(dev_info_t *, ddi_detach_cmd_t);
657c478bd9Sstevel@tonic-gate static int	_mi_driver_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate  * Globals for PPP multiplexer module wrapper
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate extern const char sppp_module_description[];
717c478bd9Sstevel@tonic-gate static dev_info_t *_mi_dip;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #define	PPP_MI_HIWAT	(PPP_MTU * 16)	/* XXX find more meaningful value */
747c478bd9Sstevel@tonic-gate #define	PPP_MI_LOWAT	(PPP_MTU * 14)	/* XXX find more meaningful value */
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static struct module_info sppp_modinfo = {
777c478bd9Sstevel@tonic-gate 	PPP_MOD_ID,		/* mi_idnum */
787c478bd9Sstevel@tonic-gate 	PPP_DRV_NAME,		/* mi_idname */
797c478bd9Sstevel@tonic-gate 	0,			/* mi_minpsz */
807c478bd9Sstevel@tonic-gate 	PPP_MAXMTU,		/* mi_maxpsz */
817c478bd9Sstevel@tonic-gate 	PPP_MI_HIWAT,		/* mi_hiwat */
827c478bd9Sstevel@tonic-gate 	PPP_MI_LOWAT		/* mi_lowat */
837c478bd9Sstevel@tonic-gate };
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate static struct qinit sppp_urinit = {
867c478bd9Sstevel@tonic-gate 	NULL,			/* qi_putp */
877c478bd9Sstevel@tonic-gate 	NULL,			/* qi_srvp */
887c478bd9Sstevel@tonic-gate 	sppp_open,		/* qi_qopen */
897c478bd9Sstevel@tonic-gate 	sppp_close,		/* qi_qclose */
907c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qadmin */
917c478bd9Sstevel@tonic-gate 	&sppp_modinfo,		/* qi_minfo */
927c478bd9Sstevel@tonic-gate 	NULL			/* qi_mstat */
937c478bd9Sstevel@tonic-gate };
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate static struct qinit sppp_uwinit = {
96*2bcc9601SToomas Soome 	sppp_uwput,		/* qi_putp */
97*2bcc9601SToomas Soome 	sppp_uwsrv,		/* qi_srvp */
987c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qopen */
997c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qclose */
1007c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qadmin */
1017c478bd9Sstevel@tonic-gate 	&sppp_modinfo,		/* qi_minfo */
1027c478bd9Sstevel@tonic-gate 	NULL			/* qi_mstat */
1037c478bd9Sstevel@tonic-gate };
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate static struct qinit sppp_lrinit = {
106*2bcc9601SToomas Soome 	sppp_lrput,		/* qi_putp */
107*2bcc9601SToomas Soome 	sppp_lrsrv,		/* qi_srvp */
1087c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qopen */
1097c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qclose */
1107c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qadmin */
1117c478bd9Sstevel@tonic-gate 	&sppp_modinfo,		/* qi_minfo */
1127c478bd9Sstevel@tonic-gate 	NULL			/* qi_mstat */
1137c478bd9Sstevel@tonic-gate };
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate static struct qinit sppp_lwinit = {
1167c478bd9Sstevel@tonic-gate 	NULL,			/* qi_putp */
117*2bcc9601SToomas Soome 	sppp_lwsrv,		/* qi_srvp */
1187c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qopen */
1197c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qclose */
1207c478bd9Sstevel@tonic-gate 	NULL,			/* qi_qadmin */
1217c478bd9Sstevel@tonic-gate 	&sppp_modinfo,		/* qi_minfo */
1227c478bd9Sstevel@tonic-gate 	NULL			/* qi_mstat */
1237c478bd9Sstevel@tonic-gate };
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate static struct streamtab sppp_tab = {
1267c478bd9Sstevel@tonic-gate 	&sppp_urinit,		/* st_rdinit */
1277c478bd9Sstevel@tonic-gate 	&sppp_uwinit,		/* st_wrinit */
1287c478bd9Sstevel@tonic-gate 	&sppp_lrinit,		/* st_muxrinit */
1297c478bd9Sstevel@tonic-gate 	&sppp_lwinit		/* st_muxwrinit */
1307c478bd9Sstevel@tonic-gate };
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate /*
1337c478bd9Sstevel@tonic-gate  * Descriptions for flags values in cb_flags field:
1347c478bd9Sstevel@tonic-gate  *
1357c478bd9Sstevel@tonic-gate  * D_MTQPAIR:
1367c478bd9Sstevel@tonic-gate  *    An inner perimeter that spans the queue pair.
1377c478bd9Sstevel@tonic-gate  * D_MTOUTPERIM:
1387c478bd9Sstevel@tonic-gate  *    An outer perimeter that spans over all queues in the module.
1397c478bd9Sstevel@tonic-gate  * D_MTOCEXCL:
1407c478bd9Sstevel@tonic-gate  *    Open & close procedures are entered exclusively at outer perimeter.
1417c478bd9Sstevel@tonic-gate  * D_MTPUTSHARED:
1427c478bd9Sstevel@tonic-gate  *    Entry to put procedures are done with SHARED (reader) acess
1437c478bd9Sstevel@tonic-gate  *    and not EXCLUSIVE (writer) access.
1447c478bd9Sstevel@tonic-gate  *
1457c478bd9Sstevel@tonic-gate  * Therefore:
1467c478bd9Sstevel@tonic-gate  *
1477c478bd9Sstevel@tonic-gate  * 1. Open and close procedures are entered with EXCLUSIVE (writer)
1487c478bd9Sstevel@tonic-gate  *    access at the inner perimeter, and with EXCLUSIVE (writer) access at
1497c478bd9Sstevel@tonic-gate  *    the outer perimeter.
1507c478bd9Sstevel@tonic-gate  *
1517c478bd9Sstevel@tonic-gate  * 2. Put procedures are entered with SHARED (reader) access at the inner
1527c478bd9Sstevel@tonic-gate  *    perimeter, and with SHARED (reader) access at the outer perimeter.
1537c478bd9Sstevel@tonic-gate  *
1547c478bd9Sstevel@tonic-gate  * 3. Service procedures are entered with EXCLUSIVE (writer) access at
1557c478bd9Sstevel@tonic-gate  *    the inner perimeter, and with SHARED (reader) access at the
1567c478bd9Sstevel@tonic-gate  *    outer perimeter.
1577c478bd9Sstevel@tonic-gate  *
1587c478bd9Sstevel@tonic-gate  * Do not attempt to modify these flags unless the entire corresponding
1597c478bd9Sstevel@tonic-gate  * driver code is changed to accomodate the newly represented MT-STREAMS
1607c478bd9Sstevel@tonic-gate  * flags. Doing so without making proper modifications to the driver code
1617c478bd9Sstevel@tonic-gate  * will severely impact the intended driver behavior, and thus may affect
1627c478bd9Sstevel@tonic-gate  * the system's stability and performance.
1637c478bd9Sstevel@tonic-gate  */
1647c478bd9Sstevel@tonic-gate DDI_DEFINE_STREAM_OPS(sppp_ops,						\
165*2bcc9601SToomas Soome     nulldev, nulldev,							\
166*2bcc9601SToomas Soome     _mi_driver_attach, _mi_driver_detach, nodev, _mi_driver_info,	\
167*2bcc9601SToomas Soome     D_NEW | D_MP | D_MTQPAIR | D_MTOUTPERIM | D_MTOCEXCL | D_MTPUTSHARED, \
168*2bcc9601SToomas Soome     &sppp_tab, ddi_quiesce_not_supported);
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
1717c478bd9Sstevel@tonic-gate 	&mod_driverops,				/* drv_modops */
1727c478bd9Sstevel@tonic-gate 	(char *)sppp_module_description,	/* drv_linkinfo */
1737c478bd9Sstevel@tonic-gate 	&sppp_ops				/* drv_dev_ops */
1747c478bd9Sstevel@tonic-gate };
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1777c478bd9Sstevel@tonic-gate 	MODREV_1,			/* ml_rev, has to be MODREV_1 */
1787c478bd9Sstevel@tonic-gate 	&modldrv,			/* ml_linkage, NULL-terminated list */
1797c478bd9Sstevel@tonic-gate 	NULL				/*  of linkage structures */
1807c478bd9Sstevel@tonic-gate };
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate int
_init(void)1837c478bd9Sstevel@tonic-gate _init(void)
1847c478bd9Sstevel@tonic-gate {
1857c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate int
_fini(void)1897c478bd9Sstevel@tonic-gate _fini(void)
1907c478bd9Sstevel@tonic-gate {
1917c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1957c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate /*
2017c478bd9Sstevel@tonic-gate  * _mi_driver_attach()
2027c478bd9Sstevel@tonic-gate  *
2037c478bd9Sstevel@tonic-gate  * Description:
2047c478bd9Sstevel@tonic-gate  *    Attach a point-to-point interface to the system.
2057c478bd9Sstevel@tonic-gate  */
2067c478bd9Sstevel@tonic-gate static int
_mi_driver_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2077c478bd9Sstevel@tonic-gate _mi_driver_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2087c478bd9Sstevel@tonic-gate {
2097c478bd9Sstevel@tonic-gate 	if (cmd != DDI_ATTACH) {
2107c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2117c478bd9Sstevel@tonic-gate 	}
212f53eecf5SJames Carlson 	_mi_dip = dip;
2137c478bd9Sstevel@tonic-gate 	if (ddi_create_minor_node(dip, PPP_DRV_NAME, S_IFCHR,
2147c478bd9Sstevel@tonic-gate 	    0, DDI_PSEUDO, CLONE_DEV) == DDI_FAILURE) {
2157c478bd9Sstevel@tonic-gate 		ddi_remove_minor_node(dip, NULL);
2167c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 	sppp_dlpi_pinfoinit();
2197c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate /*
2237c478bd9Sstevel@tonic-gate  * _mi_driver_detach()
2247c478bd9Sstevel@tonic-gate  *
2257c478bd9Sstevel@tonic-gate  * Description:
2267c478bd9Sstevel@tonic-gate  *    Detach an interface to the system.
2277c478bd9Sstevel@tonic-gate  */
2287c478bd9Sstevel@tonic-gate static int
_mi_driver_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)2297c478bd9Sstevel@tonic-gate _mi_driver_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	if (cmd != DDI_DETACH) {
2327c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2337c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate 	ddi_remove_minor_node(dip, NULL);
235f53eecf5SJames Carlson 	_mi_dip = NULL;
2367c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate /*
2407c478bd9Sstevel@tonic-gate  * _mi_driver_info()
2417c478bd9Sstevel@tonic-gate  *
2427c478bd9Sstevel@tonic-gate  * Description:
2437c478bd9Sstevel@tonic-gate  *    Translate "dev_t" to a pointer to the associated "dev_info_t".
2447c478bd9Sstevel@tonic-gate  */
2457c478bd9Sstevel@tonic-gate /* ARGSUSED */
2467c478bd9Sstevel@tonic-gate static int
_mi_driver_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)2477c478bd9Sstevel@tonic-gate _mi_driver_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
248f53eecf5SJames Carlson     void **result)
2497c478bd9Sstevel@tonic-gate {
2507c478bd9Sstevel@tonic-gate 	int	rc;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	switch (infocmd) {
2537c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
2547c478bd9Sstevel@tonic-gate 		if (_mi_dip == NULL) {
2557c478bd9Sstevel@tonic-gate 			rc = DDI_FAILURE;
2567c478bd9Sstevel@tonic-gate 		} else {
2577c478bd9Sstevel@tonic-gate 			*result = (void *)_mi_dip;
2587c478bd9Sstevel@tonic-gate 			rc = DDI_SUCCESS;
2597c478bd9Sstevel@tonic-gate 		}
2607c478bd9Sstevel@tonic-gate 		break;
2617c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
2627c478bd9Sstevel@tonic-gate 		*result = NULL;
2637c478bd9Sstevel@tonic-gate 		rc = DDI_SUCCESS;
2647c478bd9Sstevel@tonic-gate 		break;
2657c478bd9Sstevel@tonic-gate 	default:
2667c478bd9Sstevel@tonic-gate 		rc = DDI_FAILURE;
2677c478bd9Sstevel@tonic-gate 		break;
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 	return (rc);
2707c478bd9Sstevel@tonic-gate }
271