1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * generic mpxio leaf driver 31 */ 32 #include <sys/types.h> 33 #include <sys/param.h> 34 #include <sys/errno.h> 35 #include <sys/uio.h> 36 #include <sys/buf.h> 37 #include <sys/modctl.h> 38 #include <sys/open.h> 39 #include <sys/kmem.h> 40 #include <sys/conf.h> 41 #include <sys/cmn_err.h> 42 #include <sys/stat.h> 43 #include <sys/ddi.h> 44 #include <sys/sunddi.h> 45 #include <sys/sunndi.h> 46 47 48 static int tcli_open(dev_t *, int, int, cred_t *); 49 static int tcli_close(dev_t, int, int, cred_t *); 50 static int tcli_read(dev_t, struct uio *, cred_t *); 51 static int tcli_write(dev_t, struct uio *, cred_t *); 52 static int tcli_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 53 static int tcli_attach(dev_info_t *, ddi_attach_cmd_t); 54 static int tcli_detach(dev_info_t *, ddi_detach_cmd_t); 55 56 static int tcli_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 57 58 struct dstate { 59 dev_info_t *dip; 60 int oflag; 61 }; 62 63 static void *dstates; 64 65 #define INST_TO_MINOR(i) (i) 66 #define MINOR_TO_INST(mn) (mn) 67 68 static struct cb_ops tcli_cb_ops = { 69 tcli_open, /* open */ 70 tcli_close, /* close */ 71 nodev, /* strategy */ 72 nodev, /* print */ 73 nodev, /* dump */ 74 tcli_read, /* read */ 75 tcli_write, /* write */ 76 tcli_ioctl, /* ioctl */ 77 nodev, /* devmap */ 78 nodev, /* mmap */ 79 nodev, /* segmap */ 80 nochpoll, /* poll */ 81 ddi_prop_op, /* prop_op */ 82 NULL, /* streamtab */ 83 D_NEW | D_MP | D_HOTPLUG, /* flag */ 84 CB_REV, /* cb_rev */ 85 nodev, /* aread */ 86 nodev /* awrite */ 87 }; 88 89 90 static struct dev_ops tcli_ops = { 91 DEVO_REV, /* devo_rev */ 92 0, /* refcnt */ 93 tcli_info, /* getinfo */ 94 nulldev, /* identify */ 95 nulldev, /* probe */ 96 tcli_attach, /* attach */ 97 tcli_detach, /* detach */ 98 nodev, /* reset */ 99 &tcli_cb_ops, /* driver ops */ 100 (struct bus_ops *)0, /* bus ops */ 101 NULL /* power */ 102 }; 103 104 static struct modldrv modldrv = { 105 &mod_driverops, 106 "vhci client test driver %I%", 107 &tcli_ops 108 }; 109 110 static struct modlinkage modlinkage = { 111 MODREV_1, &modldrv, NULL 112 }; 113 114 int 115 _init(void) 116 { 117 int e; 118 119 if ((e = ddi_soft_state_init(&dstates, 120 sizeof (struct dstate), 0)) != 0) { 121 return (e); 122 } 123 124 if ((e = mod_install(&modlinkage)) != 0) { 125 ddi_soft_state_fini(&dstates); 126 } 127 128 return (e); 129 } 130 131 int 132 _fini(void) 133 { 134 int e; 135 136 if ((e = mod_remove(&modlinkage)) != 0) { 137 return (e); 138 } 139 ddi_soft_state_fini(&dstates); 140 return (e); 141 } 142 143 int 144 _info(struct modinfo *modinfop) 145 { 146 return (mod_info(&modlinkage, modinfop)); 147 } 148 149 /*ARGSUSED*/ 150 static int 151 tcli_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 152 { 153 int instance = ddi_get_instance(devi); 154 struct dstate *dstatep; 155 int rval; 156 157 if (cmd != DDI_ATTACH) 158 return (DDI_SUCCESS); 159 160 if (ddi_soft_state_zalloc(dstates, instance) != DDI_SUCCESS) { 161 cmn_err(CE_CONT, "%s%d: can't allocate state\n", 162 ddi_get_name(devi), instance); 163 return (DDI_FAILURE); 164 } 165 166 dstatep = ddi_get_soft_state(dstates, instance); 167 dstatep->dip = devi; 168 169 rval = ddi_create_minor_node(devi, "client", S_IFCHR, 170 (INST_TO_MINOR(instance)), DDI_PSEUDO, NULL); 171 if (rval == DDI_FAILURE) { 172 ddi_remove_minor_node(devi, NULL); 173 ddi_soft_state_free(dstates, instance); 174 cmn_err(CE_WARN, "%s%d: can't create minor nodes", 175 ddi_get_name(devi), instance); 176 return (DDI_FAILURE); 177 } 178 179 ddi_report_dev(devi); 180 return (DDI_SUCCESS); 181 } 182 183 /*ARGSUSED*/ 184 static int 185 tcli_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 186 { 187 int instance; 188 189 if (cmd != DDI_DETACH) 190 return (DDI_SUCCESS); 191 192 ddi_remove_minor_node(devi, NULL); 193 instance = ddi_get_instance(devi); 194 ddi_soft_state_free(dstates, instance); 195 return (DDI_SUCCESS); 196 } 197 198 /* ARGSUSED */ 199 static int 200 tcli_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 201 { 202 dev_t dev; 203 int instance; 204 205 if (infocmd != DDI_INFO_DEVT2INSTANCE) 206 return (DDI_FAILURE); 207 208 dev = (dev_t)arg; 209 instance = MINOR_TO_INST(getminor(dev)); 210 *result = (void *)(uintptr_t)instance; 211 return (DDI_SUCCESS); 212 } 213 214 215 /*ARGSUSED*/ 216 static int 217 tcli_open(dev_t *devp, int flag, int otyp, cred_t *cred) 218 { 219 minor_t minor; 220 struct dstate *dstatep; 221 222 if (otyp != OTYP_BLK && otyp != OTYP_CHR) 223 return (EINVAL); 224 225 minor = getminor(*devp); 226 if ((dstatep = ddi_get_soft_state(dstates, 227 MINOR_TO_INST(minor))) == NULL) 228 return (ENXIO); 229 230 dstatep->oflag = 1; 231 232 return (0); 233 } 234 235 /*ARGSUSED*/ 236 static int 237 tcli_close(dev_t dev, int flag, int otyp, cred_t *cred) 238 { 239 struct dstate *dstatep; 240 minor_t minor = getminor(dev); 241 242 if (otyp != OTYP_BLK && otyp != OTYP_CHR) 243 return (EINVAL); 244 245 dstatep = ddi_get_soft_state(dstates, MINOR_TO_INST(minor)); 246 247 if (dstatep == NULL) 248 return (ENXIO); 249 250 dstatep->oflag = 0; 251 252 return (0); 253 } 254 255 /*ARGSUSED*/ 256 static int 257 tcli_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 258 int *rvalp) 259 { 260 struct dstate *dstatep; 261 int instance; 262 263 instance = MINOR_TO_INST(getminor(dev)); 264 dstatep = ddi_get_soft_state(dstates, instance); 265 266 if (dstatep == NULL) 267 return (ENXIO); 268 269 return (0); 270 } 271 272 /*ARGSUSED*/ 273 static int 274 tcli_read(dev_t dev, struct uio *uiop, cred_t *credp) 275 { 276 return (0); 277 } 278 279 /*ARGSUSED*/ 280 static int 281 tcli_write(dev_t dev, struct uio *uiop, cred_t *credp) 282 { 283 return (0); 284 } 285