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