/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_XENDEV_H
#define _SYS_XENDEV_H
#include <sys/hypervisor.h>
#include <sys/taskq.h>
#ifndef __xpv
#include <public/io/ring.h>
#include <public/event_channel.h>
#include <public/grant_table.h>
#endif
#include <xen/sys/xenbus_impl.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Xenbus property interfaces, initialized by framework
*/
#define XBP_HP_STATUS "hotplug-status" /* backend prop: str */
#define XBV_HP_STATUS_CONN "connected" /* backend prop val */
#define XBP_DEV_TYPE "device-type" /* backend prop: str */
#define XBV_DEV_TYPE_CD "cdrom" /* backend prop val */
/*
* Xenbus property interfaces, initialized by backend disk driver
*/
#define XBP_SECTOR_SIZE "sector-size" /* backend prop: uint */
#define XBP_SECTORS "sectors" /* backend prop: uint64 */
#define XBP_INFO "info" /* backend prop: uint */
#define XBP_FB "feature-barrier" /* backend prop: boolean int */
/*
* Xenbus property interfaces, initialized by frontend disk driver
*/
#define XBP_RING_REF "ring-ref" /* frontend prop: long */
#define XBP_EVENT_CHAN "event-channel" /* frontend prop: long */
#define XBP_PROTOCOL "protocol" /* frontend prop: string */
/*
* Xenbus CDROM property interfaces, used by backend and frontend
*
* XBP_MEDIA_REQ_SUP
* - Backend xenbus property located at:
* backend/vbd/<domU_id>/<domU_dev>/media-req-sup
* - Set by the backend, consumed by the frontend.
* - Cosumed by the frontend.
* - A boolean integer property indicating backend support
* for the XBP_MEDIA_REQ property.
*
* XBP_MEDIA_REQ
* - Frontend xenbus property located at:
* /local/domain/<domU_id>/device/vbd/<domU_dev>/media-req
* - Set and consumed by both the frontend and backend.
* - Possible values:
* XBV_MEDIA_REQ_NONE, XBV_MEDIA_REQ_LOCK, and XBV_MEDIA_REQ_EJECT
* - Only applies to CDROM devices.
*
* XBV_MEDIA_REQ_NONE
* - XBP_MEDIA_REQ property valud
* - Set and consumed by both the frontend and backend.
* - Indicates that there are no currently outstanding media requet
* operations.
*
* XBV_MEDIA_REQ_LOCK
* - XBP_MEDIA_REQ property valud
* - Set by the frontend, consumed by the backend.
* - Indicates to the backend that the currenct media is locked
* and changes to the media (via xm block-configure for example)
* should not be allowed.
*
* XBV_MEDIA_REQ_EJECT
* - XBP_MEDIA_REQ property valud
* - Set by the frontend, consumed by the backend.
* - Indicates to the backend that the currenct media should be ejected.
* This means that the backend should close it's connection to
* the frontend device, close it's current backing store device/file,
* and then set the media-req property to XBV_MEDIA_REQ_NONE. (to
* indicate that the eject operation is complete.)
*/
#define XBP_MEDIA_REQ_SUP "media-req-sup" /* backend prop: boolean int */
#define XBP_MEDIA_REQ "media-req" /* frontend prop: str */
#define XBV_MEDIA_REQ_NONE "none" /* frontend prop val */
#define XBV_MEDIA_REQ_LOCK "lock" /* frontend prop val */
#define XBV_MEDIA_REQ_EJECT "eject" /* frontend prop val */
/*
* Xen device class codes
*/
typedef enum {
XEN_INVAL = -1,
XEN_CONSOLE = 0,
XEN_VNET,
XEN_VBLK,
XEN_XENBUS,
XEN_DOMCAPS,
XEN_BALLOON,
XEN_EVTCHN,
XEN_PRIVCMD,
XEN_BLKTAP,
XEN_LASTCLASS
} xendev_devclass_t;
/*
* Hotplug request sent to userland event handler.
*/
typedef enum {
XEN_HP_ADD,
XEN_HP_REMOVE
} xendev_hotplug_cmd_t;
/*
* Hotplug status.
*
* In fact, the Xen tools can write any arbitrary string into the
* hotplug-status node. We represent the known values here - anything
* else will be 'Unrecognized'.
*/
typedef enum {
Unrecognized,
Connected
} xendev_hotplug_state_t;
struct xendev_ppd {
kmutex_t xd_evt_lk;
int xd_evtchn;
struct intrspec xd_ispec;
xendev_devclass_t xd_devclass;
domid_t xd_domain;
int xd_vdevnum;
kmutex_t xd_ndi_lk;
struct xenbus_device xd_xsdev;
struct xenbus_watch xd_hp_watch;
struct xenbus_watch xd_bepath_watch;
ddi_callback_id_t xd_oe_ehid;
ddi_callback_id_t xd_hp_ehid;
ddi_taskq_t *xd_oe_taskq;
ddi_taskq_t *xd_hp_taskq;
ddi_taskq_t *xd_xb_watch_taskq;
list_t xd_xb_watches;
};
#define XS_OE_STATE "SUNW,xendev:otherend_state"
#define XS_HP_STATE "SUNW,xendev:hotplug_state"
/*
* A device with xd_vdevnum == VDEV_NOXS does not participate in
* xenstore.
*/
#define VDEV_NOXS (-1)
void xendev_enum_class(dev_info_t *, xendev_devclass_t);
void xendev_enum_all(dev_info_t *, boolean_t);
xendev_devclass_t xendev_nodename_to_devclass(char *);
int xendev_devclass_ipl(xendev_devclass_t);
struct intrspec *xendev_get_ispec(dev_info_t *, uint_t);
void xvdi_suspend(dev_info_t *);
int xvdi_resume(dev_info_t *);
int xvdi_alloc_evtchn(dev_info_t *);
int xvdi_bind_evtchn(dev_info_t *, evtchn_port_t);
void xvdi_free_evtchn(dev_info_t *);
int xvdi_add_event_handler(dev_info_t *, char *,
void (*)(dev_info_t *, ddi_eventcookie_t, void *, void *),
void *arg);
void xvdi_remove_event_handler(dev_info_t *, char *);
int xvdi_get_evtchn(dev_info_t *);
int xvdi_get_vdevnum(dev_info_t *);
char *xvdi_get_xsname(dev_info_t *);
char *xvdi_get_oename(dev_info_t *);
domid_t xvdi_get_oeid(dev_info_t *);
void xvdi_dev_error(dev_info_t *, int, char *);
void xvdi_fatal_error(dev_info_t *, int, char *);
void xvdi_notify_oe(dev_info_t *);
int xvdi_post_event(dev_info_t *, xendev_hotplug_cmd_t);
struct xenbus_device *xvdi_get_xsd(dev_info_t *);
int xvdi_switch_state(dev_info_t *, xenbus_transaction_t, XenbusState);
dev_info_t *xvdi_create_dev(dev_info_t *, xendev_devclass_t,
domid_t, int);
int xvdi_init_dev(dev_info_t *);
void xvdi_uninit_dev(dev_info_t *);
dev_info_t *xvdi_find_dev(dev_info_t *, xendev_devclass_t, domid_t, int);
extern int xvdi_add_xb_watch_handler(dev_info_t *, const char *,
const char *, xvdi_xb_watch_cb_t cb, void *);
extern void xvdi_remove_xb_watch_handlers(dev_info_t *);
/*
* common ring interfaces
*/
/*
* we need the pad between ring index
* and the real ring containing requests/responses,
* so that we can map comif_sring_t structure to
* any xxxif_sring_t structure defined via macros in ring.h
*/
#define SRINGPAD 48
typedef struct comif_sring {
RING_IDX req_prod, req_event;
RING_IDX rsp_prod, rsp_event;
uint8_t pad[SRINGPAD];
/*
* variable length
* stores real request/response entries
* entry size is fixed per ring
*/
char ring[1];
} comif_sring_t;
typedef struct comif_ring_fe {
/*
* keep the member names as defined in ring.h
* in order to make use of the pre-defined macros
*/
RING_IDX req_prod_pvt;
RING_IDX rsp_cons;
unsigned int nr_ents;
comif_sring_t *sring;
} comif_ring_fe_t;
typedef struct comif_ring_be {
/*
* keep the member names as defined in ring.h
* in order to make use of the pre-defined macros
*/
RING_IDX rsp_prod_pvt;
RING_IDX req_cons;
unsigned int nr_ents;
comif_sring_t *sring;
} comif_ring_be_t;
typedef union comif_ring {
comif_ring_fe_t fr;
comif_ring_be_t br;
} comif_ring_t;
typedef struct xendev_req {
unsigned long next;
void *req;
} xendev_req_t;
typedef struct xendev_ring {
ddi_dma_handle_t xr_dma_hdl;
ddi_acc_handle_t xr_acc_hdl;
grant_handle_t xr_grant_hdl;
caddr_t xr_vaddr;
paddr_t xr_paddr;
grant_ref_t xr_gref;
int xr_entry_size;
int xr_frontend;
comif_ring_t xr_sring;
} xendev_ring_t;
int xvdi_alloc_ring(dev_info_t *, size_t, size_t, grant_ref_t *,
xendev_ring_t **);
void xvdi_free_ring(xendev_ring_t *);
int xvdi_map_ring(dev_info_t *, size_t, size_t, grant_ref_t,
xendev_ring_t **);
void xvdi_unmap_ring(xendev_ring_t *);
uint_t xvdi_ring_avail_slots(xendev_ring_t *);
int xvdi_ring_has_unconsumed_requests(xendev_ring_t *);
int xvdi_ring_has_incomp_request(xendev_ring_t *);
int xvdi_ring_has_unconsumed_responses(xendev_ring_t *);
void* xvdi_ring_get_request(xendev_ring_t *);
int xvdi_ring_push_request(xendev_ring_t *);
void* xvdi_ring_get_response(xendev_ring_t *);
int xvdi_ring_push_response(xendev_ring_t *);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_XENDEV_H */