1ff662b5cSJustin T. Gibbs /****************************************************************************** 2ff662b5cSJustin T. Gibbs * Copyright (C) 2005 XenSource Ltd 3ff662b5cSJustin T. Gibbs * 4ff662b5cSJustin T. Gibbs * This file may be distributed separately from the Linux kernel, or 5ff662b5cSJustin T. Gibbs * incorporated into other software packages, subject to the following license: 6ff662b5cSJustin T. Gibbs * 7ff662b5cSJustin T. Gibbs * Permission is hereby granted, free of charge, to any person obtaining a copy 8ff662b5cSJustin T. Gibbs * of this source file (the "Software"), to deal in the Software without 9ff662b5cSJustin T. Gibbs * restriction, including without limitation the rights to use, copy, modify, 10ff662b5cSJustin T. Gibbs * merge, publish, distribute, sublicense, and/or sell copies of the Software, 11ff662b5cSJustin T. Gibbs * and to permit persons to whom the Software is furnished to do so, subject to 12ff662b5cSJustin T. Gibbs * the following conditions: 13ff662b5cSJustin T. Gibbs * 14ff662b5cSJustin T. Gibbs * The above copyright notice and this permission notice shall be included in 15ff662b5cSJustin T. Gibbs * all copies or substantial portions of the Software. 16ff662b5cSJustin T. Gibbs * 17ff662b5cSJustin T. Gibbs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18ff662b5cSJustin T. Gibbs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19ff662b5cSJustin T. Gibbs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20ff662b5cSJustin T. Gibbs * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21ff662b5cSJustin T. Gibbs * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22ff662b5cSJustin T. Gibbs * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23ff662b5cSJustin T. Gibbs * IN THE SOFTWARE. 24ff662b5cSJustin T. Gibbs */ 25ff662b5cSJustin T. Gibbs 26ff662b5cSJustin T. Gibbs /** 27ff662b5cSJustin T. Gibbs * \file xenbus.c 28ff662b5cSJustin T. Gibbs * 29ff662b5cSJustin T. Gibbs * \brief Client-facing interface for the Xenbus driver. 30ff662b5cSJustin T. Gibbs * 31ff662b5cSJustin T. Gibbs * In other words, the interface between the Xenbus and the device-specific 32ff662b5cSJustin T. Gibbs * code, be it the frontend or the backend of that driver. 33ff662b5cSJustin T. Gibbs */ 34ff662b5cSJustin T. Gibbs 35ff662b5cSJustin T. Gibbs #if 0 36ff662b5cSJustin T. Gibbs #define DPRINTK(fmt, args...) \ 37ff662b5cSJustin T. Gibbs printk("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) 38ff662b5cSJustin T. Gibbs #else 39ff662b5cSJustin T. Gibbs #define DPRINTK(fmt, args...) ((void)0) 40ff662b5cSJustin T. Gibbs #endif 41ff662b5cSJustin T. Gibbs 42ff662b5cSJustin T. Gibbs #include <sys/cdefs.h> 43ff662b5cSJustin T. Gibbs __FBSDID("$FreeBSD$"); 44ff662b5cSJustin T. Gibbs 45ff662b5cSJustin T. Gibbs #include <sys/cdefs.h> 46ff662b5cSJustin T. Gibbs #include <sys/param.h> 47ff662b5cSJustin T. Gibbs #include <sys/kernel.h> 48ff662b5cSJustin T. Gibbs #include <sys/types.h> 49ff662b5cSJustin T. Gibbs #include <sys/malloc.h> 50ff662b5cSJustin T. Gibbs #include <sys/libkern.h> 51ff662b5cSJustin T. Gibbs #include <sys/sbuf.h> 52ff662b5cSJustin T. Gibbs 53*76acc41fSJustin T. Gibbs #include <xen/xen-os.h> 54ff662b5cSJustin T. Gibbs #include <xen/hypervisor.h> 55ff662b5cSJustin T. Gibbs #include <xen/evtchn.h> 56ff662b5cSJustin T. Gibbs #include <xen/gnttab.h> 57ff662b5cSJustin T. Gibbs #include <xen/xenbus/xenbusvar.h> 58*76acc41fSJustin T. Gibbs 59ff662b5cSJustin T. Gibbs #include <machine/stdarg.h> 60ff662b5cSJustin T. Gibbs 61ff662b5cSJustin T. Gibbs MALLOC_DEFINE(M_XENBUS, "xenbus", "XenBus Support"); 62ff662b5cSJustin T. Gibbs 63ff662b5cSJustin T. Gibbs /*------------------------- Private Functions --------------------------------*/ 64ff662b5cSJustin T. Gibbs /** 65ff662b5cSJustin T. Gibbs * \brief Construct the error path corresponding to the given XenBus 66ff662b5cSJustin T. Gibbs * device. 67ff662b5cSJustin T. Gibbs * 68ff662b5cSJustin T. Gibbs * \param dev The XenBus device for which we are constructing an error path. 69ff662b5cSJustin T. Gibbs * 70ff662b5cSJustin T. Gibbs * \return On success, the contructed error path. Otherwise NULL. 71ff662b5cSJustin T. Gibbs * 72ff662b5cSJustin T. Gibbs * It is the caller's responsibility to free any returned error path 73ff662b5cSJustin T. Gibbs * node using the M_XENBUS malloc type. 74ff662b5cSJustin T. Gibbs */ 75ff662b5cSJustin T. Gibbs static char * 76ff662b5cSJustin T. Gibbs error_path(device_t dev) 77ff662b5cSJustin T. Gibbs { 78ff662b5cSJustin T. Gibbs char *path_buffer = malloc(strlen("error/") 79ff662b5cSJustin T. Gibbs + strlen(xenbus_get_node(dev)) + 1,M_XENBUS, M_WAITOK); 80ff662b5cSJustin T. Gibbs 81ff662b5cSJustin T. Gibbs strcpy(path_buffer, "error/"); 82ff662b5cSJustin T. Gibbs strcpy(path_buffer + strlen("error/"), xenbus_get_node(dev)); 83ff662b5cSJustin T. Gibbs 84ff662b5cSJustin T. Gibbs return (path_buffer); 85ff662b5cSJustin T. Gibbs } 86ff662b5cSJustin T. Gibbs 87ff662b5cSJustin T. Gibbs /*--------------------------- Public Functions -------------------------------*/ 88ff662b5cSJustin T. Gibbs /*-------- API comments for these methods can be found in xenbusvar.h --------*/ 89ff662b5cSJustin T. Gibbs const char * 90ff662b5cSJustin T. Gibbs xenbus_strstate(XenbusState state) 91ff662b5cSJustin T. Gibbs { 92ff662b5cSJustin T. Gibbs static const char *const name[] = { 93ff662b5cSJustin T. Gibbs [ XenbusStateUnknown ] = "Unknown", 94ff662b5cSJustin T. Gibbs [ XenbusStateInitialising ] = "Initialising", 95ff662b5cSJustin T. Gibbs [ XenbusStateInitWait ] = "InitWait", 96ff662b5cSJustin T. Gibbs [ XenbusStateInitialised ] = "Initialised", 97ff662b5cSJustin T. Gibbs [ XenbusStateConnected ] = "Connected", 98ff662b5cSJustin T. Gibbs [ XenbusStateClosing ] = "Closing", 99ff662b5cSJustin T. Gibbs [ XenbusStateClosed ] = "Closed", 100ff662b5cSJustin T. Gibbs }; 101ff662b5cSJustin T. Gibbs 102ff662b5cSJustin T. Gibbs return ((state < (XenbusStateClosed + 1)) ? name[state] : "INVALID"); 103ff662b5cSJustin T. Gibbs } 104ff662b5cSJustin T. Gibbs 105ff662b5cSJustin T. Gibbs int 106ff662b5cSJustin T. Gibbs xenbus_watch_path(device_t dev, char *path, struct xs_watch *watch, 107283d6f72SJustin T. Gibbs xs_watch_cb_t *callback, uintptr_t callback_data) 108ff662b5cSJustin T. Gibbs { 109ff662b5cSJustin T. Gibbs int error; 110ff662b5cSJustin T. Gibbs 111ff662b5cSJustin T. Gibbs watch->node = path; 112ff662b5cSJustin T. Gibbs watch->callback = callback; 113283d6f72SJustin T. Gibbs watch->callback_data = callback_data; 114ff662b5cSJustin T. Gibbs 115ff662b5cSJustin T. Gibbs error = xs_register_watch(watch); 116ff662b5cSJustin T. Gibbs 117ff662b5cSJustin T. Gibbs if (error) { 118ff662b5cSJustin T. Gibbs watch->node = NULL; 119ff662b5cSJustin T. Gibbs watch->callback = NULL; 120ff662b5cSJustin T. Gibbs xenbus_dev_fatal(dev, error, "adding watch on %s", path); 121ff662b5cSJustin T. Gibbs } 122ff662b5cSJustin T. Gibbs 123ff662b5cSJustin T. Gibbs return (error); 124ff662b5cSJustin T. Gibbs } 125ff662b5cSJustin T. Gibbs 126ff662b5cSJustin T. Gibbs int 127ff662b5cSJustin T. Gibbs xenbus_watch_path2(device_t dev, const char *path, 128ff662b5cSJustin T. Gibbs const char *path2, struct xs_watch *watch, 129283d6f72SJustin T. Gibbs xs_watch_cb_t *callback, uintptr_t callback_data) 130ff662b5cSJustin T. Gibbs { 131ff662b5cSJustin T. Gibbs int error; 132ff662b5cSJustin T. Gibbs char *state = malloc(strlen(path) + 1 + strlen(path2) + 1, 133ff662b5cSJustin T. Gibbs M_XENBUS, M_WAITOK); 134ff662b5cSJustin T. Gibbs 135ff662b5cSJustin T. Gibbs strcpy(state, path); 136ff662b5cSJustin T. Gibbs strcat(state, "/"); 137ff662b5cSJustin T. Gibbs strcat(state, path2); 138ff662b5cSJustin T. Gibbs 139283d6f72SJustin T. Gibbs error = xenbus_watch_path(dev, state, watch, callback, callback_data); 140ff662b5cSJustin T. Gibbs if (error) { 141ff662b5cSJustin T. Gibbs free(state,M_XENBUS); 142ff662b5cSJustin T. Gibbs } 143ff662b5cSJustin T. Gibbs 144ff662b5cSJustin T. Gibbs return (error); 145ff662b5cSJustin T. Gibbs } 146ff662b5cSJustin T. Gibbs 147ff662b5cSJustin T. Gibbs void 148ff662b5cSJustin T. Gibbs xenbus_dev_verror(device_t dev, int err, const char *fmt, va_list ap) 149ff662b5cSJustin T. Gibbs { 150ff662b5cSJustin T. Gibbs int ret; 151ff662b5cSJustin T. Gibbs unsigned int len; 152ff662b5cSJustin T. Gibbs char *printf_buffer = NULL, *path_buffer = NULL; 153ff662b5cSJustin T. Gibbs 154ff662b5cSJustin T. Gibbs #define PRINTF_BUFFER_SIZE 4096 155ff662b5cSJustin T. Gibbs printf_buffer = malloc(PRINTF_BUFFER_SIZE,M_XENBUS, M_WAITOK); 156ff662b5cSJustin T. Gibbs 157ff662b5cSJustin T. Gibbs len = sprintf(printf_buffer, "%i ", err); 158ff662b5cSJustin T. Gibbs ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); 159ff662b5cSJustin T. Gibbs 160ff662b5cSJustin T. Gibbs KASSERT(len + ret <= PRINTF_BUFFER_SIZE-1, ("xenbus error message too big")); 161ff662b5cSJustin T. Gibbs device_printf(dev, "Error %s\n", printf_buffer); 162ff662b5cSJustin T. Gibbs path_buffer = error_path(dev); 163ff662b5cSJustin T. Gibbs 164ff662b5cSJustin T. Gibbs if (path_buffer == NULL) { 165ff662b5cSJustin T. Gibbs printf("xenbus: failed to write error node for %s (%s)\n", 166ff662b5cSJustin T. Gibbs xenbus_get_node(dev), printf_buffer); 167ff662b5cSJustin T. Gibbs goto fail; 168ff662b5cSJustin T. Gibbs } 169ff662b5cSJustin T. Gibbs 170ff662b5cSJustin T. Gibbs if (xs_write(XST_NIL, path_buffer, "error", printf_buffer) != 0) { 171ff662b5cSJustin T. Gibbs printf("xenbus: failed to write error node for %s (%s)\n", 172ff662b5cSJustin T. Gibbs xenbus_get_node(dev), printf_buffer); 173ff662b5cSJustin T. Gibbs goto fail; 174ff662b5cSJustin T. Gibbs } 175ff662b5cSJustin T. Gibbs 176ff662b5cSJustin T. Gibbs fail: 177ff662b5cSJustin T. Gibbs if (printf_buffer) 178ff662b5cSJustin T. Gibbs free(printf_buffer,M_XENBUS); 179ff662b5cSJustin T. Gibbs if (path_buffer) 180ff662b5cSJustin T. Gibbs free(path_buffer,M_XENBUS); 181ff662b5cSJustin T. Gibbs } 182ff662b5cSJustin T. Gibbs 183ff662b5cSJustin T. Gibbs void 184ff662b5cSJustin T. Gibbs xenbus_dev_error(device_t dev, int err, const char *fmt, ...) 185ff662b5cSJustin T. Gibbs { 186ff662b5cSJustin T. Gibbs va_list ap; 187ff662b5cSJustin T. Gibbs 188ff662b5cSJustin T. Gibbs va_start(ap, fmt); 189ff662b5cSJustin T. Gibbs xenbus_dev_verror(dev, err, fmt, ap); 190ff662b5cSJustin T. Gibbs va_end(ap); 191ff662b5cSJustin T. Gibbs } 192ff662b5cSJustin T. Gibbs 193ff662b5cSJustin T. Gibbs void 194ff662b5cSJustin T. Gibbs xenbus_dev_vfatal(device_t dev, int err, const char *fmt, va_list ap) 195ff662b5cSJustin T. Gibbs { 196ff662b5cSJustin T. Gibbs xenbus_dev_verror(dev, err, fmt, ap); 197ff662b5cSJustin T. Gibbs device_printf(dev, "Fatal error. Transitioning to Closing State\n"); 198ff662b5cSJustin T. Gibbs xenbus_set_state(dev, XenbusStateClosing); 199ff662b5cSJustin T. Gibbs } 200ff662b5cSJustin T. Gibbs 201ff662b5cSJustin T. Gibbs void 202ff662b5cSJustin T. Gibbs xenbus_dev_fatal(device_t dev, int err, const char *fmt, ...) 203ff662b5cSJustin T. Gibbs { 204ff662b5cSJustin T. Gibbs va_list ap; 205ff662b5cSJustin T. Gibbs 206ff662b5cSJustin T. Gibbs va_start(ap, fmt); 207ff662b5cSJustin T. Gibbs xenbus_dev_vfatal(dev, err, fmt, ap); 208ff662b5cSJustin T. Gibbs va_end(ap); 209ff662b5cSJustin T. Gibbs } 210ff662b5cSJustin T. Gibbs 211ff662b5cSJustin T. Gibbs int 212ff662b5cSJustin T. Gibbs xenbus_grant_ring(device_t dev, unsigned long ring_mfn, grant_ref_t *refp) 213ff662b5cSJustin T. Gibbs { 214ff662b5cSJustin T. Gibbs int error; 215ff662b5cSJustin T. Gibbs 216ff662b5cSJustin T. Gibbs error = gnttab_grant_foreign_access( 217ff662b5cSJustin T. Gibbs xenbus_get_otherend_id(dev), ring_mfn, 0, refp); 218ff662b5cSJustin T. Gibbs if (error) { 219ff662b5cSJustin T. Gibbs xenbus_dev_fatal(dev, error, "granting access to ring page"); 220ff662b5cSJustin T. Gibbs return (error); 221ff662b5cSJustin T. Gibbs } 222ff662b5cSJustin T. Gibbs 223ff662b5cSJustin T. Gibbs return (0); 224ff662b5cSJustin T. Gibbs } 225ff662b5cSJustin T. Gibbs 226ff662b5cSJustin T. Gibbs XenbusState 227ff662b5cSJustin T. Gibbs xenbus_read_driver_state(const char *path) 228ff662b5cSJustin T. Gibbs { 229ff662b5cSJustin T. Gibbs XenbusState result; 230ff662b5cSJustin T. Gibbs int error; 231ff662b5cSJustin T. Gibbs 232ff662b5cSJustin T. Gibbs error = xs_gather(XST_NIL, path, "state", "%d", &result, NULL); 233ff662b5cSJustin T. Gibbs if (error) 234ff662b5cSJustin T. Gibbs result = XenbusStateClosed; 235ff662b5cSJustin T. Gibbs 236ff662b5cSJustin T. Gibbs return (result); 237ff662b5cSJustin T. Gibbs } 238ff662b5cSJustin T. Gibbs 239ff662b5cSJustin T. Gibbs int 240ff662b5cSJustin T. Gibbs xenbus_dev_is_online(device_t dev) 241ff662b5cSJustin T. Gibbs { 242ff662b5cSJustin T. Gibbs const char *path; 243ff662b5cSJustin T. Gibbs int error; 244ff662b5cSJustin T. Gibbs int value; 245ff662b5cSJustin T. Gibbs 246ff662b5cSJustin T. Gibbs path = xenbus_get_node(dev); 247ff662b5cSJustin T. Gibbs error = xs_gather(XST_NIL, path, "online", "%d", &value, NULL); 248ff662b5cSJustin T. Gibbs if (error != 0) { 249ff662b5cSJustin T. Gibbs /* Default to not online. */ 250ff662b5cSJustin T. Gibbs value = 0; 251ff662b5cSJustin T. Gibbs } 252ff662b5cSJustin T. Gibbs 253ff662b5cSJustin T. Gibbs return (value); 254ff662b5cSJustin T. Gibbs } 255283d6f72SJustin T. Gibbs 256283d6f72SJustin T. Gibbs void 257283d6f72SJustin T. Gibbs xenbus_localend_changed(device_t dev, const char *path) 258283d6f72SJustin T. Gibbs { 259283d6f72SJustin T. Gibbs } 260