Wed Jul 27 23:11:24 2011 UTC ()
Change a cast to appease gcc4.5


(matt)
diff -r1.21 -r1.22 src/sys/arch/xen/xenbus/xenbus_xs.c

cvs diff -r1.21 -r1.22 src/sys/arch/xen/xenbus/xenbus_xs.c (switch to unified diff)

--- src/sys/arch/xen/xenbus/xenbus_xs.c 2011/07/17 20:54:49 1.21
+++ src/sys/arch/xen/xenbus/xenbus_xs.c 2011/07/27 23:11:23 1.22
@@ -1,877 +1,877 @@ @@ -1,877 +1,877 @@
1/* $NetBSD: xenbus_xs.c,v 1.21 2011/07/17 20:54:49 joerg Exp $ */ 1/* $NetBSD: xenbus_xs.c,v 1.22 2011/07/27 23:11:23 matt Exp $ */
2/****************************************************************************** 2/******************************************************************************
3 * xenbus_xs.c 3 * xenbus_xs.c
4 * 4 *
5 * This is the kernel equivalent of the "xs" library. We don't need everything 5 * This is the kernel equivalent of the "xs" library. We don't need everything
6 * and we use xenbus_comms for communication. 6 * and we use xenbus_comms for communication.
7 * 7 *
8 * Copyright (C) 2005 Rusty Russell, IBM Corporation 8 * Copyright (C) 2005 Rusty Russell, IBM Corporation
9 *  9 *
10 * This file may be distributed separately from the Linux kernel, or 10 * This file may be distributed separately from the Linux kernel, or
11 * incorporated into other software packages, subject to the following license: 11 * incorporated into other software packages, subject to the following license:
12 *  12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a copy 13 * Permission is hereby granted, free of charge, to any person obtaining a copy
14 * of this source file (the "Software"), to deal in the Software without 14 * of this source file (the "Software"), to deal in the Software without
15 * restriction, including without limitation the rights to use, copy, modify, 15 * restriction, including without limitation the rights to use, copy, modify,
16 * merge, publish, distribute, sublicense, and/or sell copies of the Software, 16 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
17 * and to permit persons to whom the Software is furnished to do so, subject to 17 * and to permit persons to whom the Software is furnished to do so, subject to
18 * the following conditions: 18 * the following conditions:
19 *  19 *
20 * The above copyright notice and this permission notice shall be included in 20 * The above copyright notice and this permission notice shall be included in
21 * all copies or substantial portions of the Software. 21 * all copies or substantial portions of the Software.
22 *  22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 * IN THE SOFTWARE. 29 * IN THE SOFTWARE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: xenbus_xs.c,v 1.21 2011/07/17 20:54:49 joerg Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: xenbus_xs.c,v 1.22 2011/07/27 23:11:23 matt Exp $");
34 34
35#if 0 35#if 0
36#define DPRINTK(fmt, args...) \ 36#define DPRINTK(fmt, args...) \
37 printf("xenbus_xs (%s:%d) " fmt ".\n", __func__, __LINE__, ##args) 37 printf("xenbus_xs (%s:%d) " fmt ".\n", __func__, __LINE__, ##args)
38#else 38#else
39#define DPRINTK(fmt, args...) ((void)0) 39#define DPRINTK(fmt, args...) ((void)0)
40#endif  40#endif
41 41
42#include <sys/types.h> 42#include <sys/types.h>
43#include <sys/null.h> 43#include <sys/null.h>
44#include <sys/errno.h> 44#include <sys/errno.h>
45#include <sys/malloc.h> 45#include <sys/malloc.h>
46#include <sys/systm.h> 46#include <sys/systm.h>
47#include <sys/param.h> 47#include <sys/param.h>
48#include <sys/proc.h> 48#include <sys/proc.h>
49#include <sys/mutex.h> 49#include <sys/mutex.h>
50#include <sys/kthread.h> 50#include <sys/kthread.h>
51 51
52#include <xen/xen.h> /* for xendomain_is_dom0() */ 52#include <xen/xen.h> /* for xendomain_is_dom0() */
53#include <xen/xenbus.h> 53#include <xen/xenbus.h>
54#include "xenbus_comms.h" 54#include "xenbus_comms.h"
55 55
56#define streq(a, b) (strcmp((a), (b)) == 0) 56#define streq(a, b) (strcmp((a), (b)) == 0)
57 57
58struct xs_stored_msg { 58struct xs_stored_msg {
59 SIMPLEQ_ENTRY(xs_stored_msg) msg_next; 59 SIMPLEQ_ENTRY(xs_stored_msg) msg_next;
60 60
61 struct xsd_sockmsg hdr; 61 struct xsd_sockmsg hdr;
62 62
63 union { 63 union {
64 /* Queued replies. */ 64 /* Queued replies. */
65 struct { 65 struct {
66 char *body; 66 char *body;
67 } reply; 67 } reply;
68 68
69 /* Queued watch events. */ 69 /* Queued watch events. */
70 struct { 70 struct {
71 struct xenbus_watch *handle; 71 struct xenbus_watch *handle;
72 char **vec; 72 char **vec;
73 unsigned int vec_size; 73 unsigned int vec_size;
74 } watch; 74 } watch;
75 } u; 75 } u;
76}; 76};
77 77
78struct xs_handle { 78struct xs_handle {
79 /* A list of replies. Currently only one will ever be outstanding. */ 79 /* A list of replies. Currently only one will ever be outstanding. */
80 SIMPLEQ_HEAD(, xs_stored_msg) reply_list; 80 SIMPLEQ_HEAD(, xs_stored_msg) reply_list;
81 kmutex_t reply_lock; 81 kmutex_t reply_lock;
82 kcondvar_t reply_cv; 82 kcondvar_t reply_cv;
83 kmutex_t xs_lock; /* serialize access to xenstore */ 83 kmutex_t xs_lock; /* serialize access to xenstore */
84 int suspend_spl; 84 int suspend_spl;
85 85
86}; 86};
87 87
88static struct xs_handle xs_state; 88static struct xs_handle xs_state;
89 89
90/* List of registered watches, and a lock to protect it. */ 90/* List of registered watches, and a lock to protect it. */
91static SLIST_HEAD(, xenbus_watch) watches; 91static SLIST_HEAD(, xenbus_watch) watches;
92static kmutex_t watches_lock; 92static kmutex_t watches_lock;
93 93
94/* List of pending watch callback events, and a lock to protect it. */ 94/* List of pending watch callback events, and a lock to protect it. */
95static SIMPLEQ_HEAD(, xs_stored_msg) watch_events; 95static SIMPLEQ_HEAD(, xs_stored_msg) watch_events;
96static kmutex_t watch_events_lock; 96static kmutex_t watch_events_lock;
97static kcondvar_t watch_cv; 97static kcondvar_t watch_cv;
98 98
99static int 99static int
100get_error(const char *errorstring) 100get_error(const char *errorstring)
101{ 101{
102 unsigned int i; 102 unsigned int i;
103 103
104 for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) { 104 for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
105 if (i == (sizeof(xsd_errors) / sizeof(xsd_errors[0]) - 1)) { 105 if (i == (sizeof(xsd_errors) / sizeof(xsd_errors[0]) - 1)) {
106 printf( 106 printf(
107 "XENBUS xen store gave: unknown error %s", 107 "XENBUS xen store gave: unknown error %s",
108 errorstring); 108 errorstring);
109 return EINVAL; 109 return EINVAL;
110 } 110 }
111 } 111 }
112 return xsd_errors[i].errnum; 112 return xsd_errors[i].errnum;
113} 113}
114 114
115static void * 115static void *
116read_reply(enum xsd_sockmsg_type *type, unsigned int *len) 116read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
117{ 117{
118 struct xs_stored_msg *msg; 118 struct xs_stored_msg *msg;
119 char *body; 119 char *body;
120 120
121 mutex_enter(&xs_state.reply_lock); 121 mutex_enter(&xs_state.reply_lock);
122 while (SIMPLEQ_EMPTY(&xs_state.reply_list)) { 122 while (SIMPLEQ_EMPTY(&xs_state.reply_list)) {
123 cv_wait(&xs_state.reply_cv, &xs_state.reply_lock); 123 cv_wait(&xs_state.reply_cv, &xs_state.reply_lock);
124 } 124 }
125 msg = SIMPLEQ_FIRST(&xs_state.reply_list); 125 msg = SIMPLEQ_FIRST(&xs_state.reply_list);
126 SIMPLEQ_REMOVE_HEAD(&xs_state.reply_list, msg_next); 126 SIMPLEQ_REMOVE_HEAD(&xs_state.reply_list, msg_next);
127 mutex_exit(&xs_state.reply_lock); 127 mutex_exit(&xs_state.reply_lock);
128 128
129 *type = msg->hdr.type; 129 *type = msg->hdr.type;
130 if (len) 130 if (len)
131 *len = msg->hdr.len; 131 *len = msg->hdr.len;
132 body = msg->u.reply.body; 132 body = msg->u.reply.body;
133 DPRINTK("read_reply: type %d body %s", 133 DPRINTK("read_reply: type %d body %s",
134 msg->hdr.type, body); 134 msg->hdr.type, body);
135 135
136 free(msg, M_DEVBUF); 136 free(msg, M_DEVBUF);
137 137
138 return body; 138 return body;
139} 139}
140 140
141#if 0 141#if 0
142/* Emergency write. */ 142/* Emergency write. */
143void 143void
144xenbus_debug_write(const char *str, unsigned int count) 144xenbus_debug_write(const char *str, unsigned int count)
145{ 145{
146 struct xsd_sockmsg msg = { 0 }; 146 struct xsd_sockmsg msg = { 0 };
147 147
148 msg.type = XS_DEBUG; 148 msg.type = XS_DEBUG;
149 msg.len = sizeof("print") + count + 1; 149 msg.len = sizeof("print") + count + 1;
150 150
151 xb_write(&msg, sizeof(msg)); 151 xb_write(&msg, sizeof(msg));
152 xb_write("print", sizeof("print")); 152 xb_write("print", sizeof("print"));
153 xb_write(str, count); 153 xb_write(str, count);
154 xb_write("", 1); 154 xb_write("", 1);
155} 155}
156#endif 156#endif
157 157
158int 158int
159xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void**reply) 159xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void**reply)
160{ 160{
161 int err = 0, s; 161 int err = 0, s;
162 162
163 s = spltty(); 163 s = spltty();
164 mutex_enter(&xs_state.xs_lock); 164 mutex_enter(&xs_state.xs_lock);
165 err = xb_write(msg, sizeof(*msg) + msg->len); 165 err = xb_write(msg, sizeof(*msg) + msg->len);
166 if (err) { 166 if (err) {
167 msg->type = XS_ERROR; 167 msg->type = XS_ERROR;
168 *reply = NULL; 168 *reply = NULL;
169 } else { 169 } else {
170 *reply = read_reply(&msg->type, &msg->len); 170 *reply = read_reply(&msg->type, &msg->len);
171 } 171 }
172 mutex_exit(&xs_state.xs_lock); 172 mutex_exit(&xs_state.xs_lock);
173 splx(s); 173 splx(s);
174 174
175 return err; 175 return err;
176} 176}
177 177
178/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */ 178/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
179static int 179static int
180xs_talkv(struct xenbus_transaction *t, 180xs_talkv(struct xenbus_transaction *t,
181 enum xsd_sockmsg_type type, 181 enum xsd_sockmsg_type type,
182 const struct iovec *iovec, 182 const struct iovec *iovec,
183 unsigned int num_vecs, 183 unsigned int num_vecs,
184 unsigned int *len, 184 unsigned int *len,
185 char **retbuf) 185 char **retbuf)
186{ 186{
187 struct xsd_sockmsg msg; 187 struct xsd_sockmsg msg;
188 unsigned int i; 188 unsigned int i;
189 int err, s; 189 int err, s;
190 void *ret; 190 void *ret;
191 191
192 msg.tx_id = (uint32_t)(unsigned long)t; 192 msg.tx_id = (uint32_t)(unsigned long)t;
193 msg.req_id = 0; 193 msg.req_id = 0;
194 msg.type = type; 194 msg.type = type;
195 msg.len = 0; 195 msg.len = 0;
196 for (i = 0; i < num_vecs; i++) 196 for (i = 0; i < num_vecs; i++)
197 msg.len += iovec[i].iov_len; 197 msg.len += iovec[i].iov_len;
198 198
199 s = spltty(); 199 s = spltty();
200 mutex_enter(&xs_state.xs_lock); 200 mutex_enter(&xs_state.xs_lock);
201 201
202 DPRINTK("write msg"); 202 DPRINTK("write msg");
203 err = xb_write(&msg, sizeof(msg)); 203 err = xb_write(&msg, sizeof(msg));
204 DPRINTK("write msg err %d", err); 204 DPRINTK("write msg err %d", err);
205 if (err) { 205 if (err) {
206 mutex_exit(&xs_state.xs_lock); 206 mutex_exit(&xs_state.xs_lock);
207 splx(s); 207 splx(s);
208 return (err); 208 return (err);
209 } 209 }
210 210
211 for (i = 0; i < num_vecs; i++) { 211 for (i = 0; i < num_vecs; i++) {
212 DPRINTK("write iovect"); 212 DPRINTK("write iovect");
213 err = xb_write(iovec[i].iov_base, iovec[i].iov_len); 213 err = xb_write(iovec[i].iov_base, iovec[i].iov_len);
214 DPRINTK("write iovect err %d", err); 214 DPRINTK("write iovect err %d", err);
215 if (err) { 215 if (err) {
216 mutex_exit(&xs_state.xs_lock); 216 mutex_exit(&xs_state.xs_lock);
217 splx(s); 217 splx(s);
218 return (err); 218 return (err);
219 } 219 }
220 } 220 }
221 221
222 DPRINTK("read"); 222 DPRINTK("read");
223 ret = read_reply(&msg.type, len); 223 ret = read_reply(&msg.type, len);
224 DPRINTK("read done"); 224 DPRINTK("read done");
225 225
226 mutex_exit(&xs_state.xs_lock); 226 mutex_exit(&xs_state.xs_lock);
227 splx(s); 227 splx(s);
228 228
229 if (msg.type == XS_ERROR) { 229 if (msg.type == XS_ERROR) {
230 err = get_error(ret); 230 err = get_error(ret);
231 free(ret, M_DEVBUF); 231 free(ret, M_DEVBUF);
232 return (err); 232 return (err);
233 } 233 }
234 234
235 KASSERT(msg.type == type); 235 KASSERT(msg.type == type);
236 if (retbuf != NULL) 236 if (retbuf != NULL)
237 *retbuf = ret; 237 *retbuf = ret;
238 else 238 else
239 free(ret, M_DEVBUF); 239 free(ret, M_DEVBUF);
240 return 0; 240 return 0;
241} 241}
242 242
243/* Simplified version of xs_talkv: single message. */ 243/* Simplified version of xs_talkv: single message. */
244static int 244static int
245xs_single(struct xenbus_transaction *t, 245xs_single(struct xenbus_transaction *t,
246 enum xsd_sockmsg_type type, 246 enum xsd_sockmsg_type type,
247 const char *string, 247 const char *string,
248 unsigned int *len, 248 unsigned int *len,
249 char **ret) 249 char **ret)
250{ 250{
251 struct iovec iovec; 251 struct iovec iovec;
252 252
253 /* xs_talkv only reads iovec */ 253 /* xs_talkv only reads iovec */
254 iovec.iov_base = __UNCONST(string); 254 iovec.iov_base = __UNCONST(string);
255 iovec.iov_len = strlen(string) + 1; 255 iovec.iov_len = strlen(string) + 1;
256 return xs_talkv(t, type, &iovec, 1, len, ret); 256 return xs_talkv(t, type, &iovec, 1, len, ret);
257} 257}
258 258
259static unsigned int 259static unsigned int
260count_strings(const char *strings, unsigned int len) 260count_strings(const char *strings, unsigned int len)
261{ 261{
262 unsigned int num; 262 unsigned int num;
263 const char *p; 263 const char *p;
264 264
265 for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1) 265 for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
266 num++; 266 num++;
267 267
268 return num; 268 return num;
269} 269}
270 270
271/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */  271/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */
272static char * 272static char *
273join(const char *dir, const char *name) 273join(const char *dir, const char *name)
274{ 274{
275 char *buffer; 275 char *buffer;
276 276
277 buffer = malloc(strlen(dir) + strlen("/") + strlen(name) + 1, 277 buffer = malloc(strlen(dir) + strlen("/") + strlen(name) + 1,
278 M_DEVBUF, M_NOWAIT); 278 M_DEVBUF, M_NOWAIT);
279 if (buffer == NULL) 279 if (buffer == NULL)
280 return NULL; 280 return NULL;
281 281
282 strcpy(buffer, dir); 282 strcpy(buffer, dir);
283 if (!streq(name, "")) { 283 if (!streq(name, "")) {
284 strcat(buffer, "/"); 284 strcat(buffer, "/");
285 strcat(buffer, name); 285 strcat(buffer, name);
286 } 286 }
287 287
288 return buffer; 288 return buffer;
289} 289}
290 290
291static char ** 291static char **
292split(char *strings, unsigned int len, unsigned int *num) 292split(char *strings, unsigned int len, unsigned int *num)
293{ 293{
294 char *p, **ret; 294 char *p, **ret;
295 295
296 /* Count the strings. */ 296 /* Count the strings. */
297 *num = count_strings(strings, len); 297 *num = count_strings(strings, len);
298 298
299 /* Transfer to one big alloc for easy freeing. */ 299 /* Transfer to one big alloc for easy freeing. */
300 ret = malloc(*num * sizeof(char *) + len, M_DEVBUF, M_NOWAIT); 300 ret = malloc(*num * sizeof(char *) + len, M_DEVBUF, M_NOWAIT);
301 if (!ret) { 301 if (!ret) {
302 free(strings, M_DEVBUF); 302 free(strings, M_DEVBUF);
303 return NULL; 303 return NULL;
304 } 304 }
305 memcpy(&ret[*num], strings, len); 305 memcpy(&ret[*num], strings, len);
306 free(strings, M_DEVBUF); 306 free(strings, M_DEVBUF);
307 307
308 strings = (char *)&ret[*num]; 308 strings = (char *)&ret[*num];
309 for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1) 309 for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
310 ret[(*num)++] = p; 310 ret[(*num)++] = p;
311 311
312 return ret; 312 return ret;
313} 313}
314 314
315int 315int
316xenbus_directory(struct xenbus_transaction *t, 316xenbus_directory(struct xenbus_transaction *t,
317 const char *dir, const char *node, unsigned int *num, 317 const char *dir, const char *node, unsigned int *num,
318 char ***retbuf) 318 char ***retbuf)
319{ 319{
320 char *strings, *path; 320 char *strings, *path;
321 unsigned int len; 321 unsigned int len;
322 int err; 322 int err;
323 323
324 path = join(dir, node); 324 path = join(dir, node);
325 if (path == NULL)  325 if (path == NULL)
326 return ENOMEM; 326 return ENOMEM;
327 327
328 err = xs_single(t, XS_DIRECTORY, path, &len, &strings); 328 err = xs_single(t, XS_DIRECTORY, path, &len, &strings);
329 DPRINTK("xs_single %d %d", err, len); 329 DPRINTK("xs_single %d %d", err, len);
330 free(path, M_DEVBUF); 330 free(path, M_DEVBUF);
331 if (err) 331 if (err)
332 return err; 332 return err;
333 333
334 DPRINTK("xs_single strings %s", strings); 334 DPRINTK("xs_single strings %s", strings);
335 *retbuf = split(strings, len, num); 335 *retbuf = split(strings, len, num);
336 if (*retbuf == NULL) 336 if (*retbuf == NULL)
337 return ENOMEM; 337 return ENOMEM;
338 return 0; 338 return 0;
339} 339}
340 340
341/* Check if a path exists. Return 1 if it does. */ 341/* Check if a path exists. Return 1 if it does. */
342int 342int
343xenbus_exists(struct xenbus_transaction *t, 343xenbus_exists(struct xenbus_transaction *t,
344 const char *dir, const char *node) 344 const char *dir, const char *node)
345{ 345{
346 char **d; 346 char **d;
347 int dir_n, err; 347 int dir_n, err;
348 348
349 err = xenbus_directory(t, dir, node, &dir_n, &d); 349 err = xenbus_directory(t, dir, node, &dir_n, &d);
350 if (err) 350 if (err)
351 return 0; 351 return 0;
352 free(d, M_DEVBUF); 352 free(d, M_DEVBUF);
353 return 1; 353 return 1;
354} 354}
355 355
356/* Get the value of a single file. 356/* Get the value of a single file.
357 * Returns a kmalloced value: call free() on it after use. 357 * Returns a kmalloced value: call free() on it after use.
358 * len indicates length in bytes. 358 * len indicates length in bytes.
359 */ 359 */
360int 360int
361xenbus_read(struct xenbus_transaction *t, 361xenbus_read(struct xenbus_transaction *t,
362 const char *dir, const char *node, unsigned int *len, 362 const char *dir, const char *node, unsigned int *len,
363 char **ret) 363 char **ret)
364{ 364{
365 char *path; 365 char *path;
366 int err; 366 int err;
367 367
368 path = join(dir, node); 368 path = join(dir, node);
369 if (path == NULL) 369 if (path == NULL)
370 return ENOMEM; 370 return ENOMEM;
371 371
372 err = xs_single(t, XS_READ, path, len, ret); 372 err = xs_single(t, XS_READ, path, len, ret);
373 free(path, M_DEVBUF); 373 free(path, M_DEVBUF);
374 return err; 374 return err;
375} 375}
376 376
377/* Read a node and convert it to unsigned long. */ 377/* Read a node and convert it to unsigned long. */
378int 378int
379xenbus_read_ul(struct xenbus_transaction *t, 379xenbus_read_ul(struct xenbus_transaction *t,
380 const char *dir, const char *node, unsigned long *val, 380 const char *dir, const char *node, unsigned long *val,
381 int base) 381 int base)
382{ 382{
383 char *string, *ep; 383 char *string, *ep;
384 int err; 384 int err;
385 385
386 err = xenbus_read(t, dir, node, NULL, &string); 386 err = xenbus_read(t, dir, node, NULL, &string);
387 if (err) 387 if (err)
388 return err; 388 return err;
389 *val = strtoul(string, &ep, base); 389 *val = strtoul(string, &ep, base);
390 if (*ep != '\0') { 390 if (*ep != '\0') {
391 free(string, M_DEVBUF); 391 free(string, M_DEVBUF);
392 return EFTYPE; 392 return EFTYPE;
393 } 393 }
394 free(string, M_DEVBUF); 394 free(string, M_DEVBUF);
395 return 0; 395 return 0;
396} 396}
397 397
398/* Read a node and convert it to unsigned long long. */ 398/* Read a node and convert it to unsigned long long. */
399int 399int
400xenbus_read_ull(struct xenbus_transaction *t, 400xenbus_read_ull(struct xenbus_transaction *t,
401 const char *dir, const char *node, unsigned long long *val, 401 const char *dir, const char *node, unsigned long long *val,
402 int base) 402 int base)
403{ 403{
404 char *string, *ep; 404 char *string, *ep;
405 int err; 405 int err;
406 406
407 err = xenbus_read(t, dir, node, NULL, &string); 407 err = xenbus_read(t, dir, node, NULL, &string);
408 if (err) 408 if (err)
409 return err; 409 return err;
410 *val = strtoull(string, &ep, base); 410 *val = strtoull(string, &ep, base);
411 if (*ep != '\0') { 411 if (*ep != '\0') {
412 free(string, M_DEVBUF); 412 free(string, M_DEVBUF);
413 return EFTYPE; 413 return EFTYPE;
414 } 414 }
415 free(string, M_DEVBUF); 415 free(string, M_DEVBUF);
416 return 0; 416 return 0;
417} 417}
418 418
419/* Write the value of a single file. 419/* Write the value of a single file.
420 * Returns -err on failure. 420 * Returns -err on failure.
421 */ 421 */
422int 422int
423xenbus_write(struct xenbus_transaction *t, 423xenbus_write(struct xenbus_transaction *t,
424 const char *dir, const char *node, const char *string) 424 const char *dir, const char *node, const char *string)
425{ 425{
426 const char *path; 426 const char *path;
427 struct iovec iovec[2]; 427 struct iovec iovec[2];
428 int ret; 428 int ret;
429 429
430 path = join(dir, node); 430 path = join(dir, node);
431 if (path == NULL) 431 if (path == NULL)
432 return ENOMEM; 432 return ENOMEM;
433 433
434 /* xs_talkv only reads iovec */ 434 /* xs_talkv only reads iovec */
435 iovec[0].iov_base = __UNCONST(path); 435 iovec[0].iov_base = __UNCONST(path);
436 iovec[0].iov_len = strlen(path) + 1; 436 iovec[0].iov_len = strlen(path) + 1;
437 iovec[1].iov_base = __UNCONST(string); 437 iovec[1].iov_base = __UNCONST(string);
438 iovec[1].iov_len = strlen(string); 438 iovec[1].iov_len = strlen(string);
439 439
440 ret = xs_talkv(t, XS_WRITE, iovec, 2, NULL, NULL); 440 ret = xs_talkv(t, XS_WRITE, iovec, 2, NULL, NULL);
441 return ret; 441 return ret;
442} 442}
443 443
444/* Create a new directory. */ 444/* Create a new directory. */
445int 445int
446xenbus_mkdir(struct xenbus_transaction *t, 446xenbus_mkdir(struct xenbus_transaction *t,
447 const char *dir, const char *node) 447 const char *dir, const char *node)
448{ 448{
449 char *path; 449 char *path;
450 int ret; 450 int ret;
451 451
452 path = join(dir, node); 452 path = join(dir, node);
453 if (path == NULL) 453 if (path == NULL)
454 return ENOMEM; 454 return ENOMEM;
455 455
456 ret = xs_single(t, XS_MKDIR, path, NULL, NULL); 456 ret = xs_single(t, XS_MKDIR, path, NULL, NULL);
457 free(path, M_DEVBUF); 457 free(path, M_DEVBUF);
458 return ret; 458 return ret;
459} 459}
460 460
461/* Destroy a file or directory (directories must be empty). */ 461/* Destroy a file or directory (directories must be empty). */
462int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node) 462int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node)
463{ 463{
464 char *path; 464 char *path;
465 int ret; 465 int ret;
466 466
467 path = join(dir, node); 467 path = join(dir, node);
468 if (path == NULL) 468 if (path == NULL)
469 return ENOMEM; 469 return ENOMEM;
470 470
471 ret = xs_single(t, XS_RM, path, NULL, NULL); 471 ret = xs_single(t, XS_RM, path, NULL, NULL);
472 free(path, M_DEVBUF); 472 free(path, M_DEVBUF);
473 return ret; 473 return ret;
474} 474}
475 475
476/* Start a transaction: changes by others will not be seen during this 476/* Start a transaction: changes by others will not be seen during this
477 * transaction, and changes will not be visible to others until end. 477 * transaction, and changes will not be visible to others until end.
478 * MUST BE CALLED AT IPL_TTY ! 478 * MUST BE CALLED AT IPL_TTY !
479 */ 479 */
480struct xenbus_transaction * 480struct xenbus_transaction *
481xenbus_transaction_start(void) 481xenbus_transaction_start(void)
482{ 482{
483 char *id_str; 483 char *id_str;
484 unsigned long id, err; 484 unsigned long id, err;
485 485
486 err = xs_single(NULL, XS_TRANSACTION_START, "", NULL, &id_str); 486 err = xs_single(NULL, XS_TRANSACTION_START, "", NULL, &id_str);
487 if (err) { 487 if (err) {
488 return NULL; 488 return NULL;
489 } 489 }
490 490
491 id = strtoul(id_str, NULL, 0); 491 id = strtoul(id_str, NULL, 0);
492 free(id_str, M_DEVBUF); 492 free(id_str, M_DEVBUF);
493 493
494 return (struct xenbus_transaction *)id; 494 return (struct xenbus_transaction *)id;
495} 495}
496 496
497/* End a transaction. 497/* End a transaction.
498 * If abandon is true, transaction is discarded instead of committed. 498 * If abandon is true, transaction is discarded instead of committed.
499 * MUST BE CALLED AT IPL_TTY ! 499 * MUST BE CALLED AT IPL_TTY !
500 */ 500 */
501int xenbus_transaction_end(struct xenbus_transaction *t, int abort) 501int xenbus_transaction_end(struct xenbus_transaction *t, int abort)
502{ 502{
503 char abortstr[2]; 503 char abortstr[2];
504 int err; 504 int err;
505 505
506 if (abort) 506 if (abort)
507 strcpy(abortstr, "F"); 507 strcpy(abortstr, "F");
508 else 508 else
509 strcpy(abortstr, "T"); 509 strcpy(abortstr, "T");
510 510
511 err = xs_single(t, XS_TRANSACTION_END, abortstr, NULL, NULL); 511 err = xs_single(t, XS_TRANSACTION_END, abortstr, NULL, NULL);
512 512
513 return err; 513 return err;
514} 514}
515 515
516/* Single read and scanf: returns -errno or num scanned. */ 516/* Single read and scanf: returns -errno or num scanned. */
517int 517int
518xenbus_scanf(struct xenbus_transaction *t, 518xenbus_scanf(struct xenbus_transaction *t,
519 const char *dir, const char *node, const char *fmt, ...) 519 const char *dir, const char *node, const char *fmt, ...)
520{ 520{
521 va_list ap; 521 va_list ap;
522 int ret; 522 int ret;
523 char *val; 523 char *val;
524 524
525 ret = xenbus_read(t, dir, node, NULL, &val); 525 ret = xenbus_read(t, dir, node, NULL, &val);
526 if (ret) 526 if (ret)
527 return ret; 527 return ret;
528 528
529 va_start(ap, fmt); 529 va_start(ap, fmt);
530 //ret = vsscanf(val, fmt, ap); 530 //ret = vsscanf(val, fmt, ap);
531 ret = ENXIO; 531 ret = ENXIO;
532 printf("xb_scanf format %s in %s\n", fmt, val); 532 printf("xb_scanf format %s in %s\n", fmt, val);
533 va_end(ap); 533 va_end(ap);
534 free(val, M_DEVBUF); 534 free(val, M_DEVBUF);
535 return ret; 535 return ret;
536} 536}
537 537
538/* Single printf and write: returns -errno or 0. */ 538/* Single printf and write: returns -errno or 0. */
539int 539int
540xenbus_printf(struct xenbus_transaction *t, 540xenbus_printf(struct xenbus_transaction *t,
541 const char *dir, const char *node, const char *fmt, ...) 541 const char *dir, const char *node, const char *fmt, ...)
542{ 542{
543 va_list ap; 543 va_list ap;
544 int ret; 544 int ret;
545#define PRINTF_BUFFER_SIZE 4096 545#define PRINTF_BUFFER_SIZE 4096
546 char *printf_buffer; 546 char *printf_buffer;
547 547
548 printf_buffer = malloc(PRINTF_BUFFER_SIZE, M_DEVBUF, M_NOWAIT); 548 printf_buffer = malloc(PRINTF_BUFFER_SIZE, M_DEVBUF, M_NOWAIT);
549 if (printf_buffer == NULL) 549 if (printf_buffer == NULL)
550 return ENOMEM; 550 return ENOMEM;
551 551
552 va_start(ap, fmt); 552 va_start(ap, fmt);
553 ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap); 553 ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap);
554 va_end(ap); 554 va_end(ap);
555 555
556 KASSERT(ret < PRINTF_BUFFER_SIZE); 556 KASSERT(ret < PRINTF_BUFFER_SIZE);
557 ret = xenbus_write(t, dir, node, printf_buffer); 557 ret = xenbus_write(t, dir, node, printf_buffer);
558 558
559 free(printf_buffer, M_DEVBUF); 559 free(printf_buffer, M_DEVBUF);
560 560
561 return ret; 561 return ret;
562} 562}
563 563
564/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */ 564/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
565int 565int
566xenbus_gather(struct xenbus_transaction *t, const char *dir, ...) 566xenbus_gather(struct xenbus_transaction *t, const char *dir, ...)
567{ 567{
568 va_list ap; 568 va_list ap;
569 const char *name; 569 const char *name;
570 int ret = 0; 570 int ret = 0;
571 571
572 va_start(ap, dir); 572 va_start(ap, dir);
573 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) { 573 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
574 const char *fmt = va_arg(ap, char *); 574 const char *fmt = va_arg(ap, char *);
575 void *result = va_arg(ap, void *); 575 void *result = va_arg(ap, void *);
576 char *p; 576 char *p;
577 577
578 ret = xenbus_read(t, dir, name, NULL, &p); 578 ret = xenbus_read(t, dir, name, NULL, &p);
579 if (ret) 579 if (ret)
580 break; 580 break;
581 if (fmt) { 581 if (fmt) {
582 // XXX if (sscanf(p, fmt, result) == 0) 582 // XXX if (sscanf(p, fmt, result) == 0)
583 ret = -EINVAL; 583 ret = -EINVAL;
584 free(p, M_DEVBUF); 584 free(p, M_DEVBUF);
585 } else 585 } else
586 *(char **)result = p; 586 *(char **)result = p;
587 } 587 }
588 va_end(ap); 588 va_end(ap);
589 return ret; 589 return ret;
590} 590}
591 591
592static int 592static int
593xs_watch(const char *path, const char *token) 593xs_watch(const char *path, const char *token)
594{ 594{
595 struct iovec iov[2]; 595 struct iovec iov[2];
596 596
597 /* xs_talkv only reads iovec */ 597 /* xs_talkv only reads iovec */
598 iov[0].iov_base = __UNCONST(path); 598 iov[0].iov_base = __UNCONST(path);
599 iov[0].iov_len = strlen(path) + 1; 599 iov[0].iov_len = strlen(path) + 1;
600 iov[1].iov_base = __UNCONST(token); 600 iov[1].iov_base = __UNCONST(token);
601 iov[1].iov_len = strlen(token) + 1; 601 iov[1].iov_len = strlen(token) + 1;
602 602
603 return xs_talkv(NULL, XS_WATCH, iov, 2, NULL, NULL); 603 return xs_talkv(NULL, XS_WATCH, iov, 2, NULL, NULL);
604} 604}
605 605
606static int 606static int
607xs_unwatch(const char *path, const char *token) 607xs_unwatch(const char *path, const char *token)
608{ 608{
609 struct iovec iov[2]; 609 struct iovec iov[2];
610 610
611 /* xs_talkv only reads iovec */ 611 /* xs_talkv only reads iovec */
612 iov[0].iov_base = __UNCONST(path); 612 iov[0].iov_base = __UNCONST(path);
613 iov[0].iov_len = strlen(path) + 1; 613 iov[0].iov_len = strlen(path) + 1;
614 iov[1].iov_base = __UNCONST(token); 614 iov[1].iov_base = __UNCONST(token);
615 iov[1].iov_len = strlen(token) + 1; 615 iov[1].iov_len = strlen(token) + 1;
616 616
617 return xs_talkv(NULL, XS_UNWATCH, iov, 2, NULL, NULL); 617 return xs_talkv(NULL, XS_UNWATCH, iov, 2, NULL, NULL);
618} 618}
619 619
620static struct xenbus_watch * 620static struct xenbus_watch *
621find_watch(const char *token) 621find_watch(const char *token)
622{ 622{
623 struct xenbus_watch *i, *cmp; 623 struct xenbus_watch *i, *cmp;
624 624
625 cmp = (void *)strtoul(token, NULL, 16); 625 cmp = (void *)strtoul(token, NULL, 16);
626 626
627 SLIST_FOREACH(i, &watches, watch_next) { 627 SLIST_FOREACH(i, &watches, watch_next) {
628 if (i == cmp) 628 if (i == cmp)
629 return i; 629 return i;
630 } 630 }
631 631
632 return NULL; 632 return NULL;
633} 633}
634 634
635/* Register callback to watch this node. */ 635/* Register callback to watch this node. */
636int 636int
637register_xenbus_watch(struct xenbus_watch *watch) 637register_xenbus_watch(struct xenbus_watch *watch)
638{ 638{
639 /* Pointer in ascii is the token. */ 639 /* Pointer in ascii is the token. */
640 char token[sizeof(watch) * 2 + 1]; 640 char token[sizeof(watch) * 2 + 1];
641 int err; 641 int err;
642 642
643 snprintf(token, sizeof(token), "%lX", (long)watch); 643 snprintf(token, sizeof(token), "%lX", (long)watch);
644 644
645 mutex_enter(&watches_lock); 645 mutex_enter(&watches_lock);
646 KASSERT(find_watch(token) == 0); 646 KASSERT(find_watch(token) == 0);
647 SLIST_INSERT_HEAD(&watches, watch, watch_next); 647 SLIST_INSERT_HEAD(&watches, watch, watch_next);
648 mutex_exit(&watches_lock); 648 mutex_exit(&watches_lock);
649 649
650 err = xs_watch(watch->node, token); 650 err = xs_watch(watch->node, token);
651 651
652 /* Ignore errors due to multiple registration. */ 652 /* Ignore errors due to multiple registration. */
653 if ((err != 0) && (err != EEXIST)) { 653 if ((err != 0) && (err != EEXIST)) {
654 mutex_enter(&watches_lock); 654 mutex_enter(&watches_lock);
655 SLIST_REMOVE(&watches, watch, xenbus_watch, watch_next); 655 SLIST_REMOVE(&watches, watch, xenbus_watch, watch_next);
656 mutex_exit(&watches_lock); 656 mutex_exit(&watches_lock);
657 } 657 }
658 return err; 658 return err;
659} 659}
660 660
661void 661void
662unregister_xenbus_watch(struct xenbus_watch *watch) 662unregister_xenbus_watch(struct xenbus_watch *watch)
663{ 663{
664 SIMPLEQ_HEAD(, xs_stored_msg) gclist; 664 SIMPLEQ_HEAD(, xs_stored_msg) gclist;
665 struct xs_stored_msg *msg, *next_msg; 665 struct xs_stored_msg *msg, *next_msg;
666 char token[sizeof(watch) * 2 + 1]; 666 char token[sizeof(watch) * 2 + 1];
667 int err; 667 int err;
668 668
669 snprintf(token, sizeof(token), "%lX", (long)watch); 669 snprintf(token, sizeof(token), "%lX", (long)watch);
670 670
671 mutex_enter(&watches_lock); 671 mutex_enter(&watches_lock);
672 KASSERT(find_watch(token)); 672 KASSERT(find_watch(token));
673 SLIST_REMOVE(&watches, watch, xenbus_watch, watch_next); 673 SLIST_REMOVE(&watches, watch, xenbus_watch, watch_next);
674 mutex_exit(&watches_lock); 674 mutex_exit(&watches_lock);
675 675
676 err = xs_unwatch(watch->node, token); 676 err = xs_unwatch(watch->node, token);
677 if (err) { 677 if (err) {
678 printf( 678 printf(
679 "XENBUS Failed to release watch %s: %i\n", 679 "XENBUS Failed to release watch %s: %i\n",
680 watch->node, err); 680 watch->node, err);
681 } 681 }
682 682
683 /* Cancel pending watch events. */ 683 /* Cancel pending watch events. */
684 SIMPLEQ_INIT(&gclist); 684 SIMPLEQ_INIT(&gclist);
685 mutex_enter(&watch_events_lock); 685 mutex_enter(&watch_events_lock);
686 for (msg = SIMPLEQ_FIRST(&watch_events); msg != NULL; msg = next_msg) { 686 for (msg = SIMPLEQ_FIRST(&watch_events); msg != NULL; msg = next_msg) {
687 next_msg = SIMPLEQ_NEXT(msg, msg_next); 687 next_msg = SIMPLEQ_NEXT(msg, msg_next);
688 if (msg->u.watch.handle != watch) 688 if (msg->u.watch.handle != watch)
689 continue; 689 continue;
690 SIMPLEQ_REMOVE(&watch_events, msg, xs_stored_msg, msg_next); 690 SIMPLEQ_REMOVE(&watch_events, msg, xs_stored_msg, msg_next);
691 SIMPLEQ_INSERT_TAIL(&gclist, msg, msg_next); 691 SIMPLEQ_INSERT_TAIL(&gclist, msg, msg_next);
692 } 692 }
693 mutex_exit(&watch_events_lock); 693 mutex_exit(&watch_events_lock);
694 694
695 while ((msg = SIMPLEQ_FIRST(&gclist)) != NULL) { 695 while ((msg = SIMPLEQ_FIRST(&gclist)) != NULL) {
696 SIMPLEQ_REMOVE(&gclist, msg, xs_stored_msg, msg_next); 696 SIMPLEQ_REMOVE(&gclist, msg, xs_stored_msg, msg_next);
697 free(msg->u.watch.vec, M_DEVBUF); 697 free(msg->u.watch.vec, M_DEVBUF);
698 free(msg, M_DEVBUF); 698 free(msg, M_DEVBUF);
699 } 699 }
700} 700}
701 701
702void 702void
703xs_suspend(void) 703xs_suspend(void)
704{ 704{
705 xs_state.suspend_spl = spltty(); 705 xs_state.suspend_spl = spltty();
706} 706}
707 707
708void 708void
709xs_resume(void) 709xs_resume(void)
710{ 710{
711 struct xenbus_watch *watch; 711 struct xenbus_watch *watch;
712 char token[sizeof(watch) * 2 + 1]; 712 char token[sizeof(watch) * 2 + 1];
713 /* No need for watches_lock: the suspend_mutex is sufficient. */ 713 /* No need for watches_lock: the suspend_mutex is sufficient. */
714 SLIST_FOREACH(watch, &watches, watch_next) { 714 SLIST_FOREACH(watch, &watches, watch_next) {
715 snprintf(token, sizeof(token), "%lX", (long)watch); 715 snprintf(token, sizeof(token), "%lX", (long)watch);
716 xs_watch(watch->node, token); 716 xs_watch(watch->node, token);
717 } 717 }
718 718
719 splx(xs_state.suspend_spl); 719 splx(xs_state.suspend_spl);
720} 720}
721 721
722static void 722static void
723xenwatch_thread(void *unused) 723xenwatch_thread(void *unused)
724{ 724{
725 SIMPLEQ_HEAD(, xs_stored_msg) events_to_proces; 725 SIMPLEQ_HEAD(, xs_stored_msg) events_to_proces;
726 struct xs_stored_msg *msg; 726 struct xs_stored_msg *msg;
727 727
728 SIMPLEQ_INIT(&events_to_proces); 728 SIMPLEQ_INIT(&events_to_proces);
729 for (;;) { 729 for (;;) {
730 mutex_enter(&watch_events_lock); 730 mutex_enter(&watch_events_lock);
731 while (SIMPLEQ_EMPTY(&watch_events)) 731 while (SIMPLEQ_EMPTY(&watch_events))
732 cv_wait(&watch_cv, &watch_events_lock); 732 cv_wait(&watch_cv, &watch_events_lock);
733 SIMPLEQ_CONCAT(&events_to_proces, &watch_events); 733 SIMPLEQ_CONCAT(&events_to_proces, &watch_events);
734 mutex_exit(&watch_events_lock); 734 mutex_exit(&watch_events_lock);
735 735
736 DPRINTK("xenwatch_thread: processing events"); 736 DPRINTK("xenwatch_thread: processing events");
737 737
738 while ((msg = SIMPLEQ_FIRST(&events_to_proces)) != NULL) { 738 while ((msg = SIMPLEQ_FIRST(&events_to_proces)) != NULL) {
739 DPRINTK("xenwatch_thread: got event"); 739 DPRINTK("xenwatch_thread: got event");
740 SIMPLEQ_REMOVE_HEAD(&events_to_proces, msg_next); 740 SIMPLEQ_REMOVE_HEAD(&events_to_proces, msg_next);
741 msg->u.watch.handle->xbw_callback( 741 msg->u.watch.handle->xbw_callback(
742 msg->u.watch.handle, 742 msg->u.watch.handle,
743 (const char **)msg->u.watch.vec, 743 (void *)msg->u.watch.vec,
744 msg->u.watch.vec_size); 744 msg->u.watch.vec_size);
745 free(msg->u.watch.vec, M_DEVBUF); 745 free(msg->u.watch.vec, M_DEVBUF);
746 free(msg, M_DEVBUF); 746 free(msg, M_DEVBUF);
747 } 747 }
748 } 748 }
749} 749}
750 750
751static int 751static int
752process_msg(void) 752process_msg(void)
753{ 753{
754 struct xs_stored_msg *msg; 754 struct xs_stored_msg *msg;
755 char *body; 755 char *body;
756 int err; 756 int err;
757 757
758 msg = malloc(sizeof(*msg), M_DEVBUF, M_NOWAIT); 758 msg = malloc(sizeof(*msg), M_DEVBUF, M_NOWAIT);
759 if (msg == NULL) 759 if (msg == NULL)
760 return ENOMEM; 760 return ENOMEM;
761 761
762 err = xb_read(&msg->hdr, sizeof(msg->hdr)); 762 err = xb_read(&msg->hdr, sizeof(msg->hdr));
763 DPRINTK("xb_read hdr %d", err); 763 DPRINTK("xb_read hdr %d", err);
764 if (err) { 764 if (err) {
765 free(msg, M_DEVBUF); 765 free(msg, M_DEVBUF);
766 return err; 766 return err;
767 } 767 }
768 768
769 body = malloc(msg->hdr.len + 1, M_DEVBUF, M_NOWAIT); 769 body = malloc(msg->hdr.len + 1, M_DEVBUF, M_NOWAIT);
770 if (body == NULL) { 770 if (body == NULL) {
771 free(msg, M_DEVBUF); 771 free(msg, M_DEVBUF);
772 return ENOMEM; 772 return ENOMEM;
773 } 773 }
774 774
775 err = xb_read(body, msg->hdr.len); 775 err = xb_read(body, msg->hdr.len);
776 DPRINTK("xb_read body %d", err); 776 DPRINTK("xb_read body %d", err);
777 if (err) { 777 if (err) {
778 free(body, M_DEVBUF); 778 free(body, M_DEVBUF);
779 free(msg, M_DEVBUF); 779 free(msg, M_DEVBUF);
780 return err; 780 return err;
781 } 781 }
782 body[msg->hdr.len] = '\0'; 782 body[msg->hdr.len] = '\0';
783 783
784 if (msg->hdr.type == XS_WATCH_EVENT) { 784 if (msg->hdr.type == XS_WATCH_EVENT) {
785 bool found; 785 bool found;
786 786
787 DPRINTK("process_msg: XS_WATCH_EVENT"); 787 DPRINTK("process_msg: XS_WATCH_EVENT");
788 msg->u.watch.vec = split(body, msg->hdr.len, 788 msg->u.watch.vec = split(body, msg->hdr.len,
789 &msg->u.watch.vec_size); 789 &msg->u.watch.vec_size);
790 if (msg->u.watch.vec == NULL) { 790 if (msg->u.watch.vec == NULL) {
791 free(msg, M_DEVBUF); 791 free(msg, M_DEVBUF);
792 return ENOMEM; 792 return ENOMEM;
793 } 793 }
794 794
795 mutex_enter(&watches_lock); 795 mutex_enter(&watches_lock);
796 msg->u.watch.handle = find_watch( 796 msg->u.watch.handle = find_watch(
797 msg->u.watch.vec[XS_WATCH_TOKEN]); 797 msg->u.watch.vec[XS_WATCH_TOKEN]);
798 found = (msg->u.watch.handle != NULL); 798 found = (msg->u.watch.handle != NULL);
799 if (found) { 799 if (found) {
800 mutex_enter(&watch_events_lock); 800 mutex_enter(&watch_events_lock);
801 SIMPLEQ_INSERT_TAIL(&watch_events, msg, msg_next); 801 SIMPLEQ_INSERT_TAIL(&watch_events, msg, msg_next);
802 cv_broadcast(&watch_cv); 802 cv_broadcast(&watch_cv);
803 mutex_exit(&watch_events_lock); 803 mutex_exit(&watch_events_lock);
804 } 804 }
805 mutex_exit(&watches_lock); 805 mutex_exit(&watches_lock);
806 if (!found) { 806 if (!found) {
807 free(msg->u.watch.vec, M_DEVBUF); 807 free(msg->u.watch.vec, M_DEVBUF);
808 free(msg, M_DEVBUF); 808 free(msg, M_DEVBUF);
809 } 809 }
810 } else { 810 } else {
811 DPRINTK("process_msg: type %d body %s", msg->hdr.type, body); 811 DPRINTK("process_msg: type %d body %s", msg->hdr.type, body);
812 812
813 msg->u.reply.body = body; 813 msg->u.reply.body = body;
814 mutex_enter(&xs_state.reply_lock); 814 mutex_enter(&xs_state.reply_lock);
815 SIMPLEQ_INSERT_TAIL(&xs_state.reply_list, msg, msg_next); 815 SIMPLEQ_INSERT_TAIL(&xs_state.reply_list, msg, msg_next);
816 cv_broadcast(&xs_state.reply_cv); 816 cv_broadcast(&xs_state.reply_cv);
817 mutex_exit(&xs_state.reply_lock); 817 mutex_exit(&xs_state.reply_lock);
818 } 818 }
819 819
820 return 0; 820 return 0;
821} 821}
822 822
823static void 823static void
824xenbus_thread(void *unused) 824xenbus_thread(void *unused)
825{ 825{
826 int err; 826 int err;
827 827
828 for (;;) { 828 for (;;) {
829 err = process_msg(); 829 err = process_msg();
830 if (err) 830 if (err)
831 printk("XENBUS error %d while reading message\n", err); 831 printk("XENBUS error %d while reading message\n", err);
832 } 832 }
833} 833}
834 834
835int 835int
836xs_init(device_t dev) 836xs_init(device_t dev)
837{ 837{
838 int err; 838 int err;
839 839
840 SLIST_INIT(&watches); 840 SLIST_INIT(&watches);
841 mutex_init(&watches_lock, MUTEX_DEFAULT, IPL_TTY); 841 mutex_init(&watches_lock, MUTEX_DEFAULT, IPL_TTY);
842 842
843 SIMPLEQ_INIT(&watch_events); 843 SIMPLEQ_INIT(&watch_events);
844 mutex_init(&watch_events_lock, MUTEX_DEFAULT, IPL_TTY); 844 mutex_init(&watch_events_lock, MUTEX_DEFAULT, IPL_TTY);
845 cv_init(&watch_cv, "evtsq"); 845 cv_init(&watch_cv, "evtsq");
846 846
847 SIMPLEQ_INIT(&xs_state.reply_list); 847 SIMPLEQ_INIT(&xs_state.reply_list);
848 mutex_init(&xs_state.xs_lock, MUTEX_DEFAULT, IPL_NONE); 848 mutex_init(&xs_state.xs_lock, MUTEX_DEFAULT, IPL_NONE);
849 mutex_init(&xs_state.reply_lock, MUTEX_DEFAULT, IPL_TTY); 849 mutex_init(&xs_state.reply_lock, MUTEX_DEFAULT, IPL_TTY);
850 cv_init(&xs_state.reply_cv, "rplq"); 850 cv_init(&xs_state.reply_cv, "rplq");
851 851
852 err = kthread_create(PRI_NONE, 0, NULL, xenwatch_thread, 852 err = kthread_create(PRI_NONE, 0, NULL, xenwatch_thread,
853 NULL, NULL, "xenwatch"); 853 NULL, NULL, "xenwatch");
854 if (err) { 854 if (err) {
855 aprint_error_dev(dev, "kthread_create(xenwatch): %d\n", err); 855 aprint_error_dev(dev, "kthread_create(xenwatch): %d\n", err);
856 return err; 856 return err;
857 } 857 }
858 858
859 err = kthread_create(PRI_NONE, 0, NULL, xenbus_thread, 859 err = kthread_create(PRI_NONE, 0, NULL, xenbus_thread,
860 NULL, NULL, "xenbus"); 860 NULL, NULL, "xenbus");
861 if (err) { 861 if (err) {
862 aprint_error_dev(dev, "kthread_create(xenbus): %d\n", err); 862 aprint_error_dev(dev, "kthread_create(xenbus): %d\n", err);
863 return err; 863 return err;
864 } 864 }
865 865
866 return 0; 866 return 0;
867} 867}
868 868
869/* 869/*
870 * Local variables: 870 * Local variables:
871 * c-file-style: "linux" 871 * c-file-style: "linux"
872 * indent-tabs-mode: t 872 * indent-tabs-mode: t
873 * c-indent-level: 8 873 * c-indent-level: 8
874 * c-basic-offset: 8 874 * c-basic-offset: 8
875 * tab-width: 8 875 * tab-width: 8
876 * End: 876 * End:
877 */ 877 */