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