Home | History | Annotate | Download | only in sppp
      1 /*
      2  * sppp_mod.c - modload support for PPP pseudo-device driver.
      3  *
      4  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
      5  * Use is subject to license terms.
      6  *
      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.
     10  *
     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
     17  *
     18  * Copyright (c) 1994 The Australian National University.
     19  * All rights reserved.
     20  *
     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
     26  * any purpose.
     27  *
     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
     32  * OF SUCH DAMAGE.
     33  *
     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,
     39  * OR MODIFICATIONS.
     40  *
     41  * This driver is derived from the original SVR4 STREAMS PPP driver
     42  * originally written by Paul Mackerras <paul.mackerras (at) cs.anu.edu.au>.
     43  *
     44  * Adi Masputra <adi.masputra (at) sun.com> rewrote and restructured the code
     45  * for improved performance and scalability.
     46  */
     47 
     48 #define	RCSID	" $Id: sppp_mod.c,v 1.0 2000/05/08 10:53:28 masputra Exp $"
     49 
     50 #include <sys/types.h>
     51 #include <sys/systm.h>
     52 #include <sys/ddi.h>
     53 #include <sys/conf.h>
     54 #include <sys/sunddi.h>
     55 #include <sys/stat.h>
     56 #include <sys/kstat.h>
     57 #include <net/pppio.h>
     58 #include <sys/modctl.h>
     59 
     60 #include "s_common.h"
     61 #include "sppp.h"
     62 
     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 **);
     66 
     67 /*
     68  * Globals for PPP multiplexer module wrapper
     69  */
     70 extern const char sppp_module_description[];
     71 static dev_info_t *_mi_dip;
     72 
     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 */
     75 
     76 static struct module_info sppp_modinfo = {
     77 	PPP_MOD_ID,		/* mi_idnum */
     78 	PPP_DRV_NAME,		/* mi_idname */
     79 	0,			/* mi_minpsz */
     80 	PPP_MAXMTU,		/* mi_maxpsz */
     81 	PPP_MI_HIWAT,		/* mi_hiwat */
     82 	PPP_MI_LOWAT		/* mi_lowat */
     83 };
     84 
     85 static struct qinit sppp_urinit = {
     86 	NULL,			/* qi_putp */
     87 	NULL,			/* qi_srvp */
     88 	sppp_open,		/* qi_qopen */
     89 	sppp_close,		/* qi_qclose */
     90 	NULL,			/* qi_qadmin */
     91 	&sppp_modinfo,		/* qi_minfo */
     92 	NULL			/* qi_mstat */
     93 };
     94 
     95 static struct qinit sppp_uwinit = {
     96 	(int (*)())sppp_uwput,	/* qi_putp */
     97 	(int (*)())sppp_uwsrv,	/* qi_srvp */
     98 	NULL,			/* qi_qopen */
     99 	NULL,			/* qi_qclose */
    100 	NULL,			/* qi_qadmin */
    101 	&sppp_modinfo,		/* qi_minfo */
    102 	NULL			/* qi_mstat */
    103 };
    104 
    105 static struct qinit sppp_lrinit = {
    106 	(int (*)())sppp_lrput,	/* qi_putp */
    107 	NULL,			/* qi_srvp */
    108 	NULL,			/* qi_qopen */
    109 	NULL,			/* qi_qclose */
    110 	NULL,			/* qi_qadmin */
    111 	&sppp_modinfo,		/* qi_minfo */
    112 	NULL			/* qi_mstat */
    113 };
    114 
    115 static struct qinit sppp_lwinit = {
    116 	NULL,			/* qi_putp */
    117 	(int (*)())sppp_lwsrv,	/* qi_srvp */
    118 	NULL,			/* qi_qopen */
    119 	NULL,			/* qi_qclose */
    120 	NULL,			/* qi_qadmin */
    121 	&sppp_modinfo,		/* qi_minfo */
    122 	NULL			/* qi_mstat */
    123 };
    124 
    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 */
    130 };
    131 
    132 /*
    133  * Descriptions for flags values in cb_flags field:
    134  *
    135  * D_MTQPAIR:
    136  *    An inner perimeter that spans the queue pair.
    137  * D_MTOUTPERIM:
    138  *    An outer perimeter that spans over all queues in the module.
    139  * D_MTOCEXCL:
    140  *    Open & close procedures are entered exclusively at outer perimeter.
    141  * D_MTPUTSHARED:
    142  *    Entry to put procedures are done with SHARED (reader) acess
    143  *    and not EXCLUSIVE (writer) access.
    144  *
    145  * Therefore:
    146  *
    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.
    150  *
    151  * 2. Put procedures are entered with SHARED (reader) access at the inner
    152  *    perimeter, and with SHARED (reader) access at the outer perimeter.
    153  *
    154  * 3. Service procedures are entered with EXCLUSIVE (writer) access at
    155  *    the inner perimeter, and with SHARED (reader) access at the
    156  *    outer perimeter.
    157  *
    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.
    163  */
    164 DDI_DEFINE_STREAM_OPS(sppp_ops,						\
    165 	nulldev, nulldev,						\
    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);
    169 
    170 static struct modldrv modldrv = {
    171 	&mod_driverops,				/* drv_modops */
    172 	(char *)sppp_module_description,	/* drv_linkinfo */
    173 	&sppp_ops				/* drv_dev_ops */
    174 };
    175 
    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 */
    180 };
    181 
    182 int
    183 _init(void)
    184 {
    185 	return (mod_install(&modlinkage));
    186 }
    187 
    188 int
    189 _fini(void)
    190 {
    191 	return (mod_remove(&modlinkage));
    192 }
    193 
    194 int
    195 _info(struct modinfo *modinfop)
    196 {
    197 	return (mod_info(&modlinkage, modinfop));
    198 }
    199 
    200 /*
    201  * _mi_driver_attach()
    202  *
    203  * Description:
    204  *    Attach a point-to-point interface to the system.
    205  */
    206 static int
    207 _mi_driver_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
    208 {
    209 	if (cmd != DDI_ATTACH) {
    210 		return (DDI_FAILURE);
    211 	}
    212 	if (ddi_create_minor_node(dip, PPP_DRV_NAME, S_IFCHR,
    213 	    0, DDI_PSEUDO, CLONE_DEV) == DDI_FAILURE) {
    214 		ddi_remove_minor_node(dip, NULL);
    215 		return (DDI_FAILURE);
    216 	}
    217 	sppp_dlpi_pinfoinit();
    218 	return (DDI_SUCCESS);
    219 }
    220 
    221 /*
    222  * _mi_driver_detach()
    223  *
    224  * Description:
    225  *    Detach an interface to the system.
    226  */
    227 static int
    228 _mi_driver_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
    229 {
    230 	if (cmd != DDI_DETACH) {
    231 		return (DDI_FAILURE);
    232 	}
    233 	ddi_remove_minor_node(dip, NULL);
    234 	return (DDI_SUCCESS);
    235 }
    236 
    237 /*
    238  * _mi_driver_info()
    239  *
    240  * Description:
    241  *    Translate "dev_t" to a pointer to the associated "dev_info_t".
    242  */
    243 /* ARGSUSED */
    244 static int
    245 _mi_driver_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
    246 	void **result)
    247 {
    248 	int	rc;
    249 
    250 	switch (infocmd) {
    251 	case DDI_INFO_DEVT2DEVINFO:
    252 		if (_mi_dip == NULL) {
    253 			rc = DDI_FAILURE;
    254 		} else {
    255 			*result = (void *)_mi_dip;
    256 			rc = DDI_SUCCESS;
    257 		}
    258 		break;
    259 	case DDI_INFO_DEVT2INSTANCE:
    260 		*result = NULL;
    261 		rc = DDI_SUCCESS;
    262 		break;
    263 	default:
    264 		rc = DDI_FAILURE;
    265 		break;
    266 	}
    267 	return (rc);
    268 }
    269