pcs.c revision 7656:2621e50fdf4a
1178479Sjb/*
2178479Sjb * CDDL HEADER START
3178479Sjb *
4178479Sjb * The contents of this file are subject to the terms of the
5178479Sjb * Common Development and Distribution License (the "License").
6178479Sjb * You may not use this file except in compliance with the License.
7178479Sjb *
8178479Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9178479Sjb * or http://www.opensolaris.org/os/licensing.
10178479Sjb * See the License for the specific language governing permissions
11178479Sjb * and limitations under the License.
12178479Sjb *
13178479Sjb * When distributing Covered Code, include this CDDL HEADER in each
14178479Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15178479Sjb * If applicable, add the following below this CDDL HEADER, with the
16178479Sjb * fields enclosed by brackets "[]" replaced with your own identifying
17178479Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
18178479Sjb *
19178479Sjb * CDDL HEADER END
20178479Sjb */
21178479Sjb/*
22178479Sjb * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23178573Sjb * Use is subject to license terms.
24178479Sjb */
25178479Sjb
26178479Sjb
27178479Sjb#include <sys/types.h>
28178479Sjb#include <sys/byteorder.h>
29178479Sjb#include <sys/systm.h>
30178479Sjb#include <sys/ddi.h>
31178479Sjb#include <sys/sunddi.h>
32178479Sjb
33178573Sjbint pcs_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
34178479Sjbint pcs_attach(dev_info_t *, ddi_attach_cmd_t);
35178573Sjbint pcs_detach(dev_info_t *, ddi_detach_cmd_t);
36178573Sjbdev_info_t *pcs_dip;
37178573Sjb
38178479Sjbstatic struct dev_ops pcs_devops = {
39178479Sjb	DEVO_REV,
40178479Sjb	0,
41178573Sjb	pcs_getinfo,
42178479Sjb	nulldev,
43178573Sjb	nulldev,
44178479Sjb	pcs_attach,
45178479Sjb	pcs_detach,
46178479Sjb	nulldev,
47178479Sjb	NULL,
48178479Sjb	NULL,
49178479Sjb	NULL,
50178573Sjb	ddi_quiesce_not_needed,		/* quiesce */
51178479Sjb};
52178573Sjb/*
53178573Sjb * This is the loadable module wrapper.
54211554Srpaulo */
55211554Srpaulo#include <sys/modctl.h>
56211554Srpaulo
57178573Sjbextern struct mod_ops mod_driverops;
58178479Sjb
59178479Sjbstatic struct modldrv modldrv = {
60178479Sjb	&mod_driverops,		/* Type of module. This one is a driver */
61178479Sjb	"PCMCIA Socket Driver",	/* Name of the module. */
62178479Sjb	&pcs_devops,		/* driver ops */
63178479Sjb};
64178479Sjb
65178479Sjbstatic struct modlinkage modlinkage = {
66178479Sjb	MODREV_1, (void *)&modldrv, NULL
67178479Sjb};
68178479Sjb
69178479Sjbstruct pcs_inst {
70178479Sjb	dev_info_t *dip;
71178479Sjb} *pcs_instances;
72178479Sjb
73178479Sjbint
74178479Sjb_init()
75178479Sjb{
76178479Sjb	int ret;
77178479Sjb	if ((ret = ddi_soft_state_init((void **)&pcs_instances,
78178479Sjb	    sizeof (struct pcs_inst), 1)) != 0)
79178479Sjb		return (ret);
80178479Sjb	if ((ret = mod_install(&modlinkage)) != 0) {
81178479Sjb		ddi_soft_state_fini((void **)&pcs_instances);
82178479Sjb	}
83178479Sjb	return (ret);
84178479Sjb}
85178479Sjb
86178479Sjbint
87178479Sjb_fini()
88178479Sjb{
89178479Sjb	int ret;
90178479Sjb	ret = mod_remove(&modlinkage);
91178479Sjb	if (ret == 0) {
92178479Sjb		ddi_soft_state_fini((void **)&pcs_instances);
93178479Sjb	}
94178479Sjb	return (ret);
95178479Sjb}
96178479Sjb
97178479Sjbint
98178479Sjb_info(struct modinfo *modinfop)
99178479Sjb{
100178479Sjb	return (mod_info(&modlinkage, modinfop));
101178479Sjb}
102178479Sjb
103178479Sjbint
104178479Sjbpcs_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
105178479Sjb{
106178479Sjb	int error = DDI_SUCCESS;
107178479Sjb	int inum;
108178479Sjb	struct pcs_inst *inst;
109178479Sjb#ifdef lint
110178479Sjb	dip = dip;
111178479Sjb#endif
112178479Sjb
113178479Sjb	switch (cmd) {
114178479Sjb	case DDI_INFO_DEVT2DEVINFO:
115178479Sjb		inum = getminor((dev_t)arg);
116178479Sjb		inst = (struct pcs_inst *)ddi_get_soft_state(pcs_instances,
117178479Sjb		    inum);
118178479Sjb		if (inst == NULL)
119178479Sjb			error = DDI_FAILURE;
120178479Sjb		else
121178479Sjb			*result = inst->dip;
122178479Sjb		break;
123178479Sjb	case DDI_INFO_DEVT2INSTANCE:
124178479Sjb		inum = getminor((dev_t)arg);
125178479Sjb		inst = (struct pcs_inst *)ddi_get_soft_state(pcs_instances,
126178479Sjb		    inum);
127178479Sjb		if (inst == NULL)
128178479Sjb			error = DDI_FAILURE;
129178479Sjb		else
130178479Sjb			*result = (void *)(uintptr_t)inum;
131178479Sjb		break;
132178479Sjb	default:
133178479Sjb		error = DDI_FAILURE;
134178479Sjb	}
135178479Sjb	return (error);
136178479Sjb}
137178479Sjb
138178479Sjbint
139178479Sjbpcs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
140178479Sjb{
141178479Sjb	int ret = DDI_SUCCESS;
142178479Sjb	int inum;
143178479Sjb	struct pcs_inst *inst;
144178479Sjb
145178479Sjb	switch (cmd) {
146178479Sjb	case DDI_RESUME:
147178479Sjb		return (DDI_SUCCESS);
148178479Sjb	case DDI_ATTACH:
149178479Sjb		break;
150178479Sjb	default:
151178479Sjb		return (DDI_FAILURE);
152178479Sjb	}
153178479Sjb
154178479Sjb	inum = ddi_get_instance(dip);
155178479Sjb
156178479Sjb	if (ddi_soft_state_zalloc(pcs_instances, inum) == DDI_SUCCESS) {
157178479Sjb		inst = (struct pcs_inst *)ddi_get_soft_state(pcs_instances,
158178479Sjb		    inum);
159178479Sjb		if (inst == NULL)
160178479Sjb			ret = DDI_FAILURE;
161178479Sjb		else
162178479Sjb			inst->dip = dip;
163178479Sjb	}
164178479Sjb
165178479Sjb	return (ret);
166178479Sjb}
167178479Sjb
168178479Sjbint
169178479Sjbpcs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
170178479Sjb{
171178479Sjb	switch (cmd) {
172178479Sjb	case DDI_DETACH:
173178479Sjb		ddi_soft_state_free(pcs_instances, ddi_get_instance(dip));
174178479Sjb		return (DDI_SUCCESS);
175178479Sjb
176178479Sjb	case DDI_SUSPEND:
177178479Sjb	case DDI_PM_SUSPEND:
178178479Sjb		return (DDI_SUCCESS);
179178479Sjb	default:
180178479Sjb		break;
181178479Sjb	}
182178479Sjb	return (DDI_FAILURE);
183178479Sjb}
184178479Sjb