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