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 * Talks to Xen Store to figure out what devices we have. 29 * 30 * Copyright (C) 2005 Rusty Russell, IBM Corporation 31 * Copyright (C) 2005 Mike Wray, Hewlett-Packard 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 #endif 61 #include <sys/hypervisor.h> 62 #include <xen/sys/xenbus_impl.h> 63 #include <xen/sys/xenbus_comms.h> 64 #include <xen/public/io/xs_wire.h> 65 66 static int 67 read_otherend_details(struct xenbus_device *xendev, 68 char *id_node, char *path_node) 69 { 70 int err = xenbus_gather(XBT_NULL, xendev->nodename, 71 id_node, "%i", &xendev->otherend_id, path_node, NULL, 72 &xendev->otherend, NULL); 73 if (err) { 74 xenbus_dev_fatal(xendev, err, 75 "reading other end details from %s", xendev->nodename); 76 return (err); 77 } 78 if (strlen(xendev->otherend) == 0 || 79 !xenbus_exists(XBT_NULL, xendev->otherend, "")) { 80 xenbus_dev_fatal(xendev, X_ENOENT, "missing other end from %s", 81 xendev->nodename); 82 kmem_free((void *)xendev->otherend, 83 strlen(xendev->otherend) + 1); 84 xendev->otherend = NULL; 85 return (X_ENOENT); 86 } 87 88 return (0); 89 } 90 91 92 static int 93 read_backend_details(struct xenbus_device *xendev) 94 { 95 return (read_otherend_details(xendev, "backend-id", "backend")); 96 } 97 98 99 static int 100 read_frontend_details(struct xenbus_device *xendev) 101 { 102 return (read_otherend_details(xendev, "frontend-id", "frontend")); 103 } 104 105 106 static void 107 free_otherend_details(struct xenbus_device *dev) 108 { 109 if (dev->otherend != NULL) { 110 kmem_free((void *)dev->otherend, strlen(dev->otherend) + 1); 111 dev->otherend = NULL; 112 } 113 } 114 115 116 static void 117 free_otherend_watch(struct xenbus_device *dev) 118 { 119 if (dev->otherend_watch.node) { 120 unregister_xenbus_watch(&dev->otherend_watch); 121 kmem_free((void *)dev->otherend_watch.node, 122 strlen(dev->otherend_watch.node) + 1); 123 dev->otherend_watch.node = NULL; 124 } 125 } 126 127 128 /*ARGSUSED2*/ 129 static void 130 otherend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len) 131 { 132 struct xenbus_device *dev = watch->dev; 133 XenbusState state; 134 135 /* 136 * Protect us against watches firing on old details when the otherend 137 * details change, say immediately after a resume. 138 */ 139 if (!dev->otherend || 140 strncmp(dev->otherend, vec[XS_WATCH_PATH], strlen(dev->otherend))) { 141 #if 0 142 printf("Ignoring watch at %s", vec[XS_WATCH_PATH]); 143 #endif 144 return; 145 } 146 147 state = xenbus_read_driver_state(dev->otherend); 148 149 #if 0 150 printf("state is %d, %s, %s", 151 state, dev->otherend_watch.node, vec[XS_WATCH_PATH]); 152 #endif 153 if (dev->otherend_changed) 154 dev->otherend_changed(dev, state); 155 } 156 157 158 int 159 talk_to_otherend(struct xenbus_device *dev) 160 { 161 int err; 162 163 free_otherend_watch(dev); 164 free_otherend_details(dev); 165 166 if (dev->frontend) 167 err = read_backend_details(dev); 168 else 169 err = read_frontend_details(dev); 170 if (err) 171 return (err); 172 173 dev->otherend_watch.dev = dev; 174 return (xenbus_watch_path2(dev, dev->otherend, "state", 175 &dev->otherend_watch, otherend_changed)); 176 } 177 178 179 /* 180 * Local variables: 181 * c-file-style: "solaris" 182 * indent-tabs-mode: t 183 * c-indent-level: 8 184 * c-basic-offset: 8 185 * tab-width: 8 186 * End: 187 */ 188