Mon Apr 13 22:26:20 2015 UTC ()
Add required dependency on i2cexec


(pgoyette)
diff -r1.48 -r1.49 src/sys/dev/i2c/i2c.c

cvs diff -r1.48 -r1.49 src/sys/dev/i2c/i2c.c (switch to unified diff)

--- src/sys/dev/i2c/i2c.c 2015/04/04 15:16:54 1.48
+++ src/sys/dev/i2c/i2c.c 2015/04/13 22:26:20 1.49
@@ -1,608 +1,608 @@ @@ -1,608 +1,608 @@
1/* $NetBSD: i2c.c,v 1.48 2015/04/04 15:16:54 christos Exp $ */ 1/* $NetBSD: i2c.c,v 1.49 2015/04/13 22:26:20 pgoyette Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2003 Wasabi Systems, Inc. 4 * Copyright (c) 2003 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by 19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc. 20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior 22 * or promote products derived from this software without specific prior
23 * written permission. 23 * written permission.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37 37
38#ifdef _KERNEL_OPT 38#ifdef _KERNEL_OPT
39#include "opt_i2c.h" 39#include "opt_i2c.h"
40#endif 40#endif
41 41
42#include <sys/cdefs.h> 42#include <sys/cdefs.h>
43__KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.48 2015/04/04 15:16:54 christos Exp $"); 43__KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.49 2015/04/13 22:26:20 pgoyette Exp $");
44 44
45#include <sys/param.h> 45#include <sys/param.h>
46#include <sys/systm.h> 46#include <sys/systm.h>
47#include <sys/device.h> 47#include <sys/device.h>
48#include <sys/event.h> 48#include <sys/event.h>
49#include <sys/conf.h> 49#include <sys/conf.h>
50#include <sys/malloc.h> 50#include <sys/malloc.h>
51#include <sys/kmem.h> 51#include <sys/kmem.h>
52#include <sys/kthread.h> 52#include <sys/kthread.h>
53#include <sys/proc.h> 53#include <sys/proc.h>
54#include <sys/kernel.h> 54#include <sys/kernel.h>
55#include <sys/fcntl.h> 55#include <sys/fcntl.h>
56#include <sys/module.h> 56#include <sys/module.h>
57 57
58#include <dev/i2c/i2cvar.h> 58#include <dev/i2c/i2cvar.h>
59 59
60#include "locators.h" 60#include "locators.h"
61 61
62#ifndef I2C_MAX_ADDR 62#ifndef I2C_MAX_ADDR
63#define I2C_MAX_ADDR 0x3ff /* 10-bit address, max */ 63#define I2C_MAX_ADDR 0x3ff /* 10-bit address, max */
64#endif 64#endif
65 65
66struct iic_softc { 66struct iic_softc {
67 i2c_tag_t sc_tag; 67 i2c_tag_t sc_tag;
68 int sc_type; 68 int sc_type;
69 device_t sc_devices[I2C_MAX_ADDR + 1]; 69 device_t sc_devices[I2C_MAX_ADDR + 1];
70}; 70};
71 71
72static dev_type_open(iic_open); 72static dev_type_open(iic_open);
73static dev_type_close(iic_close); 73static dev_type_close(iic_close);
74static dev_type_ioctl(iic_ioctl); 74static dev_type_ioctl(iic_ioctl);
75 75
76const struct cdevsw iic_cdevsw = { 76const struct cdevsw iic_cdevsw = {
77 .d_open = iic_open, 77 .d_open = iic_open,
78 .d_close = iic_close, 78 .d_close = iic_close,
79 .d_read = noread, 79 .d_read = noread,
80 .d_write = nowrite, 80 .d_write = nowrite,
81 .d_ioctl = iic_ioctl, 81 .d_ioctl = iic_ioctl,
82 .d_stop = nostop, 82 .d_stop = nostop,
83 .d_tty = notty, 83 .d_tty = notty,
84 .d_poll = nopoll, 84 .d_poll = nopoll,
85 .d_mmap = nommap, 85 .d_mmap = nommap,
86 .d_kqfilter = nokqfilter, 86 .d_kqfilter = nokqfilter,
87 .d_discard = nodiscard, 87 .d_discard = nodiscard,
88 .d_flag = D_OTHER 88 .d_flag = D_OTHER
89}; 89};
90 90
91extern struct cfdriver iic_cd; 91extern struct cfdriver iic_cd;
92 92
93static void iic_smbus_intr_thread(void *); 93static void iic_smbus_intr_thread(void *);
94static void iic_fill_compat(struct i2c_attach_args*, const char*, 94static void iic_fill_compat(struct i2c_attach_args*, const char*,
95 size_t, char **); 95 size_t, char **);
96 96
97static int 97static int
98iic_print_direct(void *aux, const char *pnp) 98iic_print_direct(void *aux, const char *pnp)
99{ 99{
100 struct i2c_attach_args *ia = aux; 100 struct i2c_attach_args *ia = aux;
101 101
102 if (pnp != NULL) 102 if (pnp != NULL)
103 aprint_normal("%s at %s addr 0x%02x", ia->ia_name, pnp, 103 aprint_normal("%s at %s addr 0x%02x", ia->ia_name, pnp,
104 ia->ia_addr); 104 ia->ia_addr);
105 else 105 else
106 aprint_normal(" addr 0x%02x", ia->ia_addr); 106 aprint_normal(" addr 0x%02x", ia->ia_addr);
107 107
108 return UNCONF; 108 return UNCONF;
109} 109}
110 110
111static int 111static int
112iic_print(void *aux, const char *pnp) 112iic_print(void *aux, const char *pnp)
113{ 113{
114 struct i2c_attach_args *ia = aux; 114 struct i2c_attach_args *ia = aux;
115 115
116 if (ia->ia_addr != (i2c_addr_t)-1) 116 if (ia->ia_addr != (i2c_addr_t)-1)
117 aprint_normal(" addr 0x%x", ia->ia_addr); 117 aprint_normal(" addr 0x%x", ia->ia_addr);
118 118
119 return UNCONF; 119 return UNCONF;
120} 120}
121 121
122static int 122static int
123iic_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 123iic_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
124{ 124{
125 struct iic_softc *sc = device_private(parent); 125 struct iic_softc *sc = device_private(parent);
126 struct i2c_attach_args ia; 126 struct i2c_attach_args ia;
127 127
128 ia.ia_tag = sc->sc_tag; 128 ia.ia_tag = sc->sc_tag;
129 ia.ia_size = cf->cf_loc[IICCF_SIZE]; 129 ia.ia_size = cf->cf_loc[IICCF_SIZE];
130 ia.ia_type = sc->sc_type; 130 ia.ia_type = sc->sc_type;
131 131
132 ia.ia_name = NULL; 132 ia.ia_name = NULL;
133 ia.ia_ncompat = 0; 133 ia.ia_ncompat = 0;
134 ia.ia_compat = NULL; 134 ia.ia_compat = NULL;
135 135
136 for (ia.ia_addr = 0; ia.ia_addr <= I2C_MAX_ADDR; ia.ia_addr++) { 136 for (ia.ia_addr = 0; ia.ia_addr <= I2C_MAX_ADDR; ia.ia_addr++) {
137 if (sc->sc_devices[ia.ia_addr] != NULL) 137 if (sc->sc_devices[ia.ia_addr] != NULL)
138 continue; 138 continue;
139 139
140 if (cf->cf_loc[IICCF_ADDR] != -1 && 140 if (cf->cf_loc[IICCF_ADDR] != -1 &&
141 cf->cf_loc[IICCF_ADDR] != ia.ia_addr) 141 cf->cf_loc[IICCF_ADDR] != ia.ia_addr)
142 continue; 142 continue;
143 143
144 if (config_match(parent, cf, &ia) > 0) 144 if (config_match(parent, cf, &ia) > 0)
145 sc->sc_devices[ia.ia_addr] = 145 sc->sc_devices[ia.ia_addr] =
146 config_attach(parent, cf, &ia, iic_print); 146 config_attach(parent, cf, &ia, iic_print);
147 } 147 }
148 148
149 return 0; 149 return 0;
150} 150}
151 151
152static void 152static void
153iic_child_detach(device_t parent, device_t child) 153iic_child_detach(device_t parent, device_t child)
154{ 154{
155 struct iic_softc *sc = device_private(parent); 155 struct iic_softc *sc = device_private(parent);
156 int i; 156 int i;
157 157
158 for (i = 0; i <= I2C_MAX_ADDR; i++) 158 for (i = 0; i <= I2C_MAX_ADDR; i++)
159 if (sc->sc_devices[i] == child) { 159 if (sc->sc_devices[i] == child) {
160 sc->sc_devices[i] = NULL; 160 sc->sc_devices[i] = NULL;
161 break; 161 break;
162 } 162 }
163} 163}
164 164
165static int 165static int
166iic_rescan(device_t self, const char *ifattr, const int *locators) 166iic_rescan(device_t self, const char *ifattr, const int *locators)
167{ 167{
168 config_search_ia(iic_search, self, ifattr, NULL); 168 config_search_ia(iic_search, self, ifattr, NULL);
169 return 0; 169 return 0;
170} 170}
171 171
172static int 172static int
173iic_match(device_t parent, cfdata_t cf, void *aux) 173iic_match(device_t parent, cfdata_t cf, void *aux)
174{ 174{
175 175
176 return 1; 176 return 1;
177} 177}
178 178
179static void 179static void
180iic_attach(device_t parent, device_t self, void *aux) 180iic_attach(device_t parent, device_t self, void *aux)
181{ 181{
182 struct iic_softc *sc = device_private(self); 182 struct iic_softc *sc = device_private(self);
183 struct i2cbus_attach_args *iba = aux; 183 struct i2cbus_attach_args *iba = aux;
184 prop_array_t child_devices; 184 prop_array_t child_devices;
185 prop_dictionary_t props; 185 prop_dictionary_t props;
186 char *buf; 186 char *buf;
187 i2c_tag_t ic; 187 i2c_tag_t ic;
188 int rv; 188 int rv;
189 bool indirect_config; 189 bool indirect_config;
190 190
191 aprint_naive("\n"); 191 aprint_naive("\n");
192 aprint_normal(": I2C bus\n"); 192 aprint_normal(": I2C bus\n");
193 193
194 sc->sc_tag = iba->iba_tag; 194 sc->sc_tag = iba->iba_tag;
195 sc->sc_type = iba->iba_type; 195 sc->sc_type = iba->iba_type;
196 ic = sc->sc_tag; 196 ic = sc->sc_tag;
197 ic->ic_devname = device_xname(self); 197 ic->ic_devname = device_xname(self);
198 198
199 LIST_INIT(&(sc->sc_tag->ic_list)); 199 LIST_INIT(&(sc->sc_tag->ic_list));
200 LIST_INIT(&(sc->sc_tag->ic_proc_list)); 200 LIST_INIT(&(sc->sc_tag->ic_proc_list));
201 201
202 rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL, 202 rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL,
203 iic_smbus_intr_thread, ic, &ic->ic_intr_thread, 203 iic_smbus_intr_thread, ic, &ic->ic_intr_thread,
204 "%s", ic->ic_devname); 204 "%s", ic->ic_devname);
205 if (rv) 205 if (rv)
206 aprint_error_dev(self, "unable to create intr thread\n"); 206 aprint_error_dev(self, "unable to create intr thread\n");
207 207
208 if (!pmf_device_register(self, NULL, NULL)) 208 if (!pmf_device_register(self, NULL, NULL))
209 aprint_error_dev(self, "couldn't establish power handler\n"); 209 aprint_error_dev(self, "couldn't establish power handler\n");
210 210
211 props = device_properties(parent); 211 props = device_properties(parent);
212 if (!prop_dictionary_get_bool(props, "i2c-indirect-config", 212 if (!prop_dictionary_get_bool(props, "i2c-indirect-config",
213 &indirect_config)) 213 &indirect_config))
214 indirect_config = true; 214 indirect_config = true;
215 child_devices = prop_dictionary_get(props, "i2c-child-devices"); 215 child_devices = prop_dictionary_get(props, "i2c-child-devices");
216 if (child_devices) { 216 if (child_devices) {
217 unsigned int i, count; 217 unsigned int i, count;
218 prop_dictionary_t dev; 218 prop_dictionary_t dev;
219 prop_data_t cdata; 219 prop_data_t cdata;
220 uint32_t addr, size; 220 uint32_t addr, size;
221 uint64_t cookie; 221 uint64_t cookie;
222 const char *name; 222 const char *name;
223 struct i2c_attach_args ia; 223 struct i2c_attach_args ia;
224 int loc[2]; 224 int loc[2];
225 225
226 memset(loc, 0, sizeof loc); 226 memset(loc, 0, sizeof loc);
227 count = prop_array_count(child_devices); 227 count = prop_array_count(child_devices);
228 for (i = 0; i < count; i++) { 228 for (i = 0; i < count; i++) {
229 dev = prop_array_get(child_devices, i); 229 dev = prop_array_get(child_devices, i);
230 if (!dev) continue; 230 if (!dev) continue;
231 if (!prop_dictionary_get_cstring_nocopy( 231 if (!prop_dictionary_get_cstring_nocopy(
232 dev, "name", &name)) 232 dev, "name", &name))
233 continue; 233 continue;
234 if (!prop_dictionary_get_uint32(dev, "addr", &addr)) 234 if (!prop_dictionary_get_uint32(dev, "addr", &addr))
235 continue; 235 continue;
236 if (!prop_dictionary_get_uint64(dev, "cookie", &cookie)) 236 if (!prop_dictionary_get_uint64(dev, "cookie", &cookie))
237 cookie = 0; 237 cookie = 0;
238 loc[0] = addr; 238 loc[0] = addr;
239 if (prop_dictionary_get_uint32(dev, "size", &size)) 239 if (prop_dictionary_get_uint32(dev, "size", &size))
240 loc[1] = size; 240 loc[1] = size;
241 else 241 else
242 loc[1] = -1; 242 loc[1] = -1;
243 243
244 memset(&ia, 0, sizeof ia); 244 memset(&ia, 0, sizeof ia);
245 ia.ia_addr = addr; 245 ia.ia_addr = addr;
246 ia.ia_type = sc->sc_type; 246 ia.ia_type = sc->sc_type;
247 ia.ia_tag = ic; 247 ia.ia_tag = ic;
248 ia.ia_name = name; 248 ia.ia_name = name;
249 ia.ia_cookie = cookie; 249 ia.ia_cookie = cookie;
250 ia.ia_size = size; 250 ia.ia_size = size;
251 251
252 buf = NULL; 252 buf = NULL;
253 cdata = prop_dictionary_get(dev, "compatible"); 253 cdata = prop_dictionary_get(dev, "compatible");
254 if (cdata) 254 if (cdata)
255 iic_fill_compat(&ia, 255 iic_fill_compat(&ia,
256 prop_data_data_nocopy(cdata), 256 prop_data_data_nocopy(cdata),
257 prop_data_size(cdata), &buf); 257 prop_data_size(cdata), &buf);
258 258
259 if (addr > I2C_MAX_ADDR) { 259 if (addr > I2C_MAX_ADDR) {
260 aprint_error_dev(self, 260 aprint_error_dev(self,
261 "WARNING: ignoring bad device address " 261 "WARNING: ignoring bad device address "
262 "@ 0x%02x\n", addr); 262 "@ 0x%02x\n", addr);
263 } else if (sc->sc_devices[addr] == NULL) { 263 } else if (sc->sc_devices[addr] == NULL) {
264 sc->sc_devices[addr] = 264 sc->sc_devices[addr] =
265 config_found_sm_loc(self, "iic", loc, &ia, 265 config_found_sm_loc(self, "iic", loc, &ia,
266 iic_print_direct, NULL); 266 iic_print_direct, NULL);
267 } 267 }
268 268
269 if (ia.ia_compat) 269 if (ia.ia_compat)
270 free(ia.ia_compat, M_TEMP); 270 free(ia.ia_compat, M_TEMP);
271 if (buf) 271 if (buf)
272 free(buf, M_TEMP); 272 free(buf, M_TEMP);
273 } 273 }
274 } else if (indirect_config) { 274 } else if (indirect_config) {
275 /* 275 /*
276 * Attach all i2c devices described in the kernel 276 * Attach all i2c devices described in the kernel
277 * configuration file. 277 * configuration file.
278 */ 278 */
279 iic_rescan(self, "iic", NULL); 279 iic_rescan(self, "iic", NULL);
280 } 280 }
281} 281}
282 282
283static int 283static int
284iic_detach(device_t self, int flags) 284iic_detach(device_t self, int flags)
285{ 285{
286 struct iic_softc *sc = device_private(self); 286 struct iic_softc *sc = device_private(self);
287 i2c_tag_t ic = sc->sc_tag; 287 i2c_tag_t ic = sc->sc_tag;
288 int i, error; 288 int i, error;
289 void *hdl; 289 void *hdl;
290 290
291 for (i = 0; i <= I2C_MAX_ADDR; i++) { 291 for (i = 0; i <= I2C_MAX_ADDR; i++) {
292 if (sc->sc_devices[i]) { 292 if (sc->sc_devices[i]) {
293 error = config_detach(sc->sc_devices[i], flags); 293 error = config_detach(sc->sc_devices[i], flags);
294 if (error) 294 if (error)
295 return error; 295 return error;
296 } 296 }
297 } 297 }
298 298
299 if (ic->ic_running) { 299 if (ic->ic_running) {
300 ic->ic_running = 0; 300 ic->ic_running = 0;
301 wakeup(ic); 301 wakeup(ic);
302 kthread_join(ic->ic_intr_thread); 302 kthread_join(ic->ic_intr_thread);
303 } 303 }
304 304
305 if (!LIST_EMPTY(&ic->ic_list)) { 305 if (!LIST_EMPTY(&ic->ic_list)) {
306 device_printf(self, "WARNING: intr handler list not empty\n"); 306 device_printf(self, "WARNING: intr handler list not empty\n");
307 while (!LIST_EMPTY(&ic->ic_list)) { 307 while (!LIST_EMPTY(&ic->ic_list)) {
308 hdl = LIST_FIRST(&ic->ic_list); 308 hdl = LIST_FIRST(&ic->ic_list);
309 iic_smbus_intr_disestablish(ic, hdl); 309 iic_smbus_intr_disestablish(ic, hdl);
310 } 310 }
311 } 311 }
312 if (!LIST_EMPTY(&ic->ic_proc_list)) { 312 if (!LIST_EMPTY(&ic->ic_proc_list)) {
313 device_printf(self, "WARNING: proc handler list not empty\n"); 313 device_printf(self, "WARNING: proc handler list not empty\n");
314 while (!LIST_EMPTY(&ic->ic_proc_list)) { 314 while (!LIST_EMPTY(&ic->ic_proc_list)) {
315 hdl = LIST_FIRST(&ic->ic_proc_list); 315 hdl = LIST_FIRST(&ic->ic_proc_list);
316 iic_smbus_intr_disestablish_proc(ic, hdl); 316 iic_smbus_intr_disestablish_proc(ic, hdl);
317 } 317 }
318 } 318 }
319 319
320 pmf_device_deregister(self); 320 pmf_device_deregister(self);
321 321
322 return 0; 322 return 0;
323} 323}
324 324
325static void 325static void
326iic_smbus_intr_thread(void *aux) 326iic_smbus_intr_thread(void *aux)
327{ 327{
328 i2c_tag_t ic; 328 i2c_tag_t ic;
329 struct ic_intr_list *il; 329 struct ic_intr_list *il;
330 330
331 ic = (i2c_tag_t)aux; 331 ic = (i2c_tag_t)aux;
332 ic->ic_running = 1; 332 ic->ic_running = 1;
333 ic->ic_pending = 0; 333 ic->ic_pending = 0;
334 334
335 while (ic->ic_running) { 335 while (ic->ic_running) {
336 if (ic->ic_pending == 0) 336 if (ic->ic_pending == 0)
337 tsleep(ic, PZERO, "iicintr", hz); 337 tsleep(ic, PZERO, "iicintr", hz);
338 if (ic->ic_pending > 0) { 338 if (ic->ic_pending > 0) {
339 LIST_FOREACH(il, &(ic->ic_proc_list), il_next) { 339 LIST_FOREACH(il, &(ic->ic_proc_list), il_next) {
340 (*il->il_intr)(il->il_intrarg); 340 (*il->il_intr)(il->il_intrarg);
341 } 341 }
342 ic->ic_pending--; 342 ic->ic_pending--;
343 } 343 }
344 } 344 }
345 345
346 kthread_exit(0); 346 kthread_exit(0);
347} 347}
348 348
349void * 349void *
350iic_smbus_intr_establish(i2c_tag_t ic, int (*intr)(void *), void *intrarg) 350iic_smbus_intr_establish(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
351{ 351{
352 struct ic_intr_list *il; 352 struct ic_intr_list *il;
353 353
354 il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK); 354 il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
355 if (il == NULL) 355 if (il == NULL)
356 return NULL; 356 return NULL;
357 357
358 il->il_intr = intr; 358 il->il_intr = intr;
359 il->il_intrarg = intrarg; 359 il->il_intrarg = intrarg;
360 360
361 LIST_INSERT_HEAD(&(ic->ic_list), il, il_next); 361 LIST_INSERT_HEAD(&(ic->ic_list), il, il_next);
362 362
363 return il; 363 return il;
364} 364}
365 365
366void 366void
367iic_smbus_intr_disestablish(i2c_tag_t ic, void *hdl) 367iic_smbus_intr_disestablish(i2c_tag_t ic, void *hdl)
368{ 368{
369 struct ic_intr_list *il; 369 struct ic_intr_list *il;
370 370
371 il = (struct ic_intr_list *)hdl; 371 il = (struct ic_intr_list *)hdl;
372 372
373 LIST_REMOVE(il, il_next); 373 LIST_REMOVE(il, il_next);
374 free(il, M_DEVBUF); 374 free(il, M_DEVBUF);
375 375
376 return; 376 return;
377} 377}
378 378
379void * 379void *
380iic_smbus_intr_establish_proc(i2c_tag_t ic, int (*intr)(void *), void *intrarg) 380iic_smbus_intr_establish_proc(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
381{ 381{
382 struct ic_intr_list *il; 382 struct ic_intr_list *il;
383 383
384 il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK); 384 il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
385 if (il == NULL) 385 if (il == NULL)
386 return NULL; 386 return NULL;
387 387
388 il->il_intr = intr; 388 il->il_intr = intr;
389 il->il_intrarg = intrarg; 389 il->il_intrarg = intrarg;
390 390
391 LIST_INSERT_HEAD(&(ic->ic_proc_list), il, il_next); 391 LIST_INSERT_HEAD(&(ic->ic_proc_list), il, il_next);
392 392
393 return il; 393 return il;
394} 394}
395 395
396void 396void
397iic_smbus_intr_disestablish_proc(i2c_tag_t ic, void *hdl) 397iic_smbus_intr_disestablish_proc(i2c_tag_t ic, void *hdl)
398{ 398{
399 struct ic_intr_list *il; 399 struct ic_intr_list *il;
400 400
401 il = (struct ic_intr_list *)hdl; 401 il = (struct ic_intr_list *)hdl;
402 402
403 LIST_REMOVE(il, il_next); 403 LIST_REMOVE(il, il_next);
404 free(il, M_DEVBUF); 404 free(il, M_DEVBUF);
405 405
406 return; 406 return;
407} 407}
408 408
409int 409int
410iic_smbus_intr(i2c_tag_t ic) 410iic_smbus_intr(i2c_tag_t ic)
411{ 411{
412 struct ic_intr_list *il; 412 struct ic_intr_list *il;
413 413
414 LIST_FOREACH(il, &(ic->ic_list), il_next) { 414 LIST_FOREACH(il, &(ic->ic_list), il_next) {
415 (*il->il_intr)(il->il_intrarg); 415 (*il->il_intr)(il->il_intrarg);
416 } 416 }
417 417
418 ic->ic_pending++; 418 ic->ic_pending++;
419 wakeup(ic); 419 wakeup(ic);
420 420
421 return 1; 421 return 1;
422} 422}
423 423
424static void 424static void
425iic_fill_compat(struct i2c_attach_args *ia, const char *compat, size_t len, 425iic_fill_compat(struct i2c_attach_args *ia, const char *compat, size_t len,
426 char **buffer) 426 char **buffer)
427{ 427{
428 int count, i; 428 int count, i;
429 const char *c, *start, **ptr; 429 const char *c, *start, **ptr;
430 430
431 *buffer = NULL; 431 *buffer = NULL;
432 for (i = count = 0, c = compat; i < len; i++, c++) 432 for (i = count = 0, c = compat; i < len; i++, c++)
433 if (*c == 0) 433 if (*c == 0)
434 count++; 434 count++;
435 count += 2; 435 count += 2;
436 ptr = malloc(sizeof(char*)*count, M_TEMP, M_WAITOK); 436 ptr = malloc(sizeof(char*)*count, M_TEMP, M_WAITOK);
437 if (!ptr) return; 437 if (!ptr) return;
438 438
439 for (i = count = 0, start = c = compat; i < len; i++, c++) { 439 for (i = count = 0, start = c = compat; i < len; i++, c++) {
440 if (*c == 0) { 440 if (*c == 0) {
441 ptr[count++] = start; 441 ptr[count++] = start;
442 start = c+1; 442 start = c+1;
443 } 443 }
444 } 444 }
445 if (start < compat+len) { 445 if (start < compat+len) {
446 /* last string not 0 terminated */ 446 /* last string not 0 terminated */
447 size_t l = c-start; 447 size_t l = c-start;
448 *buffer = malloc(l+1, M_TEMP, M_WAITOK); 448 *buffer = malloc(l+1, M_TEMP, M_WAITOK);
449 memcpy(*buffer, start, l); 449 memcpy(*buffer, start, l);
450 (*buffer)[l] = 0; 450 (*buffer)[l] = 0;
451 ptr[count++] = *buffer; 451 ptr[count++] = *buffer;
452 } 452 }
453 ptr[count] = NULL; 453 ptr[count] = NULL;
454 454
455 ia->ia_compat = ptr; 455 ia->ia_compat = ptr;
456 ia->ia_ncompat = count; 456 ia->ia_ncompat = count;
457} 457}
458 458
459int 459int
460iic_compat_match(struct i2c_attach_args *ia, const char ** compats) 460iic_compat_match(struct i2c_attach_args *ia, const char ** compats)
461{ 461{
462 int i; 462 int i;
463 463
464 for (; compats && *compats; compats++) { 464 for (; compats && *compats; compats++) {
465 for (i = 0; i < ia->ia_ncompat; i++) { 465 for (i = 0; i < ia->ia_ncompat; i++) {
466 if (strcmp(*compats, ia->ia_compat[i]) == 0) 466 if (strcmp(*compats, ia->ia_compat[i]) == 0)
467 return 1; 467 return 1;
468 } 468 }
469 } 469 }
470 return 0; 470 return 0;
471} 471}
472 472
473static int 473static int
474iic_open(dev_t dev, int flag, int fmt, lwp_t *l) 474iic_open(dev_t dev, int flag, int fmt, lwp_t *l)
475{ 475{
476 struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev)); 476 struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
477 477
478 if (sc == NULL) 478 if (sc == NULL)
479 return ENXIO; 479 return ENXIO;
480 480
481 return 0; 481 return 0;
482} 482}
483 483
484static int 484static int
485iic_close(dev_t dev, int flag, int fmt, lwp_t *l) 485iic_close(dev_t dev, int flag, int fmt, lwp_t *l)
486{ 486{
487 return 0; 487 return 0;
488} 488}
489 489
490static int 490static int
491iic_ioctl_exec(struct iic_softc *sc, i2c_ioctl_exec_t *iie, int flag) 491iic_ioctl_exec(struct iic_softc *sc, i2c_ioctl_exec_t *iie, int flag)
492{ 492{
493 i2c_tag_t ic = sc->sc_tag; 493 i2c_tag_t ic = sc->sc_tag;
494 uint8_t buf[I2C_EXEC_MAX_BUFLEN]; 494 uint8_t buf[I2C_EXEC_MAX_BUFLEN];
495 void *cmd = NULL; 495 void *cmd = NULL;
496 int error; 496 int error;
497 497
498 /* Validate parameters */ 498 /* Validate parameters */
499 if (iie->iie_addr > I2C_MAX_ADDR) 499 if (iie->iie_addr > I2C_MAX_ADDR)
500 return EINVAL; 500 return EINVAL;
501 if (iie->iie_cmdlen > I2C_EXEC_MAX_CMDLEN || 501 if (iie->iie_cmdlen > I2C_EXEC_MAX_CMDLEN ||
502 iie->iie_buflen > I2C_EXEC_MAX_BUFLEN) 502 iie->iie_buflen > I2C_EXEC_MAX_BUFLEN)
503 return EINVAL; 503 return EINVAL;
504 if (iie->iie_cmd != NULL && iie->iie_cmdlen == 0) 504 if (iie->iie_cmd != NULL && iie->iie_cmdlen == 0)
505 return EINVAL; 505 return EINVAL;
506 if (iie->iie_buf != NULL && iie->iie_buflen == 0) 506 if (iie->iie_buf != NULL && iie->iie_buflen == 0)
507 return EINVAL; 507 return EINVAL;
508 if (I2C_OP_WRITE_P(iie->iie_op) && (flag & FWRITE) == 0) 508 if (I2C_OP_WRITE_P(iie->iie_op) && (flag & FWRITE) == 0)
509 return EBADF; 509 return EBADF;
510 510
511#if 0 511#if 0
512 /* Disallow userspace access to devices that have drivers attached. */ 512 /* Disallow userspace access to devices that have drivers attached. */
513 if (sc->sc_devices[iie->iie_addr] != NULL) 513 if (sc->sc_devices[iie->iie_addr] != NULL)
514 return EBUSY; 514 return EBUSY;
515#endif 515#endif
516 516
517 if (iie->iie_cmd != NULL) { 517 if (iie->iie_cmd != NULL) {
518 cmd = kmem_alloc(iie->iie_cmdlen, KM_SLEEP); 518 cmd = kmem_alloc(iie->iie_cmdlen, KM_SLEEP);
519 if (cmd == NULL) 519 if (cmd == NULL)
520 return ENOMEM; 520 return ENOMEM;
521 error = copyin(iie->iie_cmd, cmd, iie->iie_cmdlen); 521 error = copyin(iie->iie_cmd, cmd, iie->iie_cmdlen);
522 if (error) 522 if (error)
523 goto out; 523 goto out;
524 } 524 }
525 525
526 if (iie->iie_buf != NULL && I2C_OP_WRITE_P(iie->iie_op)) { 526 if (iie->iie_buf != NULL && I2C_OP_WRITE_P(iie->iie_op)) {
527 error = copyin(iie->iie_buf, buf, iie->iie_buflen); 527 error = copyin(iie->iie_buf, buf, iie->iie_buflen);
528 if (error) 528 if (error)
529 goto out; 529 goto out;
530 } 530 }
531 531
532 iic_acquire_bus(ic, 0); 532 iic_acquire_bus(ic, 0);
533 error = iic_exec(ic, iie->iie_op, iie->iie_addr, cmd, iie->iie_cmdlen, 533 error = iic_exec(ic, iie->iie_op, iie->iie_addr, cmd, iie->iie_cmdlen,
534 buf, iie->iie_buflen, 0); 534 buf, iie->iie_buflen, 0);
535 iic_release_bus(ic, 0); 535 iic_release_bus(ic, 0);
536 536
537 /* 537 /*
538 * Some drivers return error codes on failure, and others return -1. 538 * Some drivers return error codes on failure, and others return -1.
539 */ 539 */
540 if (error < 0) 540 if (error < 0)
541 error = EIO; 541 error = EIO;
542 542
543out: 543out:
544 if (cmd) 544 if (cmd)
545 kmem_free(cmd, iie->iie_cmdlen); 545 kmem_free(cmd, iie->iie_cmdlen);
546 546
547 if (error) 547 if (error)
548 return error; 548 return error;
549 549
550 if (iie->iie_buf != NULL && I2C_OP_READ_P(iie->iie_op)) 550 if (iie->iie_buf != NULL && I2C_OP_READ_P(iie->iie_op))
551 error = copyout(buf, iie->iie_buf, iie->iie_buflen); 551 error = copyout(buf, iie->iie_buf, iie->iie_buflen);
552 552
553 return error; 553 return error;
554} 554}
555 555
556static int 556static int
557iic_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l) 557iic_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
558{ 558{
559 struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev)); 559 struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
560 560
561 if (sc == NULL) 561 if (sc == NULL)
562 return ENXIO; 562 return ENXIO;
563 563
564 switch (cmd) { 564 switch (cmd) {
565 case I2C_IOCTL_EXEC: 565 case I2C_IOCTL_EXEC:
566 return iic_ioctl_exec(sc, (i2c_ioctl_exec_t *)data, flag); 566 return iic_ioctl_exec(sc, (i2c_ioctl_exec_t *)data, flag);
567 default: 567 default:
568 return ENODEV; 568 return ENODEV;
569 } 569 }
570} 570}
571 571
572 572
573CFATTACH_DECL2_NEW(iic, sizeof(struct iic_softc), 573CFATTACH_DECL2_NEW(iic, sizeof(struct iic_softc),
574 iic_match, iic_attach, iic_detach, NULL, iic_rescan, iic_child_detach); 574 iic_match, iic_attach, iic_detach, NULL, iic_rescan, iic_child_detach);
575 575
576MODULE(MODULE_CLASS_DRIVER, iic, NULL); 576MODULE(MODULE_CLASS_DRIVER, iic, "i2cexec");
577 577
578#ifdef _MODULE 578#ifdef _MODULE
579#include "ioconf.c" 579#include "ioconf.c"
580#endif 580#endif
581 581
582static int 582static int
583iic_modcmd(modcmd_t cmd, void *opaque) 583iic_modcmd(modcmd_t cmd, void *opaque)
584{ 584{
585 int error; 585 int error;
586 586
587 error = 0; 587 error = 0;
588 switch (cmd) { 588 switch (cmd) {
589 case MODULE_CMD_INIT: 589 case MODULE_CMD_INIT:
590#ifdef _MODULE 590#ifdef _MODULE
591 error = config_init_component(cfdriver_ioconf_iic, 591 error = config_init_component(cfdriver_ioconf_iic,
592 cfattach_ioconf_iic, cfdata_ioconf_iic); 592 cfattach_ioconf_iic, cfdata_ioconf_iic);
593 if (error) 593 if (error)
594 aprint_error("%s: unable to init component\n", 594 aprint_error("%s: unable to init component\n",
595 iic_cd.cd_name); 595 iic_cd.cd_name);
596#endif 596#endif
597 break; 597 break;
598 case MODULE_CMD_FINI: 598 case MODULE_CMD_FINI:
599#ifdef _MODULE 599#ifdef _MODULE
600 config_fini_component(cfdriver_ioconf_iic, 600 config_fini_component(cfdriver_ioconf_iic,
601 cfattach_ioconf_iic, cfdata_ioconf_iic); 601 cfattach_ioconf_iic, cfdata_ioconf_iic);
602#endif 602#endif
603 break; 603 break;
604 default: 604 default:
605 error = ENOTTY; 605 error = ENOTTY;
606 } 606 }
607 return error; 607 return error;
608} 608}