1ddi_soft_state(9F) Kernel Functions for Drivers ddi_soft_state(9F)
2
3
4
6 ddi_soft_state, ddi_get_soft_state, ddi_soft_state_fini,
7 ddi_soft_state_free, ddi_soft_state_init, ddi_soft_state_zalloc -
8 driver soft state utility routines
9
11 #include <sys/ddi.h>
12 #include <sys/sunddi.h>
13
14
15
16 void *ddi_get_soft_state(void *state, int item);
17
18
19 void ddi_soft_state_fini(void **state_p);
20
21
22 void ddi_soft_state_free(void *state, int item);
23
24
25 int ddi_soft_state_init(void **state_p, size_t size, size_t n_items);
26
27
28 int ddi_soft_state_zalloc(void *state, int item);
29
30
32 Solaris DDI specific (Solaris DDI).
33
35 state_p Address of the opaque state pointer which will be initial‐
36 ized by ddi_soft_state_init() to point to implementation
37 dependent data.
38
39
40 size Size of the item which will be allocated by subsequent calls
41 to ddi_soft_state_zalloc().
42
43
44 n_items A hint of the number of items which will be preallocated;
45 zero is allowed.
46
47
48 state An opaque pointer to implementation-dependent data that
49 describes the soft state.
50
51
52 item The item number for the state structure; usually the
53 instance number of the associated devinfo node.
54
55
57 Most device drivers maintain state information with each instance of
58 the device they control; for example, a soft copy of a device control
59 register, a mutex that must be held while accessing a piece of hard‐
60 ware, a partition table, or a unit structure. These utility routines
61 are intended to help device drivers manage the space used by the driver
62 to hold such state information.
63
64
65 For example, if the driver holds the state of each instance in a single
66 state structure, these routines can be used to dynamically allocate and
67 deallocate a separate structure for each instance of the driver as the
68 instance is attached and detached.
69
70
71 To use the routines, the driver writer needs to declare a state
72 pointer, state_p, which the implementation uses as a place to hang a
73 set of per-driver structures; everything else is managed by these rou‐
74 tines.
75
76
77 The routine ddi_soft_state_init() is usually called in the driver's
78 _init(9E) routine to initialize the state pointer, set the size of the
79 soft state structure, and to allow the driver to pre-allocate a given
80 number of such structures if required.
81
82
83 The routine ddi_soft_state_zalloc() is usually called in the driver's
84 attach(9E) routine. The routine is passed an item number which is used
85 to refer to the structure in subsequent calls to ddi_get_soft_state()
86 and ddi_soft_state_free(). The item number is usually just the instance
87 number of the devinfo node, obtained with ddi_get_instance(9F). The
88 routine attempts to allocate space for the new structure, and if the
89 space allocation was successful, DDI_SUCCESS is returned to the caller.
90 Returned memory is zeroed.
91
92
93 A pointer to the space previously allocated for a soft state structure
94 can be obtained by calling ddi_get_soft_state() with the appropriate
95 item number.
96
97
98 The space used by a given soft state structure can be returned to the
99 system using ddi_soft_state_free(). This routine is usually called from
100 the driver's detach(9E) entry point.
101
102
103 The space used by all the soft state structures allocated on a given
104 state pointer, together with the housekeeping information used by the
105 implementation can be returned to the system using
106 ddi_soft_state_fini(). This routine can be called from the driver's
107 _fini(9E) routine.
108
109
110 The ddi_soft_state_zalloc(), ddi_soft_state_free() and
111 ddi_get_soft_state() routines coordinate access to the underlying data
112 structures in an MT-safe fashion, thus no additional locks should be
113 necessary.
114
116 ddi_get_soft_state()
117
118 NULL The requested state structure was not allocated at the time
119 of the call.
120
121
122 pointer The pointer to the state structure.
123
124
125
126 ddi_soft_state_init()
127
128 0 The allocation was successful.
129
130
131 EINVAL Either the size parameter was zero, or the state_p parameter
132 was invalid.
133
134
135
136 ddi_soft_state_zalloc()
137
138 DDI_SUCCESS The allocation was successful.
139
140
141 DDI_FAILURE The routine failed to allocate the storage required;
142 either the state parameter was invalid, the item number
143 was negative, or an attempt was made to allocate an item
144 number that was already allocated.
145
146
148 The ddi_soft_state_init() and ddi_soft_state_alloc() functions can be
149 called from user or kernel context only, since they may internally call
150 kmem_zalloc(9F) with the KM_SLEEP flag.
151
152
153 The ddi_soft_state_fini(), ddi_soft_state_free() and
154 ddi_get_soft_state() routines can be called from any driver context.
155
157 Example 1 Creating and Removing Data Structures
158
159
160 The following example shows how the routines described above can be
161 used in terms of the driver entry points of a character-only driver.
162 The example concentrates on the portions of the code that deal with
163 creating and removing the driver's data structures.
164
165
166 typedef struct {
167 volatile caddr_t *csr; /* device registers */
168 kmutex_t csr_mutex; /* protects 'csr' field */
169 unsigned int state;
170 dev_info_t *dip; /* back pointer to devinfo */
171 } devstate_t;
172 static void *statep;
173
174 int
175 _init(void)
176 {
177 int error;
178
179 error = ddi_soft_state_init(&statep, sizeof (devstate_t), 0);
180 if (error != 0)
181 return (error);
182 if ((error = mod_install(&modlinkage)) != 0)
183 ddi_soft_state_fini(&statep);
184 return (error);
185 }
186
187 int
188 _fini(void)
189 {
190 int error;
191
192 if ((error = mod_remove(&modlinkage)) != 0)
193 return (error);
194 ddi_soft_state_fini(&statep);
195 return (0);
196 }
197
198 static int
199 xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
200 {
201 int instance;
202 devstate_t *softc;
203
204 switch (cmd) {
205 case DDI_ATTACH:
206 instance = ddi_get_instance(dip);
207 if (ddi_soft_state_zalloc(statep, instance) != DDI_SUCCESS)
208 return (DDI_FAILURE);
209 softc = ddi_get_soft_state(statep, instance);
210 softc->dip = dip;
211 ...
212 return (DDI_SUCCESS);
213 default:
214 return (DDI_FAILURE);
215 }
216 }
217
218 static int
219 xxdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
220 {
221 int instance;
222
223 switch (cmd) {
224
225 case DDI_DETACH:
226 instance = ddi_get_instance(dip);
227 ...
228 ddi_soft_state_free(statep, instance);
229 return (DDI_SUCCESS);
230
231 default:
232 return (DDI_FAILURE);
233 }
234 }
235
236 static int
237 xxopen(dev_t *devp, int flag, int otyp, cred_t *cred_p)
238 {
239 devstate_t *softc;
240 int instance;
241
242 instance = getminor(*devp);
243 if ((softc = ddi_get_soft_state(statep, instance)) == NULL)
244 return (ENXIO);
245 ...
246 softc->state |= XX_IN_USE;
247 ...
248 return (0);
249 }
250
251
253 _fini(9E), _init(9E), attach(9E), detach(9E), ddi_get_instance(9F),
254 getminor(9F), kmem_zalloc(9F)
255
256
257 Writing Device Drivers
258
260 There is no attempt to validate the item parameter given to
261 ddi_soft_state_zalloc() other than it must be a positive signed inte‐
262 ger. Therefore very large item numbers may cause the driver to hang
263 forever waiting for virtual memory resources that can never be satis‐
264 fied.
265
267 If necessary, a hierarchy of state structures can be constructed by
268 embedding state pointers in higher order state structures.
269
271 All of the messages described below usually indicate bugs in the driver
272 and should not appear in normal operation of the system.
273
274 WARNING: ddi_soft_state_zalloc: bad handle
275 WARNING: ddi_soft_state_free: bad handle
276 WARNING: ddi_soft_state_fini: bad handle
277
278
279
280 The implementation-dependent information kept in the state variable is
281 corrupt.
282
283 WARNING: ddi_soft_state_free: null handle
284 WARNING: ddi_soft_state_fini: null handle
285
286
287
288 The routine has been passed a null or corrupt state pointer. Check
289 that ddi_soft_state_init() has been called.
290
291 WARNING: ddi_soft_state_free: item %d not in range [0..%d]
292
293
294
295 The routine has been asked to free an item which was never allocated.
296 The message prints out the invalid item number and the acceptable
297 range.
298
299
300
301SunOS 5.11 16 Jan 2006 ddi_soft_state(9F)