tclient.c revision 7656:2621e50fdf4a
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 46static int tcli_open(dev_t *, int, int, cred_t *); 47static int tcli_close(dev_t, int, int, cred_t *); 48static int tcli_read(dev_t, struct uio *, cred_t *); 49static int tcli_write(dev_t, struct uio *, cred_t *); 50static int tcli_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 51static int tcli_attach(dev_info_t *, ddi_attach_cmd_t); 52static int tcli_detach(dev_info_t *, ddi_detach_cmd_t); 53 54static int tcli_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 55 56struct dstate { 57 dev_info_t *dip; 58 int oflag; 59}; 60 61static void *dstates; 62 63#define INST_TO_MINOR(i) (i) 64#define MINOR_TO_INST(mn) (mn) 65 66static 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 88static 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 103static struct modldrv modldrv = { 104 &mod_driverops, 105 "vhci client test driver", 106 &tcli_ops 107}; 108 109static struct modlinkage modlinkage = { 110 MODREV_1, &modldrv, NULL 111}; 112 113int 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 130int 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 142int 143_info(struct modinfo *modinfop) 144{ 145 return (mod_info(&modlinkage, modinfop)); 146} 147 148/*ARGSUSED*/ 149static int 150tcli_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*/ 183static int 184tcli_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 */ 198static int 199tcli_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*/ 215static int 216tcli_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*/ 235static int 236tcli_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*/ 255static int 256tcli_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*/ 272static int 273tcli_read(dev_t dev, struct uio *uiop, cred_t *credp) 274{ 275 return (0); 276} 277 278/*ARGSUSED*/ 279static int 280tcli_write(dev_t dev, struct uio *uiop, cred_t *credp) 281{ 282 return (0); 283} 284