xref: /onnv-gate/usr/src/uts/common/xen/io/blk_common.c (revision 10581:c2151e45dda5)
17756SMark.Johnson@Sun.COM /*
27756SMark.Johnson@Sun.COM  * CDDL HEADER START
37756SMark.Johnson@Sun.COM  *
47756SMark.Johnson@Sun.COM  * The contents of this file are subject to the terms of the
57756SMark.Johnson@Sun.COM  * Common Development and Distribution License (the "License").
67756SMark.Johnson@Sun.COM  * You may not use this file except in compliance with the License.
77756SMark.Johnson@Sun.COM  *
87756SMark.Johnson@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97756SMark.Johnson@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107756SMark.Johnson@Sun.COM  * See the License for the specific language governing permissions
117756SMark.Johnson@Sun.COM  * and limitations under the License.
127756SMark.Johnson@Sun.COM  *
137756SMark.Johnson@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147756SMark.Johnson@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157756SMark.Johnson@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167756SMark.Johnson@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177756SMark.Johnson@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187756SMark.Johnson@Sun.COM  *
197756SMark.Johnson@Sun.COM  * CDDL HEADER END
207756SMark.Johnson@Sun.COM  */
217756SMark.Johnson@Sun.COM 
227756SMark.Johnson@Sun.COM /*
2310175SStuart.Maybee@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247756SMark.Johnson@Sun.COM  * Use is subject to license terms.
257756SMark.Johnson@Sun.COM  */
267756SMark.Johnson@Sun.COM 
277756SMark.Johnson@Sun.COM 
287756SMark.Johnson@Sun.COM #include <sys/errno.h>
297756SMark.Johnson@Sun.COM #include <sys/types.h>
307756SMark.Johnson@Sun.COM #include <sys/conf.h>
317756SMark.Johnson@Sun.COM #include <sys/kmem.h>
327756SMark.Johnson@Sun.COM #include <sys/ddi.h>
337756SMark.Johnson@Sun.COM #include <sys/stat.h>
347756SMark.Johnson@Sun.COM #include <sys/sunddi.h>
357756SMark.Johnson@Sun.COM #include <sys/file.h>
367756SMark.Johnson@Sun.COM #include <sys/open.h>
377756SMark.Johnson@Sun.COM #include <sys/modctl.h>
387756SMark.Johnson@Sun.COM #include <sys/ddi_impldefs.h>
397756SMark.Johnson@Sun.COM #include <sys/sysmacros.h>
407756SMark.Johnson@Sun.COM #include <sys/ddidevmap.h>
417756SMark.Johnson@Sun.COM #include <sys/xendev.h>
427756SMark.Johnson@Sun.COM #include <public/io/protocols.h>
437756SMark.Johnson@Sun.COM #include <xen/io/blkif_impl.h>
447756SMark.Johnson@Sun.COM 
457756SMark.Johnson@Sun.COM #include "blk_common.h"
467756SMark.Johnson@Sun.COM 
477756SMark.Johnson@Sun.COM 
487756SMark.Johnson@Sun.COM /* blk interface status */
497756SMark.Johnson@Sun.COM enum blk_if_state {
507756SMark.Johnson@Sun.COM 	/*
517756SMark.Johnson@Sun.COM 	 * initial state
527756SMark.Johnson@Sun.COM 	 */
537756SMark.Johnson@Sun.COM 	BLK_IF_UNKNOWN = 0,
547756SMark.Johnson@Sun.COM 	/*
557756SMark.Johnson@Sun.COM 	 * frontend xenbus state changed to XenbusStateConnected,
567756SMark.Johnson@Sun.COM 	 * we finally connect
577756SMark.Johnson@Sun.COM 	 */
587756SMark.Johnson@Sun.COM 	BLK_IF_CONNECTED,
597756SMark.Johnson@Sun.COM 	/*
607756SMark.Johnson@Sun.COM 	 * frontend xenbus state changed to XenbusStateClosed,
617756SMark.Johnson@Sun.COM 	 * interface disconnected
627756SMark.Johnson@Sun.COM 	 */
637756SMark.Johnson@Sun.COM 	BLK_IF_DISCONNECTED
647756SMark.Johnson@Sun.COM };
657756SMark.Johnson@Sun.COM 
667756SMark.Johnson@Sun.COM /* backend device status */
677756SMark.Johnson@Sun.COM enum blk_be_state {
687756SMark.Johnson@Sun.COM 	/* initial state */
697756SMark.Johnson@Sun.COM 	BLK_BE_UNKNOWN = 0,
707756SMark.Johnson@Sun.COM 	/* backend device is ready (hotplug script finishes successfully) */
717756SMark.Johnson@Sun.COM 	BLK_BE_READY
727756SMark.Johnson@Sun.COM };
737756SMark.Johnson@Sun.COM 
747756SMark.Johnson@Sun.COM /* frontend status */
757756SMark.Johnson@Sun.COM enum blk_fe_state {
767756SMark.Johnson@Sun.COM 	/* initial state */
777756SMark.Johnson@Sun.COM 	BLK_FE_UNKNOWN = 0,
787756SMark.Johnson@Sun.COM 	/*
797756SMark.Johnson@Sun.COM 	 * frontend's xenbus state has changed to
807756SMark.Johnson@Sun.COM 	 * XenbusStateInitialised, is ready for connecting
817756SMark.Johnson@Sun.COM 	 */
827756SMark.Johnson@Sun.COM 	BLK_FE_READY
837756SMark.Johnson@Sun.COM };
847756SMark.Johnson@Sun.COM 
857756SMark.Johnson@Sun.COM typedef struct blk_ring_state_s {
867756SMark.Johnson@Sun.COM 	kmutex_t		rs_mutex;
877756SMark.Johnson@Sun.COM 	boolean_t		rs_sleeping_on_ring;
887756SMark.Johnson@Sun.COM 	boolean_t		rs_ring_up;
897756SMark.Johnson@Sun.COM 	kcondvar_t		rs_cv;
907756SMark.Johnson@Sun.COM } blk_ring_state_t;
917756SMark.Johnson@Sun.COM 
927756SMark.Johnson@Sun.COM /* Disk Statistics */
937756SMark.Johnson@Sun.COM static char *blk_stats[] = {
947756SMark.Johnson@Sun.COM 	"rd_reqs",
957756SMark.Johnson@Sun.COM 	"wr_reqs",
967756SMark.Johnson@Sun.COM 	"br_reqs",
977756SMark.Johnson@Sun.COM 	"fl_reqs",
987756SMark.Johnson@Sun.COM 	"oo_reqs"
997756SMark.Johnson@Sun.COM };
1007756SMark.Johnson@Sun.COM 
1017756SMark.Johnson@Sun.COM typedef struct blk_stats_s {
1027756SMark.Johnson@Sun.COM 	uint64_t bs_req_reads;
1037756SMark.Johnson@Sun.COM 	uint64_t bs_req_writes;
1047756SMark.Johnson@Sun.COM 	uint64_t bs_req_barriers;
1057756SMark.Johnson@Sun.COM 	uint64_t bs_req_flushes;
1067756SMark.Johnson@Sun.COM } blk_stats_t;
1077756SMark.Johnson@Sun.COM 
1087756SMark.Johnson@Sun.COM struct blk_ring_s {
1097756SMark.Johnson@Sun.COM 	kmutex_t		ri_mutex;
1107756SMark.Johnson@Sun.COM 	dev_info_t		*ri_dip;
1117756SMark.Johnson@Sun.COM 
1127756SMark.Johnson@Sun.COM 	kstat_t			*ri_kstats;
1137756SMark.Johnson@Sun.COM 	blk_stats_t		ri_stats;
1147756SMark.Johnson@Sun.COM 
1157756SMark.Johnson@Sun.COM 	blk_intr_t		ri_intr;
1167756SMark.Johnson@Sun.COM 	caddr_t			ri_intr_arg;
1177756SMark.Johnson@Sun.COM 	blk_ring_cb_t		ri_ringup;
1187756SMark.Johnson@Sun.COM 	caddr_t			ri_ringup_arg;
1197756SMark.Johnson@Sun.COM 	blk_ring_cb_t		ri_ringdown;
1207756SMark.Johnson@Sun.COM 	caddr_t			ri_ringdown_arg;
1217756SMark.Johnson@Sun.COM 
1227756SMark.Johnson@Sun.COM 	/* blk interface, backend, and frontend status */
1237756SMark.Johnson@Sun.COM 	enum blk_if_state	ri_if_status;
1247756SMark.Johnson@Sun.COM 	enum blk_be_state	ri_be_status;
1257756SMark.Johnson@Sun.COM 	enum blk_fe_state	ri_fe_status;
1267756SMark.Johnson@Sun.COM 
1277756SMark.Johnson@Sun.COM 	domid_t			ri_fe;
1287756SMark.Johnson@Sun.COM 
1297756SMark.Johnson@Sun.COM 	enum blkif_protocol	ri_protocol;
1307756SMark.Johnson@Sun.COM 	size_t			ri_nentry;
1317756SMark.Johnson@Sun.COM 	size_t			ri_entrysize;
1327756SMark.Johnson@Sun.COM 
1337756SMark.Johnson@Sun.COM 	xendev_ring_t		*ri_ring;
1347756SMark.Johnson@Sun.COM 	blk_ring_state_t	ri_state;
1357756SMark.Johnson@Sun.COM };
1367756SMark.Johnson@Sun.COM 
1377756SMark.Johnson@Sun.COM 
1387756SMark.Johnson@Sun.COM static void blk_oe_state_change(dev_info_t *dip, ddi_eventcookie_t id,
1397756SMark.Johnson@Sun.COM     void *arg, void *impl_data);
1407756SMark.Johnson@Sun.COM static void blk_hp_state_change(dev_info_t *dip, ddi_eventcookie_t id,
1417756SMark.Johnson@Sun.COM     void *arg, void *impl_data);
1427756SMark.Johnson@Sun.COM static int blk_check_state_transition(blk_ring_t ring, XenbusState oestate);
1437756SMark.Johnson@Sun.COM static int blk_start_connect(blk_ring_t ring);
1447756SMark.Johnson@Sun.COM static void blk_start_disconnect(blk_ring_t ring);
1457756SMark.Johnson@Sun.COM static void blk_ring_close(blk_ring_t ring);
1467756SMark.Johnson@Sun.COM static int blk_bindto_frontend(blk_ring_t ring);
1477756SMark.Johnson@Sun.COM static void blk_unbindfrom_frontend(blk_ring_t ring);
1487756SMark.Johnson@Sun.COM static uint_t blk_intr(caddr_t arg);
1497756SMark.Johnson@Sun.COM 
1507756SMark.Johnson@Sun.COM static int blk_kstat_init(blk_ring_t ring);
1517756SMark.Johnson@Sun.COM static void blk_kstat_fini(blk_ring_t ring);
1527756SMark.Johnson@Sun.COM static int blk_kstat_update(kstat_t *ksp, int flag);
1537756SMark.Johnson@Sun.COM 
1547756SMark.Johnson@Sun.COM static void blk_ring_request_32(blkif_request_t *dst,
1557756SMark.Johnson@Sun.COM     blkif_x86_32_request_t *src);
1567756SMark.Johnson@Sun.COM static void blk_ring_request_64(blkif_request_t *dst,
1577756SMark.Johnson@Sun.COM     blkif_x86_64_request_t *src);
1587756SMark.Johnson@Sun.COM 
1597756SMark.Johnson@Sun.COM static void blk_ring_response_32(blkif_x86_32_response_t *dst,
1607756SMark.Johnson@Sun.COM     blkif_response_t *src);
1617756SMark.Johnson@Sun.COM static void blk_ring_response_64(blkif_x86_64_response_t *dst,
1627756SMark.Johnson@Sun.COM     blkif_response_t *src);
1637756SMark.Johnson@Sun.COM 
1647756SMark.Johnson@Sun.COM 
1657756SMark.Johnson@Sun.COM /*
1667756SMark.Johnson@Sun.COM  * blk_ring_init()
1677756SMark.Johnson@Sun.COM  */
1687756SMark.Johnson@Sun.COM int
blk_ring_init(blk_ringinit_args_t * args,blk_ring_t * ringp)1697756SMark.Johnson@Sun.COM blk_ring_init(blk_ringinit_args_t *args, blk_ring_t *ringp)
1707756SMark.Johnson@Sun.COM {
1717756SMark.Johnson@Sun.COM 	blk_ring_t ring;
1727756SMark.Johnson@Sun.COM 	int e;
1737756SMark.Johnson@Sun.COM 
1747756SMark.Johnson@Sun.COM 
1757756SMark.Johnson@Sun.COM 	ring = kmem_zalloc(sizeof (struct blk_ring_s), KM_SLEEP);
1767756SMark.Johnson@Sun.COM 	mutex_init(&ring->ri_mutex, NULL, MUTEX_DRIVER, NULL);
1777756SMark.Johnson@Sun.COM 	ring->ri_dip = args->ar_dip;
1787756SMark.Johnson@Sun.COM 	ring->ri_intr = args->ar_intr;
1797756SMark.Johnson@Sun.COM 	ring->ri_intr_arg = args->ar_intr_arg;
1807756SMark.Johnson@Sun.COM 	ring->ri_ringup = args->ar_ringup;
1817756SMark.Johnson@Sun.COM 	ring->ri_ringup_arg = args->ar_ringup_arg;
1827756SMark.Johnson@Sun.COM 	ring->ri_ringdown = args->ar_ringdown;
1837756SMark.Johnson@Sun.COM 	ring->ri_ringdown_arg = args->ar_ringdown_arg;
1847756SMark.Johnson@Sun.COM 
1857756SMark.Johnson@Sun.COM 	ring->ri_if_status = BLK_IF_UNKNOWN;
1867756SMark.Johnson@Sun.COM 	ring->ri_be_status = BLK_BE_UNKNOWN;
1877756SMark.Johnson@Sun.COM 	ring->ri_fe_status = BLK_FE_UNKNOWN;
1887756SMark.Johnson@Sun.COM 	ring->ri_state.rs_sleeping_on_ring = B_FALSE;
1897756SMark.Johnson@Sun.COM 	ring->ri_state.rs_ring_up = B_FALSE;
1907756SMark.Johnson@Sun.COM 
1917756SMark.Johnson@Sun.COM 	mutex_init(&ring->ri_state.rs_mutex, NULL, MUTEX_DRIVER, NULL);
1927756SMark.Johnson@Sun.COM 	cv_init(&ring->ri_state.rs_cv, NULL, CV_DRIVER, NULL);
1937756SMark.Johnson@Sun.COM 
1947756SMark.Johnson@Sun.COM 	e = blk_kstat_init(ring);
1957756SMark.Johnson@Sun.COM 	if (e != DDI_SUCCESS) {
1967756SMark.Johnson@Sun.COM 		goto ringinitfail_kstat;
1977756SMark.Johnson@Sun.COM 	}
1987756SMark.Johnson@Sun.COM 
1997756SMark.Johnson@Sun.COM 	/* Watch frontend and hotplug state change */
2007756SMark.Johnson@Sun.COM 	if (xvdi_add_event_handler(ring->ri_dip, XS_OE_STATE,
2017756SMark.Johnson@Sun.COM 	    blk_oe_state_change, ring) != DDI_SUCCESS) {
2027756SMark.Johnson@Sun.COM 		goto ringinitfail_oestate;
2037756SMark.Johnson@Sun.COM 	}
2047756SMark.Johnson@Sun.COM 	if (xvdi_add_event_handler(ring->ri_dip, XS_HP_STATE,
2057756SMark.Johnson@Sun.COM 	    blk_hp_state_change, ring) != DDI_SUCCESS) {
2067756SMark.Johnson@Sun.COM 		goto ringinitfail_hpstate;
2077756SMark.Johnson@Sun.COM 	}
2087756SMark.Johnson@Sun.COM 
2097756SMark.Johnson@Sun.COM 	/*
2107756SMark.Johnson@Sun.COM 	 * Kick-off hotplug script
2117756SMark.Johnson@Sun.COM 	 */
2127756SMark.Johnson@Sun.COM 	if (xvdi_post_event(ring->ri_dip, XEN_HP_ADD) != DDI_SUCCESS) {
2137756SMark.Johnson@Sun.COM 		cmn_err(CE_WARN, "blk@%s: failed to start hotplug script",
2147756SMark.Johnson@Sun.COM 		    ddi_get_name_addr(ring->ri_dip));
2157756SMark.Johnson@Sun.COM 		goto ringinitfail_postevent;
2167756SMark.Johnson@Sun.COM 	}
2177756SMark.Johnson@Sun.COM 
2187756SMark.Johnson@Sun.COM 	/*
2197756SMark.Johnson@Sun.COM 	 * start waiting for hotplug event and otherend state event
2207756SMark.Johnson@Sun.COM 	 * mainly for debugging, frontend will not take any op seeing this
2217756SMark.Johnson@Sun.COM 	 */
2227756SMark.Johnson@Sun.COM 	(void) xvdi_switch_state(ring->ri_dip, XBT_NULL, XenbusStateInitWait);
2237756SMark.Johnson@Sun.COM 
2247756SMark.Johnson@Sun.COM 	*ringp = ring;
2257756SMark.Johnson@Sun.COM 	return (DDI_SUCCESS);
2267756SMark.Johnson@Sun.COM 
2277756SMark.Johnson@Sun.COM ringinitfail_postevent:
2287756SMark.Johnson@Sun.COM 	xvdi_remove_event_handler(ring->ri_dip, XS_HP_STATE);
2297756SMark.Johnson@Sun.COM ringinitfail_hpstate:
2307756SMark.Johnson@Sun.COM 	xvdi_remove_event_handler(ring->ri_dip, XS_OE_STATE);
2317756SMark.Johnson@Sun.COM ringinitfail_oestate:
2327756SMark.Johnson@Sun.COM 	blk_kstat_fini(ring);
2337756SMark.Johnson@Sun.COM ringinitfail_kstat:
2347756SMark.Johnson@Sun.COM 	cv_destroy(&ring->ri_state.rs_cv);
2357756SMark.Johnson@Sun.COM 	mutex_destroy(&ring->ri_state.rs_mutex);
2367756SMark.Johnson@Sun.COM 	mutex_destroy(&ring->ri_mutex);
2377756SMark.Johnson@Sun.COM 	kmem_free(ring, sizeof (struct blk_ring_s));
2387756SMark.Johnson@Sun.COM 	return (DDI_FAILURE);
2397756SMark.Johnson@Sun.COM }
2407756SMark.Johnson@Sun.COM 
2417756SMark.Johnson@Sun.COM 
2427756SMark.Johnson@Sun.COM /*
2437756SMark.Johnson@Sun.COM  * blk_ring_fini()
2447756SMark.Johnson@Sun.COM  */
2457756SMark.Johnson@Sun.COM void
blk_ring_fini(blk_ring_t * ringp)2467756SMark.Johnson@Sun.COM blk_ring_fini(blk_ring_t *ringp)
2477756SMark.Johnson@Sun.COM {
2487756SMark.Johnson@Sun.COM 	blk_ring_t ring;
2497756SMark.Johnson@Sun.COM 
2507756SMark.Johnson@Sun.COM 
2517756SMark.Johnson@Sun.COM 	ring = *ringp;
2527756SMark.Johnson@Sun.COM 
2537756SMark.Johnson@Sun.COM 	mutex_enter(&ring->ri_mutex);
2547756SMark.Johnson@Sun.COM 	if (ring->ri_if_status != BLK_IF_DISCONNECTED) {
2557756SMark.Johnson@Sun.COM 		blk_ring_close(ring);
2567756SMark.Johnson@Sun.COM 	}
2577756SMark.Johnson@Sun.COM 	mutex_exit(&ring->ri_mutex);
2587756SMark.Johnson@Sun.COM 
2597756SMark.Johnson@Sun.COM 	xvdi_remove_event_handler(ring->ri_dip, NULL);
2607756SMark.Johnson@Sun.COM 	blk_kstat_fini(ring);
2617756SMark.Johnson@Sun.COM 	cv_destroy(&ring->ri_state.rs_cv);
2627756SMark.Johnson@Sun.COM 	mutex_destroy(&ring->ri_state.rs_mutex);
2637756SMark.Johnson@Sun.COM 	mutex_destroy(&ring->ri_mutex);
2647756SMark.Johnson@Sun.COM 	kmem_free(ring, sizeof (struct blk_ring_s));
2657756SMark.Johnson@Sun.COM 
2667756SMark.Johnson@Sun.COM 	*ringp = NULL;
2677756SMark.Johnson@Sun.COM }
2687756SMark.Johnson@Sun.COM 
2697756SMark.Johnson@Sun.COM 
2707756SMark.Johnson@Sun.COM /*
2717756SMark.Johnson@Sun.COM  * blk_kstat_init()
2727756SMark.Johnson@Sun.COM  */
2737756SMark.Johnson@Sun.COM static int
blk_kstat_init(blk_ring_t ring)2747756SMark.Johnson@Sun.COM blk_kstat_init(blk_ring_t ring)
2757756SMark.Johnson@Sun.COM {
2767756SMark.Johnson@Sun.COM 	int nstat = sizeof (blk_stats) / sizeof (blk_stats[0]);
2777756SMark.Johnson@Sun.COM 	char **cp = blk_stats;
2787756SMark.Johnson@Sun.COM 	kstat_named_t *knp;
2797756SMark.Johnson@Sun.COM 
2807756SMark.Johnson@Sun.COM 	ring->ri_kstats = kstat_create(ddi_get_name(ring->ri_dip),
2817756SMark.Johnson@Sun.COM 	    ddi_get_instance(ring->ri_dip), "req_statistics", "block",
2827756SMark.Johnson@Sun.COM 	    KSTAT_TYPE_NAMED, nstat, 0);
2837756SMark.Johnson@Sun.COM 	if (ring->ri_kstats == NULL) {
2847756SMark.Johnson@Sun.COM 		return (DDI_FAILURE);
2857756SMark.Johnson@Sun.COM 	}
2867756SMark.Johnson@Sun.COM 
2877756SMark.Johnson@Sun.COM 	ring->ri_kstats->ks_private = ring;
2887756SMark.Johnson@Sun.COM 	ring->ri_kstats->ks_update = blk_kstat_update;
2897756SMark.Johnson@Sun.COM 
2907756SMark.Johnson@Sun.COM 	knp = ring->ri_kstats->ks_data;
2917756SMark.Johnson@Sun.COM 	while (nstat > 0) {
2927756SMark.Johnson@Sun.COM 		kstat_named_init(knp, *cp, KSTAT_DATA_UINT64);
2937756SMark.Johnson@Sun.COM 		knp++;
2947756SMark.Johnson@Sun.COM 		cp++;
2957756SMark.Johnson@Sun.COM 		nstat--;
2967756SMark.Johnson@Sun.COM 	}
2977756SMark.Johnson@Sun.COM 
2987756SMark.Johnson@Sun.COM 	kstat_install(ring->ri_kstats);
2997756SMark.Johnson@Sun.COM 
3007756SMark.Johnson@Sun.COM 	return (DDI_SUCCESS);
3017756SMark.Johnson@Sun.COM }
3027756SMark.Johnson@Sun.COM 
3037756SMark.Johnson@Sun.COM 
3047756SMark.Johnson@Sun.COM /*
3057756SMark.Johnson@Sun.COM  * blk_kstat_fini()
3067756SMark.Johnson@Sun.COM  */
3077756SMark.Johnson@Sun.COM static void
blk_kstat_fini(blk_ring_t ring)3087756SMark.Johnson@Sun.COM blk_kstat_fini(blk_ring_t ring)
3097756SMark.Johnson@Sun.COM {
3107756SMark.Johnson@Sun.COM 	kstat_delete(ring->ri_kstats);
3117756SMark.Johnson@Sun.COM }
3127756SMark.Johnson@Sun.COM 
3137756SMark.Johnson@Sun.COM 
3147756SMark.Johnson@Sun.COM /*
3157756SMark.Johnson@Sun.COM  * blk_kstat_update()
3167756SMark.Johnson@Sun.COM  */
3177756SMark.Johnson@Sun.COM static int
blk_kstat_update(kstat_t * ksp,int flag)3187756SMark.Johnson@Sun.COM blk_kstat_update(kstat_t *ksp, int flag)
3197756SMark.Johnson@Sun.COM {
3207756SMark.Johnson@Sun.COM 	kstat_named_t *knp;
3217756SMark.Johnson@Sun.COM 	blk_stats_t *stats;
3227756SMark.Johnson@Sun.COM 	blk_ring_t ring;
3237756SMark.Johnson@Sun.COM 
3247756SMark.Johnson@Sun.COM 
3257756SMark.Johnson@Sun.COM 	if (flag != KSTAT_READ) {
3267756SMark.Johnson@Sun.COM 		return (EACCES);
3277756SMark.Johnson@Sun.COM 	}
3287756SMark.Johnson@Sun.COM 
3297756SMark.Johnson@Sun.COM 	ring = ksp->ks_private;
3307756SMark.Johnson@Sun.COM 	stats = &ring->ri_stats;
3317756SMark.Johnson@Sun.COM 	knp = ksp->ks_data;
3327756SMark.Johnson@Sun.COM 
3337756SMark.Johnson@Sun.COM 	/*
3347756SMark.Johnson@Sun.COM 	 * Assignment order should match that of the names in
3357756SMark.Johnson@Sun.COM 	 * blk_stats.
3367756SMark.Johnson@Sun.COM 	 */
3377756SMark.Johnson@Sun.COM 	(knp++)->value.ui64 = stats->bs_req_reads;
3387756SMark.Johnson@Sun.COM 	(knp++)->value.ui64 = stats->bs_req_writes;
3397756SMark.Johnson@Sun.COM 	(knp++)->value.ui64 = stats->bs_req_barriers;
3407756SMark.Johnson@Sun.COM 	(knp++)->value.ui64 = stats->bs_req_flushes;
3417756SMark.Johnson@Sun.COM 	(knp++)->value.ui64 = 0; /* oo_req */
3427756SMark.Johnson@Sun.COM 
3437756SMark.Johnson@Sun.COM 	return (0);
3447756SMark.Johnson@Sun.COM }
3457756SMark.Johnson@Sun.COM 
3467756SMark.Johnson@Sun.COM 
3477756SMark.Johnson@Sun.COM /*
3487756SMark.Johnson@Sun.COM  * blk_oe_state_change()
3497756SMark.Johnson@Sun.COM  */
3507756SMark.Johnson@Sun.COM /*ARGSUSED*/
3517756SMark.Johnson@Sun.COM static void
blk_oe_state_change(dev_info_t * dip,ddi_eventcookie_t id,void * arg,void * impl_data)3527756SMark.Johnson@Sun.COM blk_oe_state_change(dev_info_t *dip, ddi_eventcookie_t id, void *arg,
3537756SMark.Johnson@Sun.COM     void *impl_data)
3547756SMark.Johnson@Sun.COM {
3557756SMark.Johnson@Sun.COM 	XenbusState new_state;
3567756SMark.Johnson@Sun.COM 	blk_ring_t ring;
3577756SMark.Johnson@Sun.COM 
3587756SMark.Johnson@Sun.COM 
3597756SMark.Johnson@Sun.COM 	ring = (blk_ring_t)arg;
3607756SMark.Johnson@Sun.COM 	new_state = *(XenbusState *)impl_data;
3617756SMark.Johnson@Sun.COM 
3627756SMark.Johnson@Sun.COM 	mutex_enter(&ring->ri_mutex);
3637756SMark.Johnson@Sun.COM 
3647756SMark.Johnson@Sun.COM 	if (blk_check_state_transition(ring, new_state) == DDI_FAILURE) {
3657756SMark.Johnson@Sun.COM 		mutex_exit(&ring->ri_mutex);
3667756SMark.Johnson@Sun.COM 		return;
3677756SMark.Johnson@Sun.COM 	}
3687756SMark.Johnson@Sun.COM 
3697756SMark.Johnson@Sun.COM 	switch (new_state) {
3707756SMark.Johnson@Sun.COM 	case XenbusStateInitialised:
3717756SMark.Johnson@Sun.COM 		ASSERT(ring->ri_if_status == BLK_IF_UNKNOWN);
3727756SMark.Johnson@Sun.COM 
3737756SMark.Johnson@Sun.COM 		/* frontend is ready for connecting */
3747756SMark.Johnson@Sun.COM 		ring->ri_fe_status = BLK_FE_READY;
3757756SMark.Johnson@Sun.COM 
3767756SMark.Johnson@Sun.COM 		if (ring->ri_be_status == BLK_BE_READY) {
3777756SMark.Johnson@Sun.COM 			mutex_exit(&ring->ri_mutex);
3787756SMark.Johnson@Sun.COM 			if (blk_start_connect(ring) != DDI_SUCCESS)
3797756SMark.Johnson@Sun.COM 				(void) blk_start_disconnect(ring);
3807756SMark.Johnson@Sun.COM 			mutex_enter(&ring->ri_mutex);
3817756SMark.Johnson@Sun.COM 		}
3827756SMark.Johnson@Sun.COM 		break;
3837756SMark.Johnson@Sun.COM 	case XenbusStateClosing:
3847756SMark.Johnson@Sun.COM 		(void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosing);
3857756SMark.Johnson@Sun.COM 		break;
3867756SMark.Johnson@Sun.COM 	case XenbusStateClosed:
3877756SMark.Johnson@Sun.COM 		/* clean up */
3887756SMark.Johnson@Sun.COM 		(void) xvdi_post_event(ring->ri_dip, XEN_HP_REMOVE);
3897756SMark.Johnson@Sun.COM 		if (ring->ri_ringdown != NULL) {
3907756SMark.Johnson@Sun.COM 			(*(ring->ri_ringdown))(ring->ri_ringdown_arg);
3917756SMark.Johnson@Sun.COM 		}
3927756SMark.Johnson@Sun.COM 		blk_ring_close(ring);
3937756SMark.Johnson@Sun.COM 
3947756SMark.Johnson@Sun.COM 		/* reset state in case of reconnect */
3957756SMark.Johnson@Sun.COM 		ring->ri_if_status = BLK_IF_UNKNOWN;
3967756SMark.Johnson@Sun.COM 		ring->ri_be_status = BLK_BE_UNKNOWN;
3977756SMark.Johnson@Sun.COM 		ring->ri_fe_status = BLK_FE_UNKNOWN;
3987756SMark.Johnson@Sun.COM 		ring->ri_state.rs_sleeping_on_ring = B_FALSE;
3997756SMark.Johnson@Sun.COM 		ring->ri_state.rs_ring_up = B_FALSE;
4007756SMark.Johnson@Sun.COM 
4017756SMark.Johnson@Sun.COM 		break;
4027756SMark.Johnson@Sun.COM 	default:
4037756SMark.Johnson@Sun.COM 		ASSERT(0);
4047756SMark.Johnson@Sun.COM 	}
4057756SMark.Johnson@Sun.COM 
4067756SMark.Johnson@Sun.COM 	mutex_exit(&ring->ri_mutex);
4077756SMark.Johnson@Sun.COM }
4087756SMark.Johnson@Sun.COM 
4097756SMark.Johnson@Sun.COM 
4107756SMark.Johnson@Sun.COM /*
4117756SMark.Johnson@Sun.COM  * blk_hp_state_change()
4127756SMark.Johnson@Sun.COM  */
4137756SMark.Johnson@Sun.COM /*ARGSUSED*/
4147756SMark.Johnson@Sun.COM static void
blk_hp_state_change(dev_info_t * dip,ddi_eventcookie_t id,void * arg,void * impl_data)4157756SMark.Johnson@Sun.COM blk_hp_state_change(dev_info_t *dip, ddi_eventcookie_t id, void *arg,
4167756SMark.Johnson@Sun.COM     void *impl_data)
4177756SMark.Johnson@Sun.COM {
4187756SMark.Johnson@Sun.COM 	xendev_hotplug_state_t hpstate;
4197756SMark.Johnson@Sun.COM 	blk_ring_t ring;
4207756SMark.Johnson@Sun.COM 
4217756SMark.Johnson@Sun.COM 
4227756SMark.Johnson@Sun.COM 	ring = (blk_ring_t)arg;
4237756SMark.Johnson@Sun.COM 	hpstate = *(xendev_hotplug_state_t *)impl_data;
4247756SMark.Johnson@Sun.COM 
4257756SMark.Johnson@Sun.COM 	mutex_enter(&ring->ri_mutex);
4267756SMark.Johnson@Sun.COM 	if (hpstate == Connected) {
4277756SMark.Johnson@Sun.COM 		/* Hotplug script has completed successfully */
4287756SMark.Johnson@Sun.COM 		if (ring->ri_be_status == BLK_BE_UNKNOWN) {
4297756SMark.Johnson@Sun.COM 			ring->ri_be_status = BLK_BE_READY;
4307756SMark.Johnson@Sun.COM 			if (ring->ri_fe_status == BLK_FE_READY) {
4317756SMark.Johnson@Sun.COM 				mutex_exit(&ring->ri_mutex);
4327756SMark.Johnson@Sun.COM 				/* try to connect to frontend */
4337756SMark.Johnson@Sun.COM 				if (blk_start_connect(ring) != DDI_SUCCESS)
4347756SMark.Johnson@Sun.COM 					(void) blk_start_disconnect(ring);
4357756SMark.Johnson@Sun.COM 				mutex_enter(&ring->ri_mutex);
4367756SMark.Johnson@Sun.COM 			}
4377756SMark.Johnson@Sun.COM 		}
4387756SMark.Johnson@Sun.COM 	}
4397756SMark.Johnson@Sun.COM 	mutex_exit(&ring->ri_mutex);
4407756SMark.Johnson@Sun.COM }
4417756SMark.Johnson@Sun.COM 
4427756SMark.Johnson@Sun.COM 
4437756SMark.Johnson@Sun.COM /*
4447756SMark.Johnson@Sun.COM  * blk_check_state_transition()
4457756SMark.Johnson@Sun.COM  *    check the XenbusState change to see if the change is a valid transition
4467756SMark.Johnson@Sun.COM  *    or not. The new state is written by frontend domain, or by running
4477756SMark.Johnson@Sun.COM  *    xenstore-write to change it manually in dom0.
4487756SMark.Johnson@Sun.COM  */
4497756SMark.Johnson@Sun.COM static int
blk_check_state_transition(blk_ring_t ring,XenbusState oestate)4507756SMark.Johnson@Sun.COM blk_check_state_transition(blk_ring_t ring, XenbusState oestate)
4517756SMark.Johnson@Sun.COM {
4527756SMark.Johnson@Sun.COM 	switch (ring->ri_if_status) {
4537756SMark.Johnson@Sun.COM 	case BLK_IF_UNKNOWN:
4547756SMark.Johnson@Sun.COM 		if (ring->ri_fe_status == BLK_FE_UNKNOWN) {
4557756SMark.Johnson@Sun.COM 			if ((oestate == XenbusStateUnknown)		||
4567756SMark.Johnson@Sun.COM 			    (oestate == XenbusStateConnected))
4577756SMark.Johnson@Sun.COM 				goto statechkfail_bug;
4587756SMark.Johnson@Sun.COM 			else if ((oestate == XenbusStateInitialising)	||
4597756SMark.Johnson@Sun.COM 			    (oestate == XenbusStateInitWait))
4607756SMark.Johnson@Sun.COM 				goto statechkfail_nop;
4617756SMark.Johnson@Sun.COM 		} else {
4627756SMark.Johnson@Sun.COM 			if ((oestate == XenbusStateUnknown)		||
4637756SMark.Johnson@Sun.COM 			    (oestate == XenbusStateInitialising)	||
4647756SMark.Johnson@Sun.COM 			    (oestate == XenbusStateInitWait)		||
4657756SMark.Johnson@Sun.COM 			    (oestate == XenbusStateConnected))
4667756SMark.Johnson@Sun.COM 				goto statechkfail_bug;
4677756SMark.Johnson@Sun.COM 			else if (oestate == XenbusStateInitialised)
4687756SMark.Johnson@Sun.COM 				goto statechkfail_nop;
4697756SMark.Johnson@Sun.COM 		}
4707756SMark.Johnson@Sun.COM 		break;
4717756SMark.Johnson@Sun.COM 
4727756SMark.Johnson@Sun.COM 	case BLK_IF_CONNECTED:
4737756SMark.Johnson@Sun.COM 		if ((oestate == XenbusStateUnknown)		||
4747756SMark.Johnson@Sun.COM 		    (oestate == XenbusStateInitialising)	||
4757756SMark.Johnson@Sun.COM 		    (oestate == XenbusStateInitWait)		||
4767756SMark.Johnson@Sun.COM 		    (oestate == XenbusStateInitialised))
4777756SMark.Johnson@Sun.COM 			goto statechkfail_bug;
4787756SMark.Johnson@Sun.COM 		else if (oestate == XenbusStateConnected)
4797756SMark.Johnson@Sun.COM 			goto statechkfail_nop;
4807756SMark.Johnson@Sun.COM 		break;
4817756SMark.Johnson@Sun.COM 
4827756SMark.Johnson@Sun.COM 	case BLK_IF_DISCONNECTED:
4837756SMark.Johnson@Sun.COM 	default:
4847756SMark.Johnson@Sun.COM 		goto statechkfail_bug;
4857756SMark.Johnson@Sun.COM 	}
4867756SMark.Johnson@Sun.COM 
4877756SMark.Johnson@Sun.COM 	return (DDI_SUCCESS);
4887756SMark.Johnson@Sun.COM 
4897756SMark.Johnson@Sun.COM statechkfail_bug:
4907756SMark.Johnson@Sun.COM 	cmn_err(CE_NOTE, "blk@%s: unexpected otherend "
4917756SMark.Johnson@Sun.COM 	    "state change to %d!, when status is %d",
4927756SMark.Johnson@Sun.COM 	    ddi_get_name_addr(ring->ri_dip), oestate,
4937756SMark.Johnson@Sun.COM 	    ring->ri_if_status);
4947756SMark.Johnson@Sun.COM 
4957756SMark.Johnson@Sun.COM statechkfail_nop:
4967756SMark.Johnson@Sun.COM 	return (DDI_FAILURE);
4977756SMark.Johnson@Sun.COM }
4987756SMark.Johnson@Sun.COM 
4997756SMark.Johnson@Sun.COM 
5007756SMark.Johnson@Sun.COM /*
5017756SMark.Johnson@Sun.COM  * blk_start_connect()
5027756SMark.Johnson@Sun.COM  *    Kick-off connect process
5037756SMark.Johnson@Sun.COM  *    If ri_fe_status == BLK_FE_READY and ri_be_status == BLK_BE_READY
5047756SMark.Johnson@Sun.COM  *    the ri_if_status will be changed to BLK_IF_CONNECTED on success,
5057756SMark.Johnson@Sun.COM  *    otherwise, ri_if_status will not be changed
5067756SMark.Johnson@Sun.COM  */
5077756SMark.Johnson@Sun.COM static int
blk_start_connect(blk_ring_t ring)5087756SMark.Johnson@Sun.COM blk_start_connect(blk_ring_t ring)
5097756SMark.Johnson@Sun.COM {
5107756SMark.Johnson@Sun.COM 	xenbus_transaction_t xbt;
5117756SMark.Johnson@Sun.COM 	dev_info_t *dip;
5127756SMark.Johnson@Sun.COM 	char *barrier;
5137756SMark.Johnson@Sun.COM 	char *xsnode;
5147756SMark.Johnson@Sun.COM 	uint_t len;
5157756SMark.Johnson@Sun.COM 	int e;
5167756SMark.Johnson@Sun.COM 
5177756SMark.Johnson@Sun.COM 
5187756SMark.Johnson@Sun.COM 	dip = ring->ri_dip;
5197756SMark.Johnson@Sun.COM 
5207756SMark.Johnson@Sun.COM 	/*
5217756SMark.Johnson@Sun.COM 	 * Start connect to frontend only when backend device are ready
5227756SMark.Johnson@Sun.COM 	 * and frontend has moved to XenbusStateInitialised, which means
5237756SMark.Johnson@Sun.COM 	 * ready to connect
5247756SMark.Johnson@Sun.COM 	 */
5257756SMark.Johnson@Sun.COM 	ASSERT(ring->ri_fe_status == BLK_FE_READY);
5267756SMark.Johnson@Sun.COM 	ASSERT(ring->ri_be_status == BLK_BE_READY);
5277756SMark.Johnson@Sun.COM 
5287756SMark.Johnson@Sun.COM 	xsnode = xvdi_get_xsname(dip);
5297756SMark.Johnson@Sun.COM 	if (xsnode == NULL) {
5307756SMark.Johnson@Sun.COM 		goto startconnectfail_get_xsname;
5317756SMark.Johnson@Sun.COM 	}
5327756SMark.Johnson@Sun.COM 
5337756SMark.Johnson@Sun.COM 	ring->ri_fe = xvdi_get_oeid(dip);
5347756SMark.Johnson@Sun.COM 	if (ring->ri_fe == (domid_t)-1) {
5357756SMark.Johnson@Sun.COM 		goto startconnectfail_get_oeid;
5367756SMark.Johnson@Sun.COM 	}
5377756SMark.Johnson@Sun.COM 
5387756SMark.Johnson@Sun.COM 	e =  xvdi_switch_state(dip, XBT_NULL, XenbusStateInitialised);
5397756SMark.Johnson@Sun.COM 	if (e > 0) {
5407756SMark.Johnson@Sun.COM 		goto startconnectfail_switch_init;
5417756SMark.Johnson@Sun.COM 	}
5427756SMark.Johnson@Sun.COM 
5437756SMark.Johnson@Sun.COM 	e = blk_bindto_frontend(ring);
5447756SMark.Johnson@Sun.COM 	if (e != DDI_SUCCESS) {
5457756SMark.Johnson@Sun.COM 		goto startconnectfail_bindto_frontend;
5467756SMark.Johnson@Sun.COM 	}
5477756SMark.Johnson@Sun.COM 	ring->ri_if_status = BLK_IF_CONNECTED;
5487756SMark.Johnson@Sun.COM 
5497756SMark.Johnson@Sun.COM 	e = ddi_add_intr(dip, 0, NULL, NULL, blk_intr, (caddr_t)ring);
5507756SMark.Johnson@Sun.COM 	if (e != DDI_SUCCESS) {
5517756SMark.Johnson@Sun.COM 		goto startconnectfail_add_intr;
5527756SMark.Johnson@Sun.COM 	}
5537756SMark.Johnson@Sun.COM 
5547756SMark.Johnson@Sun.COM trans_retry:
5557756SMark.Johnson@Sun.COM 	e = xenbus_transaction_start(&xbt);
5567756SMark.Johnson@Sun.COM 	if (e != 0) {
5577756SMark.Johnson@Sun.COM 		xvdi_fatal_error(dip, e, "transaction start");
5587756SMark.Johnson@Sun.COM 		goto startconnectfail_transaction_start;
5597756SMark.Johnson@Sun.COM 	}
5607756SMark.Johnson@Sun.COM 
561*10581SMark.Johnson@Sun.COM 	/* xentop requires the instance in xenstore */
562*10581SMark.Johnson@Sun.COM 	e = xenbus_printf(xbt, xsnode, "instance", "%d",
563*10581SMark.Johnson@Sun.COM 	    ddi_get_instance(ring->ri_dip));
564*10581SMark.Johnson@Sun.COM 	if (e != 0) {
565*10581SMark.Johnson@Sun.COM 		cmn_err(CE_WARN, "xdb@%s: failed to write 'instance'",
566*10581SMark.Johnson@Sun.COM 		    ddi_get_name_addr(dip));
567*10581SMark.Johnson@Sun.COM 		xvdi_fatal_error(dip, e, "writing 'instance'");
568*10581SMark.Johnson@Sun.COM 		(void) xenbus_transaction_end(xbt, 1);
569*10581SMark.Johnson@Sun.COM 		goto startconnectfail_xenbus_printf;
570*10581SMark.Johnson@Sun.COM 	}
571*10581SMark.Johnson@Sun.COM 
5727756SMark.Johnson@Sun.COM 	/* If feature-barrier isn't present in xenstore, add it */
5737756SMark.Johnson@Sun.COM 	e = xenbus_read(xbt, xsnode, "feature-barrier", (void **)&barrier,
5747756SMark.Johnson@Sun.COM 	    &len);
5757756SMark.Johnson@Sun.COM 	if (e != 0) {
5767756SMark.Johnson@Sun.COM 		e = xenbus_printf(xbt, xsnode, "feature-barrier", "%d", 1);
5777756SMark.Johnson@Sun.COM 		if (e != 0) {
5787756SMark.Johnson@Sun.COM 			cmn_err(CE_WARN, "xdb@%s: failed to write "
5797756SMark.Johnson@Sun.COM 			    "'feature-barrier'", ddi_get_name_addr(dip));
5807756SMark.Johnson@Sun.COM 			xvdi_fatal_error(dip, e, "writing 'feature-barrier'");
5817756SMark.Johnson@Sun.COM 			(void) xenbus_transaction_end(xbt, 1);
5827756SMark.Johnson@Sun.COM 			goto startconnectfail_xenbus_printf;
5837756SMark.Johnson@Sun.COM 		}
5847756SMark.Johnson@Sun.COM 	} else {
5857756SMark.Johnson@Sun.COM 		kmem_free(barrier, len);
5867756SMark.Johnson@Sun.COM 	}
5877756SMark.Johnson@Sun.COM 
5887756SMark.Johnson@Sun.COM 	e = xvdi_switch_state(dip, xbt, XenbusStateConnected);
5897756SMark.Johnson@Sun.COM 	if (e > 0) {
5907756SMark.Johnson@Sun.COM 		xvdi_fatal_error(dip, e, "writing 'state'");
5917756SMark.Johnson@Sun.COM 		(void) xenbus_transaction_end(xbt, 1);
5927756SMark.Johnson@Sun.COM 		goto startconnectfail_switch_connected;
5937756SMark.Johnson@Sun.COM 	}
5947756SMark.Johnson@Sun.COM 
5957756SMark.Johnson@Sun.COM 	e = xenbus_transaction_end(xbt, 0);
5967756SMark.Johnson@Sun.COM 	if (e != 0) {
5977756SMark.Johnson@Sun.COM 		if (e == EAGAIN) {
5987756SMark.Johnson@Sun.COM 			/* transaction is ended, don't need to abort it */
5997756SMark.Johnson@Sun.COM 			goto trans_retry;
6007756SMark.Johnson@Sun.COM 		}
6017756SMark.Johnson@Sun.COM 		xvdi_fatal_error(dip, e, "completing transaction");
6027756SMark.Johnson@Sun.COM 		goto startconnectfail_transaction_end;
6037756SMark.Johnson@Sun.COM 	}
6047756SMark.Johnson@Sun.COM 
6057756SMark.Johnson@Sun.COM 	mutex_enter(&ring->ri_state.rs_mutex);
6067756SMark.Johnson@Sun.COM 	ring->ri_state.rs_ring_up = B_TRUE;
6077756SMark.Johnson@Sun.COM 	if (ring->ri_state.rs_sleeping_on_ring) {
6087756SMark.Johnson@Sun.COM 		ring->ri_state.rs_sleeping_on_ring = B_FALSE;
6097756SMark.Johnson@Sun.COM 		cv_signal(&ring->ri_state.rs_cv);
6107756SMark.Johnson@Sun.COM 	}
6117756SMark.Johnson@Sun.COM 	mutex_exit(&ring->ri_state.rs_mutex);
6127756SMark.Johnson@Sun.COM 
6137756SMark.Johnson@Sun.COM 	if (ring->ri_ringup != NULL) {
6147756SMark.Johnson@Sun.COM 		(*(ring->ri_ringup))(ring->ri_ringup_arg);
6157756SMark.Johnson@Sun.COM 	}
6167756SMark.Johnson@Sun.COM 
6177756SMark.Johnson@Sun.COM 	return (DDI_SUCCESS);
6187756SMark.Johnson@Sun.COM 
6197756SMark.Johnson@Sun.COM 
6207756SMark.Johnson@Sun.COM startconnectfail_transaction_end:
6217756SMark.Johnson@Sun.COM startconnectfail_switch_connected:
6227756SMark.Johnson@Sun.COM startconnectfail_xenbus_printf:
6237756SMark.Johnson@Sun.COM startconnectfail_transaction_start:
6247756SMark.Johnson@Sun.COM 	ddi_remove_intr(dip, 0, NULL);
6257756SMark.Johnson@Sun.COM startconnectfail_add_intr:
6267756SMark.Johnson@Sun.COM 	blk_unbindfrom_frontend(ring);
6277756SMark.Johnson@Sun.COM 	ring->ri_fe = (domid_t)-1;
6287756SMark.Johnson@Sun.COM startconnectfail_bindto_frontend:
6297756SMark.Johnson@Sun.COM 	(void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosed);
6307756SMark.Johnson@Sun.COM startconnectfail_switch_init:
6317756SMark.Johnson@Sun.COM startconnectfail_get_oeid:
6327756SMark.Johnson@Sun.COM startconnectfail_get_xsname:
6337756SMark.Johnson@Sun.COM 	return (DDI_FAILURE);
6347756SMark.Johnson@Sun.COM }
6357756SMark.Johnson@Sun.COM 
6367756SMark.Johnson@Sun.COM 
6377756SMark.Johnson@Sun.COM /*
6387756SMark.Johnson@Sun.COM  * blk_start_disconnect()
6397756SMark.Johnson@Sun.COM  *    Kick-off disconnect process. ri_if_status will not be changed
6407756SMark.Johnson@Sun.COM  */
6417756SMark.Johnson@Sun.COM static void
blk_start_disconnect(blk_ring_t ring)6427756SMark.Johnson@Sun.COM blk_start_disconnect(blk_ring_t ring)
6437756SMark.Johnson@Sun.COM {
6447756SMark.Johnson@Sun.COM 	/* Kick-off disconnect process */
6457756SMark.Johnson@Sun.COM 	(void) xvdi_switch_state(ring->ri_dip, XBT_NULL, XenbusStateClosing);
6467756SMark.Johnson@Sun.COM }
6477756SMark.Johnson@Sun.COM 
6487756SMark.Johnson@Sun.COM 
6497756SMark.Johnson@Sun.COM /*
6507756SMark.Johnson@Sun.COM  * blk_ring_close()
6517756SMark.Johnson@Sun.COM  *    Disconnect from frontend and close backend device
6527756SMark.Johnson@Sun.COM  *    ifstatus will be changed to BLK_DISCONNECTED
6537756SMark.Johnson@Sun.COM  *    Xenbus state will be changed to XenbusStateClosed
6547756SMark.Johnson@Sun.COM  */
6557756SMark.Johnson@Sun.COM static void
blk_ring_close(blk_ring_t ring)6567756SMark.Johnson@Sun.COM blk_ring_close(blk_ring_t ring)
6577756SMark.Johnson@Sun.COM {
6587756SMark.Johnson@Sun.COM 	dev_info_t *dip;
6597756SMark.Johnson@Sun.COM 
6607756SMark.Johnson@Sun.COM 
6617756SMark.Johnson@Sun.COM 	/* mutex protect ri_if_status only here */
6627756SMark.Johnson@Sun.COM 	ASSERT(MUTEX_HELD(&ring->ri_mutex));
6637756SMark.Johnson@Sun.COM 
6647756SMark.Johnson@Sun.COM 	dip = ring->ri_dip;
6657756SMark.Johnson@Sun.COM 
6667756SMark.Johnson@Sun.COM 	if (ring->ri_if_status != BLK_IF_CONNECTED) {
6677756SMark.Johnson@Sun.COM 		return;
6687756SMark.Johnson@Sun.COM 	}
6697756SMark.Johnson@Sun.COM 
6707756SMark.Johnson@Sun.COM 	ring->ri_if_status = BLK_IF_DISCONNECTED;
6717756SMark.Johnson@Sun.COM 	mutex_exit(&ring->ri_mutex);
6727756SMark.Johnson@Sun.COM 
6737756SMark.Johnson@Sun.COM 	/* stop accepting I/O request from frontend */
6747756SMark.Johnson@Sun.COM 	ddi_remove_intr(dip, 0, NULL);
6757756SMark.Johnson@Sun.COM 
6767756SMark.Johnson@Sun.COM 	blk_unbindfrom_frontend(ring);
6777756SMark.Johnson@Sun.COM 	ring->ri_fe = (domid_t)-1;
6787756SMark.Johnson@Sun.COM 	(void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosed);
6797756SMark.Johnson@Sun.COM 	mutex_enter(&ring->ri_mutex);
6807756SMark.Johnson@Sun.COM }
6817756SMark.Johnson@Sun.COM 
6827756SMark.Johnson@Sun.COM 
6837756SMark.Johnson@Sun.COM /*
6847756SMark.Johnson@Sun.COM  * blk_bindto_frontend()
6857756SMark.Johnson@Sun.COM  */
6867756SMark.Johnson@Sun.COM static int
blk_bindto_frontend(blk_ring_t ring)6877756SMark.Johnson@Sun.COM blk_bindto_frontend(blk_ring_t ring)
6887756SMark.Johnson@Sun.COM {
6897756SMark.Johnson@Sun.COM 	evtchn_port_t evtchn;
6907756SMark.Johnson@Sun.COM 	char protocol[64];
6917756SMark.Johnson@Sun.COM 	grant_ref_t gref;
6927756SMark.Johnson@Sun.COM 	dev_info_t *dip;
6937756SMark.Johnson@Sun.COM 	char *oename;
6947756SMark.Johnson@Sun.COM 	int e;
6957756SMark.Johnson@Sun.COM 
6967756SMark.Johnson@Sun.COM 
6977756SMark.Johnson@Sun.COM 	dip = ring->ri_dip;
6987756SMark.Johnson@Sun.COM 	protocol[0] = 0x0;
6997756SMark.Johnson@Sun.COM 
7007756SMark.Johnson@Sun.COM 	/*
7017756SMark.Johnson@Sun.COM 	 * Gather info from frontend
7027756SMark.Johnson@Sun.COM 	 */
7037756SMark.Johnson@Sun.COM 	oename = xvdi_get_oename(dip);
7047756SMark.Johnson@Sun.COM 	if (oename == NULL) {
7057756SMark.Johnson@Sun.COM 		return (DDI_FAILURE);
7067756SMark.Johnson@Sun.COM 	}
7077756SMark.Johnson@Sun.COM 
7087756SMark.Johnson@Sun.COM 	e = xenbus_gather(XBT_NULL, oename, "ring-ref", "%lu", &gref,
7097756SMark.Johnson@Sun.COM 	    "event-channel", "%u", &evtchn, NULL);
7107756SMark.Johnson@Sun.COM 	if (e != 0) {
7117756SMark.Johnson@Sun.COM 		xvdi_fatal_error(dip, e,
7127756SMark.Johnson@Sun.COM 		    "Getting ring-ref and evtchn from frontend");
7137756SMark.Johnson@Sun.COM 		return (DDI_FAILURE);
7147756SMark.Johnson@Sun.COM 	}
7157756SMark.Johnson@Sun.COM 
7167756SMark.Johnson@Sun.COM 	e = xenbus_gather(XBT_NULL, oename, "protocol", "%63s",
7177756SMark.Johnson@Sun.COM 	    protocol, NULL);
7187756SMark.Johnson@Sun.COM 	if (e != 0) {
7197756SMark.Johnson@Sun.COM 		(void) strcpy(protocol, "unspecified, assuming native");
7207756SMark.Johnson@Sun.COM 	} else if (strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE) == 0) {
7217756SMark.Johnson@Sun.COM 		ring->ri_protocol = BLKIF_PROTOCOL_NATIVE;
7227756SMark.Johnson@Sun.COM 		ring->ri_nentry = BLKIF_RING_SIZE;
7237756SMark.Johnson@Sun.COM 		ring->ri_entrysize = sizeof (union blkif_sring_entry);
7247756SMark.Johnson@Sun.COM 	} else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) {
7257756SMark.Johnson@Sun.COM 		ring->ri_protocol = BLKIF_PROTOCOL_X86_32;
7267756SMark.Johnson@Sun.COM 		ring->ri_nentry = BLKIF_X86_32_RING_SIZE;
7277756SMark.Johnson@Sun.COM 		ring->ri_entrysize = sizeof (union blkif_x86_32_sring_entry);
7287756SMark.Johnson@Sun.COM 	} else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_64) == 0) {
7297756SMark.Johnson@Sun.COM 		ring->ri_protocol = BLKIF_PROTOCOL_X86_64;
7307756SMark.Johnson@Sun.COM 		ring->ri_nentry = BLKIF_X86_64_RING_SIZE;
7317756SMark.Johnson@Sun.COM 		ring->ri_entrysize = sizeof (union blkif_x86_64_sring_entry);
7327756SMark.Johnson@Sun.COM 	} else {
7337756SMark.Johnson@Sun.COM 		xvdi_fatal_error(dip, e, "unknown fe protocol");
7347756SMark.Johnson@Sun.COM 		return (DDI_FAILURE);
7357756SMark.Johnson@Sun.COM 	}
7367756SMark.Johnson@Sun.COM 
7377756SMark.Johnson@Sun.COM 	/*
7387756SMark.Johnson@Sun.COM 	 * map and init ring
7397756SMark.Johnson@Sun.COM 	 */
7407756SMark.Johnson@Sun.COM 	e = xvdi_map_ring(dip, ring->ri_nentry, ring->ri_entrysize, gref,
7417756SMark.Johnson@Sun.COM 	    &ring->ri_ring);
7427756SMark.Johnson@Sun.COM 	if (e != DDI_SUCCESS) {
7437756SMark.Johnson@Sun.COM 		return (DDI_FAILURE);
7447756SMark.Johnson@Sun.COM 	}
7457756SMark.Johnson@Sun.COM 
7467756SMark.Johnson@Sun.COM 	/*
7477756SMark.Johnson@Sun.COM 	 * bind event channel
7487756SMark.Johnson@Sun.COM 	 */
7497756SMark.Johnson@Sun.COM 	e = xvdi_bind_evtchn(dip, evtchn);
7507756SMark.Johnson@Sun.COM 	if (e != DDI_SUCCESS) {
7517756SMark.Johnson@Sun.COM 		xvdi_unmap_ring(ring->ri_ring);
7527756SMark.Johnson@Sun.COM 		return (DDI_FAILURE);
7537756SMark.Johnson@Sun.COM 	}
7547756SMark.Johnson@Sun.COM 
7557756SMark.Johnson@Sun.COM 
7567756SMark.Johnson@Sun.COM 	return (DDI_SUCCESS);
7577756SMark.Johnson@Sun.COM }
7587756SMark.Johnson@Sun.COM 
7597756SMark.Johnson@Sun.COM 
7607756SMark.Johnson@Sun.COM /*
7617756SMark.Johnson@Sun.COM  * blk_unbindfrom_frontend()
7627756SMark.Johnson@Sun.COM  */
7637756SMark.Johnson@Sun.COM static void
blk_unbindfrom_frontend(blk_ring_t ring)7647756SMark.Johnson@Sun.COM blk_unbindfrom_frontend(blk_ring_t ring)
7657756SMark.Johnson@Sun.COM {
7667756SMark.Johnson@Sun.COM 	xvdi_free_evtchn(ring->ri_dip);
7677756SMark.Johnson@Sun.COM 	xvdi_unmap_ring(ring->ri_ring);
7687756SMark.Johnson@Sun.COM }
7697756SMark.Johnson@Sun.COM 
7707756SMark.Johnson@Sun.COM 
7717756SMark.Johnson@Sun.COM /*
7727756SMark.Johnson@Sun.COM  * blk_intr()
7737756SMark.Johnson@Sun.COM  */
7747756SMark.Johnson@Sun.COM static uint_t
blk_intr(caddr_t arg)7757756SMark.Johnson@Sun.COM blk_intr(caddr_t arg)
7767756SMark.Johnson@Sun.COM {
7777756SMark.Johnson@Sun.COM 	blk_ring_t ring;
7787756SMark.Johnson@Sun.COM 
7797756SMark.Johnson@Sun.COM 	ring = (blk_ring_t)arg;
7807756SMark.Johnson@Sun.COM 	if (ring->ri_if_status != BLK_IF_CONNECTED) {
7817756SMark.Johnson@Sun.COM 		return (DDI_INTR_CLAIMED);
7827756SMark.Johnson@Sun.COM 	}
7837756SMark.Johnson@Sun.COM 
7847756SMark.Johnson@Sun.COM 	(void) (*ring->ri_intr)(ring->ri_intr_arg);
7857756SMark.Johnson@Sun.COM 	return (DDI_INTR_CLAIMED);
7867756SMark.Johnson@Sun.COM }
7877756SMark.Johnson@Sun.COM 
7887756SMark.Johnson@Sun.COM 
7897756SMark.Johnson@Sun.COM /*
7907756SMark.Johnson@Sun.COM  * blk_ring_request_get()
7917756SMark.Johnson@Sun.COM  */
7927756SMark.Johnson@Sun.COM boolean_t
blk_ring_request_get(blk_ring_t ring,blkif_request_t * req)7937756SMark.Johnson@Sun.COM blk_ring_request_get(blk_ring_t ring, blkif_request_t *req)
7947756SMark.Johnson@Sun.COM {
7957756SMark.Johnson@Sun.COM 	blkif_request_t *src;
7967756SMark.Johnson@Sun.COM 	blk_stats_t *stats;
7977756SMark.Johnson@Sun.COM 
7987756SMark.Johnson@Sun.COM 
7997756SMark.Johnson@Sun.COM 	mutex_enter(&ring->ri_mutex);
80010175SStuart.Maybee@Sun.COM 
80110175SStuart.Maybee@Sun.COM 	if (ring->ri_if_status != BLK_IF_CONNECTED) {
80210175SStuart.Maybee@Sun.COM 		mutex_exit(&ring->ri_mutex);
80310175SStuart.Maybee@Sun.COM 		return (B_FALSE);
80410175SStuart.Maybee@Sun.COM 	}
80510175SStuart.Maybee@Sun.COM 
8067756SMark.Johnson@Sun.COM 	src = xvdi_ring_get_request(ring->ri_ring);
8077756SMark.Johnson@Sun.COM 	if (src == NULL) {
8087756SMark.Johnson@Sun.COM 		mutex_exit(&ring->ri_mutex);
8097756SMark.Johnson@Sun.COM 		return (B_FALSE);
8107756SMark.Johnson@Sun.COM 	}
8117756SMark.Johnson@Sun.COM 
8127756SMark.Johnson@Sun.COM 	switch (ring->ri_protocol) {
8137756SMark.Johnson@Sun.COM 	case BLKIF_PROTOCOL_NATIVE:
8147756SMark.Johnson@Sun.COM 		bcopy(src, req, sizeof (*req));
8157756SMark.Johnson@Sun.COM 		break;
8167756SMark.Johnson@Sun.COM 	case BLKIF_PROTOCOL_X86_32:
8177756SMark.Johnson@Sun.COM 		blk_ring_request_32(req, (blkif_x86_32_request_t *)src);
8187756SMark.Johnson@Sun.COM 		break;
8197756SMark.Johnson@Sun.COM 	case BLKIF_PROTOCOL_X86_64:
8207756SMark.Johnson@Sun.COM 		blk_ring_request_64(req, (blkif_x86_64_request_t *)src);
8217756SMark.Johnson@Sun.COM 		break;
8227756SMark.Johnson@Sun.COM 	default:
8237756SMark.Johnson@Sun.COM 		cmn_err(CE_WARN, "blkif@%s: unrecognised protocol: %d",
8247756SMark.Johnson@Sun.COM 		    ddi_get_name_addr(ring->ri_dip),
8257756SMark.Johnson@Sun.COM 		    ring->ri_protocol);
8267756SMark.Johnson@Sun.COM 	}
8277756SMark.Johnson@Sun.COM 	mutex_exit(&ring->ri_mutex);
8287756SMark.Johnson@Sun.COM 
8297756SMark.Johnson@Sun.COM 	stats = &ring->ri_stats;
8307756SMark.Johnson@Sun.COM 	switch (req->operation) {
8317756SMark.Johnson@Sun.COM 	case BLKIF_OP_READ:
8327756SMark.Johnson@Sun.COM 		stats->bs_req_reads++;
8337756SMark.Johnson@Sun.COM 		break;
8347756SMark.Johnson@Sun.COM 	case BLKIF_OP_WRITE:
8357756SMark.Johnson@Sun.COM 		stats->bs_req_writes++;
8367756SMark.Johnson@Sun.COM 		break;
8377756SMark.Johnson@Sun.COM 	case BLKIF_OP_WRITE_BARRIER:
8387756SMark.Johnson@Sun.COM 		stats->bs_req_barriers++;
8397756SMark.Johnson@Sun.COM 		break;
8407756SMark.Johnson@Sun.COM 	case BLKIF_OP_FLUSH_DISKCACHE:
8417756SMark.Johnson@Sun.COM 		stats->bs_req_flushes++;
8427756SMark.Johnson@Sun.COM 		break;
8437756SMark.Johnson@Sun.COM 	}
8447756SMark.Johnson@Sun.COM 
8457756SMark.Johnson@Sun.COM 	return (B_TRUE);
8467756SMark.Johnson@Sun.COM }
8477756SMark.Johnson@Sun.COM 
8487756SMark.Johnson@Sun.COM 
8497756SMark.Johnson@Sun.COM /*
8507756SMark.Johnson@Sun.COM  * blk_ring_request_requeue()
8517756SMark.Johnson@Sun.COM  *    if a request is requeued, caller will have to poll for request
8527756SMark.Johnson@Sun.COM  *    later.
8537756SMark.Johnson@Sun.COM  */
8547756SMark.Johnson@Sun.COM void
blk_ring_request_requeue(blk_ring_t ring)8557756SMark.Johnson@Sun.COM blk_ring_request_requeue(blk_ring_t ring)
8567756SMark.Johnson@Sun.COM {
85710175SStuart.Maybee@Sun.COM 	mutex_enter(&ring->ri_mutex);
85810175SStuart.Maybee@Sun.COM 
85910175SStuart.Maybee@Sun.COM 	if (ring->ri_if_status != BLK_IF_CONNECTED) {
86010175SStuart.Maybee@Sun.COM 		mutex_exit(&ring->ri_mutex);
86110175SStuart.Maybee@Sun.COM 		return;
86210175SStuart.Maybee@Sun.COM 	}
86310175SStuart.Maybee@Sun.COM 
8647756SMark.Johnson@Sun.COM 	ring->ri_ring->xr_sring.br.req_cons--;
86510175SStuart.Maybee@Sun.COM 
86610175SStuart.Maybee@Sun.COM 	mutex_exit(&ring->ri_mutex);
8677756SMark.Johnson@Sun.COM }
8687756SMark.Johnson@Sun.COM 
8697756SMark.Johnson@Sun.COM 
8707756SMark.Johnson@Sun.COM /*
8717756SMark.Johnson@Sun.COM  * blk_ring_response_put()
8727756SMark.Johnson@Sun.COM  */
8737756SMark.Johnson@Sun.COM void
blk_ring_response_put(blk_ring_t ring,blkif_response_t * src)8747756SMark.Johnson@Sun.COM blk_ring_response_put(blk_ring_t ring, blkif_response_t *src)
8757756SMark.Johnson@Sun.COM {
87610175SStuart.Maybee@Sun.COM 	blkif_response_t *rsp;
8777756SMark.Johnson@Sun.COM 	int e;
8787756SMark.Johnson@Sun.COM 
87910175SStuart.Maybee@Sun.COM 
88010175SStuart.Maybee@Sun.COM 	mutex_enter(&ring->ri_mutex);
88110175SStuart.Maybee@Sun.COM 
88210175SStuart.Maybee@Sun.COM 	if (ring->ri_if_status != BLK_IF_CONNECTED) {
88310175SStuart.Maybee@Sun.COM 		mutex_exit(&ring->ri_mutex);
88410175SStuart.Maybee@Sun.COM 		return;
88510175SStuart.Maybee@Sun.COM 	}
88610175SStuart.Maybee@Sun.COM 
88710175SStuart.Maybee@Sun.COM 	rsp = xvdi_ring_get_response(ring->ri_ring);
8887756SMark.Johnson@Sun.COM 	ASSERT(rsp);
8897756SMark.Johnson@Sun.COM 
8907756SMark.Johnson@Sun.COM 	switch (ring->ri_protocol) {
8917756SMark.Johnson@Sun.COM 	case BLKIF_PROTOCOL_NATIVE:
8927756SMark.Johnson@Sun.COM 		bcopy(src, rsp, sizeof (*rsp));
8937756SMark.Johnson@Sun.COM 		break;
8947756SMark.Johnson@Sun.COM 	case BLKIF_PROTOCOL_X86_32:
8957756SMark.Johnson@Sun.COM 		blk_ring_response_32((blkif_x86_32_response_t *)rsp, src);
8967756SMark.Johnson@Sun.COM 		break;
8977756SMark.Johnson@Sun.COM 	case BLKIF_PROTOCOL_X86_64:
8987756SMark.Johnson@Sun.COM 		blk_ring_response_64((blkif_x86_64_response_t *)rsp, src);
8997756SMark.Johnson@Sun.COM 		break;
9007756SMark.Johnson@Sun.COM 	default:
9017756SMark.Johnson@Sun.COM 		cmn_err(CE_WARN, "blk@%s: unrecognised protocol: %d",
9027756SMark.Johnson@Sun.COM 		    ddi_get_name_addr(ring->ri_dip),
9037756SMark.Johnson@Sun.COM 		    ring->ri_protocol);
9047756SMark.Johnson@Sun.COM 	}
9057756SMark.Johnson@Sun.COM 
9067756SMark.Johnson@Sun.COM 	e = xvdi_ring_push_response(ring->ri_ring);
9077756SMark.Johnson@Sun.COM 	if (e != 0) {
9087756SMark.Johnson@Sun.COM 		xvdi_notify_oe(ring->ri_dip);
9097756SMark.Johnson@Sun.COM 	}
91010175SStuart.Maybee@Sun.COM 
91110175SStuart.Maybee@Sun.COM 	mutex_exit(&ring->ri_mutex);
9127756SMark.Johnson@Sun.COM }
9137756SMark.Johnson@Sun.COM 
9147756SMark.Johnson@Sun.COM 
9157756SMark.Johnson@Sun.COM /*
9167756SMark.Johnson@Sun.COM  * blk_ring_request_32()
9177756SMark.Johnson@Sun.COM  */
9187756SMark.Johnson@Sun.COM static void
blk_ring_request_32(blkif_request_t * dst,blkif_x86_32_request_t * src)9197756SMark.Johnson@Sun.COM blk_ring_request_32(blkif_request_t *dst, blkif_x86_32_request_t *src)
9207756SMark.Johnson@Sun.COM {
9217756SMark.Johnson@Sun.COM 	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
9227756SMark.Johnson@Sun.COM 	dst->operation = src->operation;
9237756SMark.Johnson@Sun.COM 	dst->nr_segments = src->nr_segments;
9247756SMark.Johnson@Sun.COM 	dst->handle = src->handle;
9257756SMark.Johnson@Sun.COM 	dst->id = src->id;
9267756SMark.Johnson@Sun.COM 	dst->sector_number = src->sector_number;
9277756SMark.Johnson@Sun.COM 	if (n > src->nr_segments)
9287756SMark.Johnson@Sun.COM 		n = src->nr_segments;
9297756SMark.Johnson@Sun.COM 	for (i = 0; i < n; i++)
9307756SMark.Johnson@Sun.COM 		dst->seg[i] = src->seg[i];
9317756SMark.Johnson@Sun.COM }
9327756SMark.Johnson@Sun.COM 
9337756SMark.Johnson@Sun.COM 
9347756SMark.Johnson@Sun.COM /*
9357756SMark.Johnson@Sun.COM  * blk_ring_request_64()
9367756SMark.Johnson@Sun.COM  */
9377756SMark.Johnson@Sun.COM static void
blk_ring_request_64(blkif_request_t * dst,blkif_x86_64_request_t * src)9387756SMark.Johnson@Sun.COM blk_ring_request_64(blkif_request_t *dst, blkif_x86_64_request_t *src)
9397756SMark.Johnson@Sun.COM {
9407756SMark.Johnson@Sun.COM 	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
9417756SMark.Johnson@Sun.COM 	dst->operation = src->operation;
9427756SMark.Johnson@Sun.COM 	dst->nr_segments = src->nr_segments;
9437756SMark.Johnson@Sun.COM 	dst->handle = src->handle;
9447756SMark.Johnson@Sun.COM 	dst->id = src->id;
9457756SMark.Johnson@Sun.COM 	dst->sector_number = src->sector_number;
9467756SMark.Johnson@Sun.COM 	if (n > src->nr_segments)
9477756SMark.Johnson@Sun.COM 		n = src->nr_segments;
9487756SMark.Johnson@Sun.COM 	for (i = 0; i < n; i++)
9497756SMark.Johnson@Sun.COM 		dst->seg[i] = src->seg[i];
9507756SMark.Johnson@Sun.COM }
9517756SMark.Johnson@Sun.COM 
9527756SMark.Johnson@Sun.COM 
9537756SMark.Johnson@Sun.COM /*
9547756SMark.Johnson@Sun.COM  * blk_ring_response_32()
9557756SMark.Johnson@Sun.COM  */
9567756SMark.Johnson@Sun.COM static void
blk_ring_response_32(blkif_x86_32_response_t * dst,blkif_response_t * src)9577756SMark.Johnson@Sun.COM blk_ring_response_32(blkif_x86_32_response_t *dst, blkif_response_t *src)
9587756SMark.Johnson@Sun.COM {
9597756SMark.Johnson@Sun.COM 	dst->id = src->id;
9607756SMark.Johnson@Sun.COM 	dst->operation = src->operation;
9617756SMark.Johnson@Sun.COM 	dst->status = src->status;
9627756SMark.Johnson@Sun.COM }
9637756SMark.Johnson@Sun.COM 
9647756SMark.Johnson@Sun.COM 
9657756SMark.Johnson@Sun.COM /*
9667756SMark.Johnson@Sun.COM  * blk_ring_response_64()
9677756SMark.Johnson@Sun.COM  */
9687756SMark.Johnson@Sun.COM static void
blk_ring_response_64(blkif_x86_64_response_t * dst,blkif_response_t * src)9697756SMark.Johnson@Sun.COM blk_ring_response_64(blkif_x86_64_response_t *dst, blkif_response_t *src)
9707756SMark.Johnson@Sun.COM {
9717756SMark.Johnson@Sun.COM 	dst->id = src->id;
9727756SMark.Johnson@Sun.COM 	dst->operation = src->operation;
9737756SMark.Johnson@Sun.COM 	dst->status = src->status;
9747756SMark.Johnson@Sun.COM }
9757756SMark.Johnson@Sun.COM 
9767756SMark.Johnson@Sun.COM 
9777756SMark.Johnson@Sun.COM /*
9787756SMark.Johnson@Sun.COM  * blk_ring_request_dump()
9797756SMark.Johnson@Sun.COM  */
9807756SMark.Johnson@Sun.COM void
blk_ring_request_dump(blkif_request_t * req)9817756SMark.Johnson@Sun.COM blk_ring_request_dump(blkif_request_t *req)
9827756SMark.Johnson@Sun.COM {
9837756SMark.Johnson@Sun.COM 	int i;
9847756SMark.Johnson@Sun.COM 
9857756SMark.Johnson@Sun.COM 	/*
9867756SMark.Johnson@Sun.COM 	 * Exploit the public interface definitions for BLKIF_OP_READ
9877756SMark.Johnson@Sun.COM 	 * etc..
9887756SMark.Johnson@Sun.COM 	 */
9897756SMark.Johnson@Sun.COM 	char *op_name[] = { "read", "write", "barrier", "flush" };
9907756SMark.Johnson@Sun.COM 
9917756SMark.Johnson@Sun.COM 	cmn_err(CE_NOTE, "   op=%s", op_name[req->operation]);
9927756SMark.Johnson@Sun.COM 	cmn_err(CE_NOTE, "   num of segments=%d", req->nr_segments);
9937756SMark.Johnson@Sun.COM 	cmn_err(CE_NOTE, "   handle=%d", req->handle);
9947756SMark.Johnson@Sun.COM 	cmn_err(CE_NOTE, "   id=0x%llx", (unsigned long long)req->id);
9957756SMark.Johnson@Sun.COM 	cmn_err(CE_NOTE, "   start sector=%llu",
9967756SMark.Johnson@Sun.COM 	    (unsigned long long)req->sector_number);
9977756SMark.Johnson@Sun.COM 	for (i = 0; i < req->nr_segments; i++) {
9987756SMark.Johnson@Sun.COM 		cmn_err(CE_NOTE, "   gref=%d, first sec=%d,"
9997756SMark.Johnson@Sun.COM 		    "last sec=%d", req->seg[i].gref, req->seg[i].first_sect,
10007756SMark.Johnson@Sun.COM 		    req->seg[i].last_sect);
10017756SMark.Johnson@Sun.COM 	}
10027756SMark.Johnson@Sun.COM }
10037756SMark.Johnson@Sun.COM 
10047756SMark.Johnson@Sun.COM 
10057756SMark.Johnson@Sun.COM /*
10067756SMark.Johnson@Sun.COM  * blk_ring_response_dump()
10077756SMark.Johnson@Sun.COM  */
10087756SMark.Johnson@Sun.COM void
blk_ring_response_dump(blkif_response_t * resp)10097756SMark.Johnson@Sun.COM blk_ring_response_dump(blkif_response_t *resp)
10107756SMark.Johnson@Sun.COM {
10117756SMark.Johnson@Sun.COM 	/*
10127756SMark.Johnson@Sun.COM 	 * Exploit the public interface definitions for BLKIF_OP_READ
10137756SMark.Johnson@Sun.COM 	 * etc..
10147756SMark.Johnson@Sun.COM 	 */
10157756SMark.Johnson@Sun.COM 	char *op_name[] = { "read", "write", "barrier", "flush" };
10167756SMark.Johnson@Sun.COM 
10177756SMark.Johnson@Sun.COM 	cmn_err(CE_NOTE, "   op=%d:%s", resp->operation,
10187756SMark.Johnson@Sun.COM 	    op_name[resp->operation]);
10197756SMark.Johnson@Sun.COM 	cmn_err(CE_NOTE, "   op=%d", resp->operation);
10207756SMark.Johnson@Sun.COM 	cmn_err(CE_NOTE, "   status=%d", resp->status);
10217756SMark.Johnson@Sun.COM }
1022