843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The contents of this file are subject to the terms of the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Common Development and Distribution License (the "License").
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You may not use this file except in compliance with the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When distributing Covered Code, include this CDDL HEADER in each
843e19887f64dde75055cf8842fc4db2171eff45johnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If applicable, add the following below this CDDL HEADER, with the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * fields enclosed by brackets "[]" replaced with your own identifying
843e19887f64dde75055cf8842fc4db2171eff45johnlev * information: Portions Copyright [yyyy] [name of copyright owner]
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER END
b26a64ae582e72d0b4c710cd8eba9c4afd4a9fddjohnlev * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Use is subject to license terms.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Driver giving user-space access to the kernel's xenbus connection
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to xenstore.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Copyright (c) 2005, Christian Limpach
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Copyright (c) 2005, Rusty Russell, IBM Corporation
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This file may be distributed separately from the Linux kernel, or
843e19887f64dde75055cf8842fc4db2171eff45johnlev * incorporated into other software packages, subject to the following license:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Permission is hereby granted, free of charge, to any person obtaining a copy
843e19887f64dde75055cf8842fc4db2171eff45johnlev * of this source file (the "Software"), to deal in the Software without
843e19887f64dde75055cf8842fc4db2171eff45johnlev * restriction, including without limitation the rights to use, copy, modify,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * merge, publish, distribute, sublicense, and/or sell copies of the Software,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and to permit persons to whom the Software is furnished to do so, subject to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the following conditions:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The above copyright notice and this permission notice shall be included in
843e19887f64dde75055cf8842fc4db2171eff45johnlev * all copies or substantial portions of the Software.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
843e19887f64dde75055cf8842fc4db2171eff45johnlev * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
843e19887f64dde75055cf8842fc4db2171eff45johnlev * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
843e19887f64dde75055cf8842fc4db2171eff45johnlev * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
843e19887f64dde75055cf8842fc4db2171eff45johnlev * IN THE SOFTWARE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XENBUSDRV_DBPRINT(fmt) { if (xenbusdrv_debug) cmn_err fmt; }
843e19887f64dde75055cf8842fc4db2171eff45johnlev#endif /* ifdef DEBUG */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Some handy macros */
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XENBUSDRV_MASK_READ_IDX(idx) ((idx) & (PAGESIZE - 1))
843e19887f64dde75055cf8842fc4db2171eff45johnlev ((xenbus_dev_t *)ddi_get_soft_state(xenbusdrv_statep, (instance)))
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Soft state data structure for xenbus driver */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* In-progress transaction. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Partial request. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Response queue. */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xenbusdrv_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xenbusdrv_attach(dev_info_t *, ddi_attach_cmd_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xenbusdrv_detach(dev_info_t *, ddi_detach_cmd_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xenbusdrv_open(dev_t *, int, int, cred_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xenbusdrv_close(dev_t, int, int, cred_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xenbusdrv_read(dev_t, struct uio *, cred_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xenbusdrv_write(dev_t, struct uio *, cred_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xenbusdrv_devmap(dev_t, devmap_cookie_t, offset_t, size_t, size_t *,
b26a64ae582e72d0b4c710cd8eba9c4afd4a9fddjohnlevstatic int xenbusdrv_segmap(dev_t, off_t, ddi_as_handle_t, caddr_t *, off_t,
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xenbusdrv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xenbusdrv_queue_reply(xenbus_dev_t *, const struct xsd_sockmsg *,
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Solaris driver framework */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0, /* cb_stream */
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0, /* devo_refcnt */
843e19887f64dde75055cf8842fc4db2171eff45johnlev &mod_driverops, /* Type of module. This one is a driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "virtual bus driver", /* Name of the module. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev e = ddi_soft_state_init(&xenbusdrv_statep, sizeof (xenbus_dev_t), 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (e);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (e);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (e);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* ARGSUSED */
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbusdrv_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
843e19887f64dde75055cf8842fc4db2171eff45johnlev *result = (void *)0;
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbusdrv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "xenbus_attach: unknown cmd 0x%x\n", cmd);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* DDI_ATTACH */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * only one instance - but we clone using the open routine
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_init(&xenbusdrv_clone_tab_mutex, NULL, MUTEX_DRIVER,
843e19887f64dde75055cf8842fc4db2171eff45johnlev error = ddi_create_minor_node(dip, "xenbus", S_IFCHR, unit,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * save dip for getinfo
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbusdrv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * again, only one instance
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "xenbus_detach: unknown cmd 0x%x\n", cmd);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* ARGSUSED */
b26a64ae582e72d0b4c710cd8eba9c4afd4a9fddjohnlevxenbusdrv_open(dev_t *devp, int flag, int otyp, cred_t *cr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * only allow open on minor = 0 - the clone device
843e19887f64dde75055cf8842fc4db2171eff45johnlev * find a free slot and grab it
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (minor = 1; minor < XENBUSDRV_NCLONES; minor++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Allocate softstate structure */
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(minor));
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* ... and init it */
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_init(&xbs->read_mutex, NULL, MUTEX_DRIVER, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_create(&xbs->transactions, sizeof (struct xenbus_dev_transaction),
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* clone driver */
843e19887f64dde75055cf8842fc4db2171eff45johnlev XENBUSDRV_DBPRINT((CE_NOTE, "Xenbus drv open succeeded, minor=%d",
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* ARGSUSED */
b26a64ae582e72d0b4c710cd8eba9c4afd4a9fddjohnlevxenbusdrv_close(dev_t dev, int flag, int otyp, struct cred *cr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(minor));
843e19887f64dde75055cf8842fc4db2171eff45johnlev * XXPV - would like to be able to notify xenstore down here, but
843e19887f64dde75055cf8842fc4db2171eff45johnlev * as the daemon is currently written, it doesn't leave the device
843e19887f64dde75055cf8842fc4db2171eff45johnlev * open after initial setup, so we have no way of knowing if it has
843e19887f64dde75055cf8842fc4db2171eff45johnlev * gone away.
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* free pending transaction */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ddi_soft_state_free(xenbusdrv_statep, XENBUSDRV_MINOR2INST(minor));
843e19887f64dde75055cf8842fc4db2171eff45johnlev * free clone tab slot
843e19887f64dde75055cf8842fc4db2171eff45johnlev XENBUSDRV_DBPRINT((CE_NOTE, "Xenbus drv close succeeded, minor=%d",
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* ARGSUSED */
b26a64ae582e72d0b4c710cd8eba9c4afd4a9fddjohnlevxenbusdrv_read(dev_t dev, struct uio *uiop, cred_t *cr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_read called"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev)));
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* check if we have something to read */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (cv_wait_sig(&xbs->read_cv, &xbs->read_mutex) == 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = uiomove(xbs->read_buffer + idx, len, UIO_READ, uiop);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * prepare data for xenbusdrv_read()
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbusdrv_queue_reply(xenbus_dev_t *xbs, const struct xsd_sockmsg *msg,
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *reply)
843e19887f64dde75055cf8842fc4db2171eff45johnlev XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_queue_reply called"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < sizeof (*msg); i++, xbs->read_prod++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbs->read_buffer[XENBUSDRV_MASK_READ_IDX(xbs->read_prod)] =
843e19887f64dde75055cf8842fc4db2171eff45johnlev ((char *)msg)[i];
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbs->read_buffer[XENBUSDRV_MASK_READ_IDX(xbs->read_prod)] =
843e19887f64dde75055cf8842fc4db2171eff45johnlev XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_queue_reply exited"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* ARGSUSED */
b26a64ae582e72d0b4c710cd8eba9c4afd4a9fddjohnlevxenbusdrv_write(dev_t dev, struct uio *uiop, cred_t *cr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_write called"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev)));
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (uiomove(xbs->u.buffer + xbs->len, len, UIO_WRITE, uiop) != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbs->len < (sizeof (xbs->u.msg) + xbs->u.msg.len)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* send the request to xenstore and get feedback */
843e19887f64dde75055cf8842fc4db2171eff45johnlev rc = xenbus_dev_request_and_reply(&xbs->u.msg, &reply);
843e19887f64dde75055cf8842fc4db2171eff45johnlev "xenbus_dev_request_and_reply failed"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* handle transaction start/end */
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_insert_tail(&xbs->transactions, (void *)trans);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* try to find out the ending transaction */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* free it, if we find it */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* prepare data for xenbusdrv_read() to get */
843e19887f64dde75055cf8842fc4db2171eff45johnlev rc = xenbusdrv_queue_reply(xbs, &xbs->u.msg, reply);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbusdrv_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev)));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = devmap_umem_setup(dhp, xbs->dip, NULL, xb_xenstore_cookie(),
843e19887f64dde75055cf8842fc4db2171eff45johnlev 0, PAGESIZE, PROT_READ | PROT_WRITE | PROT_USER, 0, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
b26a64ae582e72d0b4c710cd8eba9c4afd4a9fddjohnlevxenbusdrv_segmap(dev_t dev, off_t off, ddi_as_handle_t as, caddr_t *addrp,
b26a64ae582e72d0b4c710cd8eba9c4afd4a9fddjohnlev off_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr)
b26a64ae582e72d0b4c710cd8eba9c4afd4a9fddjohnlev return (ddi_devmap_segmap(dev, off, as, addrp, len, prot,
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
b26a64ae582e72d0b4c710cd8eba9c4afd4a9fddjohnlevxenbusdrv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev)));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);