1 /* 2 * sppp_mod.c - modload support for PPP pseudo-device driver. 3 * 4 * Copyright 2007 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@cs.anu.edu.au>. 43 * 44 * Adi Masputra <adi.masputra@sun.com> rewrote and restructured the code 45 * for improved performance and scalability. 46 */ 47 48 #pragma ident "%Z%%M% %I% %E% SMI" 49 #define RCSID " $Id: sppp_mod.c,v 1.0 2000/05/08 10:53:28 masputra Exp $" 50 51 #include <sys/types.h> 52 #include <sys/systm.h> 53 #include <sys/ddi.h> 54 #include <sys/conf.h> 55 #include <sys/sunddi.h> 56 #include <sys/stat.h> 57 #include <sys/kstat.h> 58 #include <net/pppio.h> 59 #include <sys/modctl.h> 60 61 #include "s_common.h" 62 #include "sppp.h" 63 64 static int _mi_driver_attach(dev_info_t *, ddi_attach_cmd_t); 65 static int _mi_driver_detach(dev_info_t *, ddi_detach_cmd_t); 66 static int _mi_driver_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 67 68 /* 69 * Globals for PPP multiplexer module wrapper 70 */ 71 extern const char sppp_module_description[]; 72 static dev_info_t *_mi_dip; 73 74 #define PPP_MI_HIWAT (PPP_MTU * 16) /* XXX find more meaningful value */ 75 #define PPP_MI_LOWAT (PPP_MTU * 14) /* XXX find more meaningful value */ 76 77 static struct module_info sppp_modinfo = { 78 PPP_MOD_ID, /* mi_idnum */ 79 PPP_DRV_NAME, /* mi_idname */ 80 0, /* mi_minpsz */ 81 PPP_MAXMTU, /* mi_maxpsz */ 82 PPP_MI_HIWAT, /* mi_hiwat */ 83 PPP_MI_LOWAT /* mi_lowat */ 84 }; 85 86 static struct qinit sppp_urinit = { 87 NULL, /* qi_putp */ 88 NULL, /* qi_srvp */ 89 sppp_open, /* qi_qopen */ 90 sppp_close, /* qi_qclose */ 91 NULL, /* qi_qadmin */ 92 &sppp_modinfo, /* qi_minfo */ 93 NULL /* qi_mstat */ 94 }; 95 96 static struct qinit sppp_uwinit = { 97 (int (*)())sppp_uwput, /* qi_putp */ 98 (int (*)())sppp_uwsrv, /* qi_srvp */ 99 NULL, /* qi_qopen */ 100 NULL, /* qi_qclose */ 101 NULL, /* qi_qadmin */ 102 &sppp_modinfo, /* qi_minfo */ 103 NULL /* qi_mstat */ 104 }; 105 106 static struct qinit sppp_lrinit = { 107 (int (*)())sppp_lrput, /* qi_putp */ 108 NULL, /* qi_srvp */ 109 NULL, /* qi_qopen */ 110 NULL, /* qi_qclose */ 111 NULL, /* qi_qadmin */ 112 &sppp_modinfo, /* qi_minfo */ 113 NULL /* qi_mstat */ 114 }; 115 116 static struct qinit sppp_lwinit = { 117 NULL, /* qi_putp */ 118 (int (*)())sppp_lwsrv, /* qi_srvp */ 119 NULL, /* qi_qopen */ 120 NULL, /* qi_qclose */ 121 NULL, /* qi_qadmin */ 122 &sppp_modinfo, /* qi_minfo */ 123 NULL /* qi_mstat */ 124 }; 125 126 static struct streamtab sppp_tab = { 127 &sppp_urinit, /* st_rdinit */ 128 &sppp_uwinit, /* st_wrinit */ 129 &sppp_lrinit, /* st_muxrinit */ 130 &sppp_lwinit /* st_muxwrinit */ 131 }; 132 133 /* 134 * Descriptions for flags values in cb_flags field: 135 * 136 * D_MTQPAIR: 137 * An inner perimeter that spans the queue pair. 138 * D_MTOUTPERIM: 139 * An outer perimeter that spans over all queues in the module. 140 * D_MTOCEXCL: 141 * Open & close procedures are entered exclusively at outer perimeter. 142 * D_MTPUTSHARED: 143 * Entry to put procedures are done with SHARED (reader) acess 144 * and not EXCLUSIVE (writer) access. 145 * 146 * Therefore: 147 * 148 * 1. Open and close procedures are entered with EXCLUSIVE (writer) 149 * access at the inner perimeter, and with EXCLUSIVE (writer) access at 150 * the outer perimeter. 151 * 152 * 2. Put procedures are entered with SHARED (reader) access at the inner 153 * perimeter, and with SHARED (reader) access at the outer perimeter. 154 * 155 * 3. Service procedures are entered with EXCLUSIVE (writer) access at 156 * the inner perimeter, and with SHARED (reader) access at the 157 * outer perimeter. 158 * 159 * Do not attempt to modify these flags unless the entire corresponding 160 * driver code is changed to accomodate the newly represented MT-STREAMS 161 * flags. Doing so without making proper modifications to the driver code 162 * will severely impact the intended driver behavior, and thus may affect 163 * the system's stability and performance. 164 */ 165 DDI_DEFINE_STREAM_OPS(sppp_ops, \ 166 nulldev, nulldev, \ 167 _mi_driver_attach, _mi_driver_detach, nodev, _mi_driver_info, \ 168 D_NEW | D_MP | D_MTQPAIR | D_MTOUTPERIM | D_MTOCEXCL | D_MTPUTSHARED, \ 169 &sppp_tab); 170 171 static struct modldrv modldrv = { 172 &mod_driverops, /* drv_modops */ 173 (char *)sppp_module_description, /* drv_linkinfo */ 174 &sppp_ops /* drv_dev_ops */ 175 }; 176 177 static struct modlinkage modlinkage = { 178 MODREV_1, /* ml_rev, has to be MODREV_1 */ 179 &modldrv, /* ml_linkage, NULL-terminated list */ 180 NULL /* of linkage structures */ 181 }; 182 183 int 184 _init(void) 185 { 186 return (mod_install(&modlinkage)); 187 } 188 189 int 190 _fini(void) 191 { 192 return (mod_remove(&modlinkage)); 193 } 194 195 int 196 _info(struct modinfo *modinfop) 197 { 198 return (mod_info(&modlinkage, modinfop)); 199 } 200 201 /* 202 * _mi_driver_attach() 203 * 204 * Description: 205 * Attach a point-to-point interface to the system. 206 */ 207 static int 208 _mi_driver_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 209 { 210 if (cmd != DDI_ATTACH) { 211 return (DDI_FAILURE); 212 } 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); 217 } 218 sppp_dlpi_pinfoinit(); 219 return (DDI_SUCCESS); 220 } 221 222 /* 223 * _mi_driver_detach() 224 * 225 * Description: 226 * Detach an interface to the system. 227 */ 228 static int 229 _mi_driver_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 230 { 231 if (cmd != DDI_DETACH) { 232 return (DDI_FAILURE); 233 } 234 ddi_remove_minor_node(dip, NULL); 235 return (DDI_SUCCESS); 236 } 237 238 /* 239 * _mi_driver_info() 240 * 241 * Description: 242 * Translate "dev_t" to a pointer to the associated "dev_info_t". 243 */ 244 /* ARGSUSED */ 245 static int 246 _mi_driver_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 247 void **result) 248 { 249 int rc; 250 251 switch (infocmd) { 252 case DDI_INFO_DEVT2DEVINFO: 253 if (_mi_dip == NULL) { 254 rc = DDI_FAILURE; 255 } else { 256 *result = (void *)_mi_dip; 257 rc = DDI_SUCCESS; 258 } 259 break; 260 case DDI_INFO_DEVT2INSTANCE: 261 *result = NULL; 262 rc = DDI_SUCCESS; 263 break; 264 default: 265 rc = DDI_FAILURE; 266 break; 267 } 268 return (rc); 269 } 270