15084Sjohnlev /*
25084Sjohnlev * CDDL HEADER START
35084Sjohnlev *
45084Sjohnlev * The contents of this file are subject to the terms of the
55084Sjohnlev * Common Development and Distribution License (the "License").
65084Sjohnlev * You may not use this file except in compliance with the License.
75084Sjohnlev *
85084Sjohnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95084Sjohnlev * or http://www.opensolaris.org/os/licensing.
105084Sjohnlev * See the License for the specific language governing permissions
115084Sjohnlev * and limitations under the License.
125084Sjohnlev *
135084Sjohnlev * When distributing Covered Code, include this CDDL HEADER in each
145084Sjohnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155084Sjohnlev * If applicable, add the following below this CDDL HEADER, with the
165084Sjohnlev * fields enclosed by brackets "[]" replaced with your own identifying
175084Sjohnlev * information: Portions Copyright [yyyy] [name of copyright owner]
185084Sjohnlev *
195084Sjohnlev * CDDL HEADER END
205084Sjohnlev */
215084Sjohnlev
225084Sjohnlev /*
23*8863SEdward.Pilatowicz@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
245084Sjohnlev * Use is subject to license terms.
255084Sjohnlev */
265084Sjohnlev
275084Sjohnlev /*
285084Sjohnlev * Talks to Xen Store to figure out what devices we have.
295084Sjohnlev *
305084Sjohnlev * Copyright (C) 2005 Rusty Russell, IBM Corporation
315084Sjohnlev * Copyright (C) 2005 Mike Wray, Hewlett-Packard
325084Sjohnlev * Copyright (C) 2005 XenSource Ltd
335084Sjohnlev *
345084Sjohnlev * This file may be distributed separately from the Linux kernel, or
355084Sjohnlev * incorporated into other software packages, subject to the following license:
365084Sjohnlev *
375084Sjohnlev * Permission is hereby granted, free of charge, to any person obtaining a copy
385084Sjohnlev * of this source file (the "Software"), to deal in the Software without
395084Sjohnlev * restriction, including without limitation the rights to use, copy, modify,
405084Sjohnlev * merge, publish, distribute, sublicense, and/or sell copies of the Software,
415084Sjohnlev * and to permit persons to whom the Software is furnished to do so, subject to
425084Sjohnlev * the following conditions:
435084Sjohnlev *
445084Sjohnlev * The above copyright notice and this permission notice shall be included in
455084Sjohnlev * all copies or substantial portions of the Software.
465084Sjohnlev *
475084Sjohnlev * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
485084Sjohnlev * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
495084Sjohnlev * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
505084Sjohnlev * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
515084Sjohnlev * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
525084Sjohnlev * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
535084Sjohnlev * IN THE SOFTWARE.
545084Sjohnlev */
555084Sjohnlev
565741Smrj #ifdef XPV_HVM_DRIVER
575741Smrj #include <sys/xpv_support.h>
585741Smrj #endif
595084Sjohnlev #include <sys/hypervisor.h>
605084Sjohnlev #include <xen/sys/xenbus_impl.h>
615084Sjohnlev #include <xen/sys/xenbus_comms.h>
625084Sjohnlev #include <xen/public/io/xs_wire.h>
635084Sjohnlev
645084Sjohnlev static int
read_otherend_details(struct xenbus_device * xendev,char * id_node,char * path_node)655084Sjohnlev read_otherend_details(struct xenbus_device *xendev,
665084Sjohnlev char *id_node, char *path_node)
675084Sjohnlev {
685084Sjohnlev int err = xenbus_gather(XBT_NULL, xendev->nodename,
695084Sjohnlev id_node, "%i", &xendev->otherend_id, path_node, NULL,
705084Sjohnlev &xendev->otherend, NULL);
715084Sjohnlev if (err) {
725084Sjohnlev xenbus_dev_fatal(xendev, err,
735084Sjohnlev "reading other end details from %s", xendev->nodename);
745084Sjohnlev return (err);
755084Sjohnlev }
765084Sjohnlev if (strlen(xendev->otherend) == 0 ||
77*8863SEdward.Pilatowicz@Sun.COM !xenbus_exists_dir(xendev->otherend, "")) {
785084Sjohnlev xenbus_dev_fatal(xendev, X_ENOENT, "missing other end from %s",
795084Sjohnlev xendev->nodename);
805084Sjohnlev kmem_free((void *)xendev->otherend,
815084Sjohnlev strlen(xendev->otherend) + 1);
825084Sjohnlev xendev->otherend = NULL;
835084Sjohnlev return (X_ENOENT);
845084Sjohnlev }
855084Sjohnlev
865084Sjohnlev return (0);
875084Sjohnlev }
885084Sjohnlev
895084Sjohnlev
905084Sjohnlev static int
read_backend_details(struct xenbus_device * xendev)915084Sjohnlev read_backend_details(struct xenbus_device *xendev)
925084Sjohnlev {
935084Sjohnlev return (read_otherend_details(xendev, "backend-id", "backend"));
945084Sjohnlev }
955084Sjohnlev
965084Sjohnlev
975084Sjohnlev static int
read_frontend_details(struct xenbus_device * xendev)985084Sjohnlev read_frontend_details(struct xenbus_device *xendev)
995084Sjohnlev {
1005084Sjohnlev return (read_otherend_details(xendev, "frontend-id", "frontend"));
1015084Sjohnlev }
1025084Sjohnlev
1035084Sjohnlev
1045084Sjohnlev static void
free_otherend_details(struct xenbus_device * dev)1055084Sjohnlev free_otherend_details(struct xenbus_device *dev)
1065084Sjohnlev {
1075084Sjohnlev if (dev->otherend != NULL) {
1085084Sjohnlev kmem_free((void *)dev->otherend, strlen(dev->otherend) + 1);
1095084Sjohnlev dev->otherend = NULL;
1105084Sjohnlev }
1115084Sjohnlev }
1125084Sjohnlev
1135084Sjohnlev
1145084Sjohnlev static void
free_otherend_watch(struct xenbus_device * dev)1155084Sjohnlev free_otherend_watch(struct xenbus_device *dev)
1165084Sjohnlev {
1175084Sjohnlev if (dev->otherend_watch.node) {
1185084Sjohnlev unregister_xenbus_watch(&dev->otherend_watch);
1195084Sjohnlev kmem_free((void *)dev->otherend_watch.node,
1205084Sjohnlev strlen(dev->otherend_watch.node) + 1);
1215084Sjohnlev dev->otherend_watch.node = NULL;
1225084Sjohnlev }
1235084Sjohnlev }
1245084Sjohnlev
1255084Sjohnlev
1265084Sjohnlev /*ARGSUSED2*/
1275084Sjohnlev static void
otherend_changed(struct xenbus_watch * watch,const char ** vec,unsigned int len)1285084Sjohnlev otherend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len)
1295084Sjohnlev {
1305084Sjohnlev struct xenbus_device *dev = watch->dev;
1315084Sjohnlev XenbusState state;
1325084Sjohnlev
1335084Sjohnlev /*
1345084Sjohnlev * Protect us against watches firing on old details when the otherend
1355084Sjohnlev * details change, say immediately after a resume.
1365084Sjohnlev */
1375084Sjohnlev if (!dev->otherend ||
1385084Sjohnlev strncmp(dev->otherend, vec[XS_WATCH_PATH], strlen(dev->otherend))) {
1395084Sjohnlev #if 0
1405084Sjohnlev printf("Ignoring watch at %s", vec[XS_WATCH_PATH]);
1415084Sjohnlev #endif
1425084Sjohnlev return;
1435084Sjohnlev }
1445084Sjohnlev
1455084Sjohnlev state = xenbus_read_driver_state(dev->otherend);
1465084Sjohnlev
1475084Sjohnlev #if 0
1485084Sjohnlev printf("state is %d, %s, %s",
1495084Sjohnlev state, dev->otherend_watch.node, vec[XS_WATCH_PATH]);
1505084Sjohnlev #endif
1515084Sjohnlev if (dev->otherend_changed)
1525084Sjohnlev dev->otherend_changed(dev, state);
1535084Sjohnlev }
1545084Sjohnlev
1555084Sjohnlev
1565084Sjohnlev int
talk_to_otherend(struct xenbus_device * dev)1575084Sjohnlev talk_to_otherend(struct xenbus_device *dev)
1585084Sjohnlev {
1595084Sjohnlev int err;
1605084Sjohnlev
1615084Sjohnlev free_otherend_watch(dev);
1625084Sjohnlev free_otherend_details(dev);
1635084Sjohnlev
1645084Sjohnlev if (dev->frontend)
1655084Sjohnlev err = read_backend_details(dev);
1665084Sjohnlev else
1675084Sjohnlev err = read_frontend_details(dev);
1685084Sjohnlev if (err)
1695084Sjohnlev return (err);
1705084Sjohnlev
1715084Sjohnlev dev->otherend_watch.dev = dev;
1725084Sjohnlev return (xenbus_watch_path2(dev, dev->otherend, "state",
1735084Sjohnlev &dev->otherend_watch, otherend_changed));
1745084Sjohnlev }
1755084Sjohnlev
1765084Sjohnlev
1775084Sjohnlev /*
1785084Sjohnlev * Local variables:
1795084Sjohnlev * c-file-style: "solaris"
1805084Sjohnlev * indent-tabs-mode: t
1815084Sjohnlev * c-indent-level: 8
1825084Sjohnlev * c-basic-offset: 8
1835084Sjohnlev * tab-width: 8
1845084Sjohnlev * End:
1855084Sjohnlev */
186