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/*
23 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * Client-facing interface for the Xenbus driver.  In other words, the
29 * interface between the Xenbus and the device-specific code, be it the
30 * frontend or the backend of that driver.
31 *
32 * Copyright (C) 2005 XenSource Ltd
33 *
34 * This file may be distributed separately from the Linux kernel, or
35 * incorporated into other software packages, subject to the following license:
36 *
37 * Permission is hereby granted, free of charge, to any person obtaining a copy
38 * of this source file (the "Software"), to deal in the Software without
39 * restriction, including without limitation the rights to use, copy, modify,
40 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
41 * and to permit persons to whom the Software is furnished to do so, subject to
42 * the following conditions:
43 *
44 * The above copyright notice and this permission notice shall be included in
45 * all copies or substantial portions of the Software.
46 *
47 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
50 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
51 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
52 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
53 * IN THE SOFTWARE.
54 */
55
56#pragma ident	"%Z%%M%	%I%	%E% SMI"
57
58#ifdef XPV_HVM_DRIVER
59#include <sys/xpv_support.h>
60#include <sys/hypervisor.h>
61#else
62#include <sys/hypervisor.h>
63#include <sys/xen_mmu.h>
64#include <sys/evtchn_impl.h>
65#endif
66#include <sys/gnttab.h>
67#include <xen/sys/xenbus_impl.h>
68#include <sys/cmn_err.h>
69
70
71int
72xenbus_watch_path(struct xenbus_device *dev, const char *path,
73			struct xenbus_watch *watch,
74			void (*callback)(struct xenbus_watch *,
75			const char **, unsigned int))
76{
77	int err;
78
79	watch->node = path;
80	watch->callback = callback;
81
82	err = register_xenbus_watch(watch);
83
84	if (err) {
85		watch->node = NULL;
86		watch->callback = NULL;
87		xenbus_dev_fatal(dev, err, "adding watch on %s", path);
88	}
89
90	return (err);
91}
92
93
94int
95xenbus_watch_path2(struct xenbus_device *dev, const char *path,
96			const char *path2, struct xenbus_watch *watch,
97			void (*callback)(struct xenbus_watch *,
98			const char **, unsigned int))
99{
100	int err;
101	char *state;
102
103	state = kmem_alloc(strlen(path) + 1 + strlen(path2) + 1, KM_SLEEP);
104	(void) strcpy(state, path);
105	(void) strcat(state, "/");
106	(void) strcat(state, path2);
107
108	err = xenbus_watch_path(dev, state, watch, callback);
109	if (err)
110		kmem_free(state, strlen(state) + 1);
111	return (err);
112}
113
114/*
115 * Returns 0 on success, -1 if no change was made, or an errno on failure.  We
116 * check whether the state is currently set to the given value, and if not,
117 * then the state is set.  We don't want to unconditionally write the given
118 * state, because we don't want to fire watches unnecessarily.  Furthermore, if
119 * the node has gone, we don't write to it, as the device will be tearing down,
120 * and we don't want to resurrect that directory.
121 *
122 * XXPV: not clear that this is still safe if two threads are racing to update
123 * the state?
124 */
125int
126xenbus_switch_state(struct xenbus_device *dev, xenbus_transaction_t xbt,
127			XenbusState state)
128{
129	int current_state;
130	int err;
131
132	err = xenbus_scanf(xbt, dev->nodename, "state", "%d", &current_state);
133
134	/* XXPV: is this really the right thing to do? */
135	if (err == ENOENT)
136		return (0);
137	if (err)
138		return (err);
139
140	err = -1;
141
142	if ((XenbusState)current_state != state) {
143		err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
144		if (err)
145			xenbus_dev_fatal(dev, err, "writing new state");
146	}
147
148	return (err);
149}
150
151
152/*
153 * Return the path to the error node for the given device, or NULL on failure.
154 * If the value returned is non-NULL, then it is the caller's to kmem_free.
155 */
156static char *
157error_path(struct xenbus_device *dev)
158{
159	char *path_buffer;
160
161	path_buffer = kmem_alloc(strlen("error/") + strlen(dev->nodename) +
162	    1, KM_SLEEP);
163
164	(void) strcpy(path_buffer, "error/");
165	(void) strcpy(path_buffer + strlen("error/"), dev->nodename);
166
167	return (path_buffer);
168}
169
170static void
171common_dev_error(struct xenbus_device *dev, int err, const char *fmt,
172		va_list ap)
173{
174	int ret;
175	unsigned int len;
176	char *printf_buffer = NULL, *path_buffer = NULL;
177
178#define	PRINTF_BUFFER_SIZE 4096
179	printf_buffer = kmem_alloc(PRINTF_BUFFER_SIZE, KM_SLEEP);
180
181	(void) snprintf(printf_buffer, PRINTF_BUFFER_SIZE, "%d ", err);
182	len = strlen(printf_buffer);
183	ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
184
185	ASSERT(len + ret <= PRINTF_BUFFER_SIZE-1);
186	dev->has_error = 1;
187
188	path_buffer = error_path(dev);
189
190	if (path_buffer == NULL) {
191		printf("xenbus: failed to write error node for %s (%s)\n",
192		    dev->nodename, printf_buffer);
193		goto fail;
194	}
195
196	if (xenbus_write(NULL, path_buffer, "error", printf_buffer) != 0) {
197		printf("xenbus: failed to write error node for %s (%s)\n",
198		    dev->nodename, printf_buffer);
199		goto fail;
200	}
201
202fail:
203	if (printf_buffer)
204		kmem_free(printf_buffer, PRINTF_BUFFER_SIZE);
205	if (path_buffer)
206		kmem_free(path_buffer, strlen(path_buffer) + 1);
207}
208
209
210void
211xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
212{
213	va_list ap;
214
215	va_start(ap, fmt);
216	common_dev_error(dev, err, fmt, ap);
217	va_end(ap);
218}
219
220
221void
222xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...)
223{
224	va_list ap;
225
226	va_start(ap, fmt);
227	common_dev_error(dev, err, fmt, ap);
228	va_end(ap);
229
230	(void) xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing);
231}
232
233/* Clear any error. */
234void
235xenbus_dev_ok(struct xenbus_device *dev)
236{
237	if (dev->has_error) {
238		if (xenbus_rm(NULL, dev->nodename, "error") != 0)
239			printf("xenbus: failed to clear error node for %s\n",
240			    dev->nodename);
241		else
242			dev->has_error = 0;
243	}
244}
245
246int
247xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn)
248{
249	int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0);
250	if (err < 0)
251		xenbus_dev_fatal(dev, err, "granting access to ring page");
252	return (err);
253}
254
255
256int
257xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
258{
259	int err;
260
261	err = xen_alloc_unbound_evtchn(dev->otherend_id, port);
262	if (err)
263		xenbus_dev_fatal(dev, err, "allocating event channel");
264	return (err);
265}
266
267
268XenbusState
269xenbus_read_driver_state(const char *path)
270{
271	XenbusState result;
272
273	int err = xenbus_gather(XBT_NULL, path, "state", "%d", &result, NULL);
274	if (err)
275		result = XenbusStateClosed;
276
277	return (result);
278}
279
280
281/*
282 * Local variables:
283 *  c-file-style: "solaris"
284 *  indent-tabs-mode: t
285 *  c-indent-level: 8
286 *  c-basic-offset: 8
287 *  tab-width: 8
288 * End:
289 */
290