xref: /illumos-gate/usr/src/uts/common/io/tclient.c (revision 88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98)
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