xref: /illumos-gate/usr/src/uts/common/pcmcia/pcs/pcs.c (revision 613b28719c10e84c1202c1045df44d77767de21d)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/byteorder.h>
30 #include <sys/systm.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 
34 int pcs_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
35 int pcs_attach(dev_info_t *, ddi_attach_cmd_t);
36 int pcs_detach(dev_info_t *, ddi_detach_cmd_t);
37 dev_info_t *pcs_dip;
38 
39 static struct dev_ops pcs_devops = {
40 	DEVO_REV,
41 	0,
42 	pcs_getinfo,
43 	nulldev,
44 	nulldev,
45 	pcs_attach,
46 	pcs_detach,
47 	nulldev,
48 	NULL,
49 	NULL
50 };
51 /*
52  * This is the loadable module wrapper.
53  */
54 #include <sys/modctl.h>
55 
56 extern struct mod_ops mod_driverops;
57 
58 static struct modldrv modldrv = {
59 	&mod_driverops,		/* Type of module. This one is a driver */
60 	"PCMCIA Socket Driver %I%",	/* Name of the module. */
61 	&pcs_devops,		/* driver ops */
62 };
63 
64 static struct modlinkage modlinkage = {
65 	MODREV_1, (void *)&modldrv, NULL
66 };
67 
68 struct pcs_inst {
69 	dev_info_t *dip;
70 } *pcs_instances;
71 
72 int
73 _init()
74 {
75 	int ret;
76 	if ((ret = ddi_soft_state_init((void **)&pcs_instances,
77 					sizeof (struct pcs_inst), 1)) != 0)
78 		return (ret);
79 	if ((ret = mod_install(&modlinkage)) != 0) {
80 		ddi_soft_state_fini((void **)&pcs_instances);
81 	}
82 	return (ret);
83 }
84 
85 int
86 _fini()
87 {
88 	int ret;
89 	ret = mod_remove(&modlinkage);
90 	if (ret == 0) {
91 		ddi_soft_state_fini((void **)&pcs_instances);
92 	}
93 	return (ret);
94 }
95 
96 int
97 _info(struct modinfo *modinfop)
98 {
99 	return (mod_info(&modlinkage, modinfop));
100 }
101 
102 int
103 pcs_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
104 {
105 	int error = DDI_SUCCESS;
106 	int inum;
107 	struct pcs_inst *inst;
108 #ifdef lint
109 	dip = dip;
110 #endif
111 
112 	switch (cmd) {
113 	case DDI_INFO_DEVT2DEVINFO:
114 		inum = getminor((dev_t)arg);
115 		inst = (struct pcs_inst *)ddi_get_soft_state(pcs_instances,
116 								inum);
117 		if (inst == NULL)
118 			error = DDI_FAILURE;
119 		else
120 			*result = inst->dip;
121 		break;
122 	case DDI_INFO_DEVT2INSTANCE:
123 		inum = getminor((dev_t)arg);
124 		inst = (struct pcs_inst *)ddi_get_soft_state(pcs_instances,
125 								inum);
126 		if (inst == NULL)
127 			error = DDI_FAILURE;
128 		else
129 			*result = (void *)(uintptr_t)inum;
130 		break;
131 	default:
132 		error = DDI_FAILURE;
133 	}
134 	return (error);
135 }
136 
137 int
138 pcs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
139 {
140 	int ret = DDI_SUCCESS;
141 	int inum;
142 	struct pcs_inst *inst;
143 
144 	switch (cmd) {
145 	case DDI_RESUME:
146 		return (DDI_SUCCESS);
147 	case DDI_ATTACH:
148 		break;
149 	default:
150 		return (DDI_FAILURE);
151 	}
152 
153 	inum = ddi_get_instance(dip);
154 
155 	if (ddi_soft_state_zalloc(pcs_instances, inum) == DDI_SUCCESS) {
156 		inst = (struct pcs_inst *)ddi_get_soft_state(pcs_instances,
157 								inum);
158 		if (inst == NULL)
159 			ret = DDI_FAILURE;
160 		else
161 			inst->dip = dip;
162 	}
163 
164 	return (ret);
165 }
166 
167 int
168 pcs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
169 {
170 	switch (cmd) {
171 	case DDI_DETACH:
172 		ddi_soft_state_free(pcs_instances, ddi_get_instance(dip));
173 		return (DDI_SUCCESS);
174 
175 	case DDI_SUSPEND:
176 	case DDI_PM_SUSPEND:
177 		return (DDI_SUCCESS);
178 	default:
179 		break;
180 	}
181 	return (DDI_FAILURE);
182 }
183