1 /* 2 * sppp_mod.c - modload support for PPP pseudo-device driver. 3 * 4 * Copyright 2009 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 #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 (int (*)())sppp_lrsrv, /* 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, NULL } /* ml_linkage, NULL-terminated list */ 179 }; 180 181 int 182 _init(void) 183 { 184 return (mod_install(&modlinkage)); 185 } 186 187 int 188 _fini(void) 189 { 190 return (mod_remove(&modlinkage)); 191 } 192 193 int 194 _info(struct modinfo *modinfop) 195 { 196 return (mod_info(&modlinkage, modinfop)); 197 } 198 199 /* 200 * _mi_driver_attach() 201 * 202 * Description: 203 * Attach a point-to-point interface to the system. 204 */ 205 static int 206 _mi_driver_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 207 { 208 if (cmd != DDI_ATTACH) { 209 return (DDI_FAILURE); 210 } 211 _mi_dip = dip; 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 _mi_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 }