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> 43*fdafd315SWarner Losh 44ff662b5cSJustin T. Gibbs #include <sys/param.h> 45ff662b5cSJustin T. Gibbs #include <sys/kernel.h> 46ff662b5cSJustin T. Gibbs #include <sys/types.h> 47ff662b5cSJustin T. Gibbs #include <sys/malloc.h> 48ff662b5cSJustin T. Gibbs #include <sys/libkern.h> 49ff662b5cSJustin T. Gibbs #include <sys/sbuf.h> 50ff662b5cSJustin T. Gibbs 5176acc41fSJustin T. Gibbs #include <xen/xen-os.h> 52ff662b5cSJustin T. Gibbs #include <xen/hypervisor.h> 53ff662b5cSJustin T. Gibbs #include <xen/evtchn.h> 54ff662b5cSJustin T. Gibbs #include <xen/gnttab.h> 55ff662b5cSJustin T. Gibbs #include <xen/xenbus/xenbusvar.h> 5676acc41fSJustin T. Gibbs 57ff662b5cSJustin T. Gibbs #include <machine/stdarg.h> 58ff662b5cSJustin T. Gibbs 59ff662b5cSJustin T. Gibbs MALLOC_DEFINE(M_XENBUS, "xenbus", "XenBus Support"); 60ff662b5cSJustin T. Gibbs 61ff662b5cSJustin T. Gibbs /*------------------------- Private Functions --------------------------------*/ 62ff662b5cSJustin T. Gibbs /** 63ff662b5cSJustin T. Gibbs * \brief Construct the error path corresponding to the given XenBus 64ff662b5cSJustin T. Gibbs * device. 65ff662b5cSJustin T. Gibbs * 66ff662b5cSJustin T. Gibbs * \param dev The XenBus device for which we are constructing an error path. 67ff662b5cSJustin T. Gibbs * 68ff662b5cSJustin T. Gibbs * \return On success, the contructed error path. Otherwise NULL. 69ff662b5cSJustin T. Gibbs * 70ff662b5cSJustin T. Gibbs * It is the caller's responsibility to free any returned error path 71ff662b5cSJustin T. Gibbs * node using the M_XENBUS malloc type. 72ff662b5cSJustin T. Gibbs */ 73ff662b5cSJustin T. Gibbs static char * 74ff662b5cSJustin T. Gibbs error_path(device_t dev) 75ff662b5cSJustin T. Gibbs { 76ff662b5cSJustin T. Gibbs char *path_buffer = malloc(strlen("error/") 77ff662b5cSJustin T. Gibbs + strlen(xenbus_get_node(dev)) + 1,M_XENBUS, M_WAITOK); 78ff662b5cSJustin T. Gibbs 79ff662b5cSJustin T. Gibbs strcpy(path_buffer, "error/"); 80ff662b5cSJustin T. Gibbs strcpy(path_buffer + strlen("error/"), xenbus_get_node(dev)); 81ff662b5cSJustin T. Gibbs 82ff662b5cSJustin T. Gibbs return (path_buffer); 83ff662b5cSJustin T. Gibbs } 84ff662b5cSJustin T. Gibbs 85ff662b5cSJustin T. Gibbs /*--------------------------- Public Functions -------------------------------*/ 86ff662b5cSJustin T. Gibbs /*-------- API comments for these methods can be found in xenbusvar.h --------*/ 87ff662b5cSJustin T. Gibbs const char * 88ff662b5cSJustin T. Gibbs xenbus_strstate(XenbusState state) 89ff662b5cSJustin T. Gibbs { 90ff662b5cSJustin T. Gibbs static const char *const name[] = { 91ff662b5cSJustin T. Gibbs [ XenbusStateUnknown ] = "Unknown", 92ff662b5cSJustin T. Gibbs [ XenbusStateInitialising ] = "Initialising", 93ff662b5cSJustin T. Gibbs [ XenbusStateInitWait ] = "InitWait", 94ff662b5cSJustin T. Gibbs [ XenbusStateInitialised ] = "Initialised", 95ff662b5cSJustin T. Gibbs [ XenbusStateConnected ] = "Connected", 96ff662b5cSJustin T. Gibbs [ XenbusStateClosing ] = "Closing", 97ff662b5cSJustin T. Gibbs [ XenbusStateClosed ] = "Closed", 98ff662b5cSJustin T. Gibbs }; 99ff662b5cSJustin T. Gibbs 100ff662b5cSJustin T. Gibbs return ((state < (XenbusStateClosed + 1)) ? name[state] : "INVALID"); 101ff662b5cSJustin T. Gibbs } 102ff662b5cSJustin T. Gibbs 103ff662b5cSJustin T. Gibbs void 104ff662b5cSJustin T. Gibbs xenbus_dev_verror(device_t dev, int err, const char *fmt, va_list ap) 105ff662b5cSJustin T. Gibbs { 10638731172SJohn Baldwin int ret __diagused; 107ff662b5cSJustin T. Gibbs unsigned int len; 108ff662b5cSJustin T. Gibbs char *printf_buffer = NULL, *path_buffer = NULL; 109ff662b5cSJustin T. Gibbs 110ff662b5cSJustin T. Gibbs #define PRINTF_BUFFER_SIZE 4096 111ff662b5cSJustin T. Gibbs printf_buffer = malloc(PRINTF_BUFFER_SIZE,M_XENBUS, M_WAITOK); 112ff662b5cSJustin T. Gibbs 113ff662b5cSJustin T. Gibbs len = sprintf(printf_buffer, "%i ", err); 114ff662b5cSJustin T. Gibbs ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); 115ff662b5cSJustin T. Gibbs 116ff662b5cSJustin T. Gibbs KASSERT(len + ret <= PRINTF_BUFFER_SIZE-1, ("xenbus error message too big")); 117ff662b5cSJustin T. Gibbs device_printf(dev, "Error %s\n", printf_buffer); 118ff662b5cSJustin T. Gibbs path_buffer = error_path(dev); 119ff662b5cSJustin T. Gibbs 120ff662b5cSJustin T. Gibbs if (path_buffer == NULL) { 121ff662b5cSJustin T. Gibbs printf("xenbus: failed to write error node for %s (%s)\n", 122ff662b5cSJustin T. Gibbs xenbus_get_node(dev), printf_buffer); 123ff662b5cSJustin T. Gibbs goto fail; 124ff662b5cSJustin T. Gibbs } 125ff662b5cSJustin T. Gibbs 126ff662b5cSJustin T. Gibbs if (xs_write(XST_NIL, path_buffer, "error", printf_buffer) != 0) { 127ff662b5cSJustin T. Gibbs printf("xenbus: failed to write error node for %s (%s)\n", 128ff662b5cSJustin T. Gibbs xenbus_get_node(dev), printf_buffer); 129ff662b5cSJustin T. Gibbs goto fail; 130ff662b5cSJustin T. Gibbs } 131ff662b5cSJustin T. Gibbs 132ff662b5cSJustin T. Gibbs fail: 133ff662b5cSJustin T. Gibbs if (printf_buffer) 134ff662b5cSJustin T. Gibbs free(printf_buffer,M_XENBUS); 135ff662b5cSJustin T. Gibbs if (path_buffer) 136ff662b5cSJustin T. Gibbs free(path_buffer,M_XENBUS); 137ff662b5cSJustin T. Gibbs } 138ff662b5cSJustin T. Gibbs 139ff662b5cSJustin T. Gibbs void 140ff662b5cSJustin T. Gibbs xenbus_dev_error(device_t dev, int err, const char *fmt, ...) 141ff662b5cSJustin T. Gibbs { 142ff662b5cSJustin T. Gibbs va_list ap; 143ff662b5cSJustin T. Gibbs 144ff662b5cSJustin T. Gibbs va_start(ap, fmt); 145ff662b5cSJustin T. Gibbs xenbus_dev_verror(dev, err, fmt, ap); 146ff662b5cSJustin T. Gibbs va_end(ap); 147ff662b5cSJustin T. Gibbs } 148ff662b5cSJustin T. Gibbs 149ff662b5cSJustin T. Gibbs void 150ff662b5cSJustin T. Gibbs xenbus_dev_vfatal(device_t dev, int err, const char *fmt, va_list ap) 151ff662b5cSJustin T. Gibbs { 152ff662b5cSJustin T. Gibbs xenbus_dev_verror(dev, err, fmt, ap); 153ff662b5cSJustin T. Gibbs device_printf(dev, "Fatal error. Transitioning to Closing State\n"); 154ff662b5cSJustin T. Gibbs xenbus_set_state(dev, XenbusStateClosing); 155ff662b5cSJustin T. Gibbs } 156ff662b5cSJustin T. Gibbs 157ff662b5cSJustin T. Gibbs void 158ff662b5cSJustin T. Gibbs xenbus_dev_fatal(device_t dev, int err, const char *fmt, ...) 159ff662b5cSJustin T. Gibbs { 160ff662b5cSJustin T. Gibbs va_list ap; 161ff662b5cSJustin T. Gibbs 162ff662b5cSJustin T. Gibbs va_start(ap, fmt); 163ff662b5cSJustin T. Gibbs xenbus_dev_vfatal(dev, err, fmt, ap); 164ff662b5cSJustin T. Gibbs va_end(ap); 165ff662b5cSJustin T. Gibbs } 166ff662b5cSJustin T. Gibbs 167ff662b5cSJustin T. Gibbs int 168ff662b5cSJustin T. Gibbs xenbus_grant_ring(device_t dev, unsigned long ring_mfn, grant_ref_t *refp) 169ff662b5cSJustin T. Gibbs { 170ff662b5cSJustin T. Gibbs int error; 171ff662b5cSJustin T. Gibbs 172ff662b5cSJustin T. Gibbs error = gnttab_grant_foreign_access( 173ff662b5cSJustin T. Gibbs xenbus_get_otherend_id(dev), ring_mfn, 0, refp); 174ff662b5cSJustin T. Gibbs if (error) { 175ff662b5cSJustin T. Gibbs xenbus_dev_fatal(dev, error, "granting access to ring page"); 176ff662b5cSJustin T. Gibbs return (error); 177ff662b5cSJustin T. Gibbs } 178ff662b5cSJustin T. Gibbs 179ff662b5cSJustin T. Gibbs return (0); 180ff662b5cSJustin T. Gibbs } 181ff662b5cSJustin T. Gibbs 182ff662b5cSJustin T. Gibbs XenbusState 183ff662b5cSJustin T. Gibbs xenbus_read_driver_state(const char *path) 184ff662b5cSJustin T. Gibbs { 185ff662b5cSJustin T. Gibbs XenbusState result; 186ff662b5cSJustin T. Gibbs int error; 187ff662b5cSJustin T. Gibbs 188ff662b5cSJustin T. Gibbs error = xs_gather(XST_NIL, path, "state", "%d", &result, NULL); 189ff662b5cSJustin T. Gibbs if (error) 190ff662b5cSJustin T. Gibbs result = XenbusStateClosed; 191ff662b5cSJustin T. Gibbs 192ff662b5cSJustin T. Gibbs return (result); 193ff662b5cSJustin T. Gibbs } 194ff662b5cSJustin T. Gibbs 195ff662b5cSJustin T. Gibbs int 196ff662b5cSJustin T. Gibbs xenbus_dev_is_online(device_t dev) 197ff662b5cSJustin T. Gibbs { 198ff662b5cSJustin T. Gibbs const char *path; 199ff662b5cSJustin T. Gibbs int error; 200ff662b5cSJustin T. Gibbs int value; 201ff662b5cSJustin T. Gibbs 202ff662b5cSJustin T. Gibbs path = xenbus_get_node(dev); 203ff662b5cSJustin T. Gibbs error = xs_gather(XST_NIL, path, "online", "%d", &value, NULL); 204ff662b5cSJustin T. Gibbs if (error != 0) { 205ff662b5cSJustin T. Gibbs /* Default to not online. */ 206ff662b5cSJustin T. Gibbs value = 0; 207ff662b5cSJustin T. Gibbs } 208ff662b5cSJustin T. Gibbs 209ff662b5cSJustin T. Gibbs return (value); 210ff662b5cSJustin T. Gibbs } 211283d6f72SJustin T. Gibbs 212283d6f72SJustin T. Gibbs void 213283d6f72SJustin T. Gibbs xenbus_localend_changed(device_t dev, const char *path) 214283d6f72SJustin T. Gibbs { 215283d6f72SJustin T. Gibbs } 216