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