xref: /illumos-gate/usr/src/uts/common/xen/io/xdb.c (revision 93a18d6d401e844455263f926578e9d2aa6b47ec)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Note: This is the backend part of the split PV disk driver. This driver
29  * is not a nexus driver, nor is it a leaf driver(block/char/stream driver).
30  * Currently, it does not create any minor node. So, although, it runs in
31  * backend domain, it will not be used directly from within dom0.
32  * It simply gets block I/O requests issued by frontend from a shared page
33  * (blkif ring buffer - defined by Xen) between backend and frontend domain,
34  * generates a buf, and push it down to underlying disk target driver via
35  * ldi interface. When buf is done, this driver will generate a response
36  * and put it into ring buffer to inform frontend of the status of the I/O
37  * request issued by it. When a new virtual device entry is added in xenstore,
38  * there will be an watch event sent from Xen to xvdi framework, who will,
39  * in turn, create the devinfo node and try to attach this driver
40  * (see xvdi_create_dev). When frontend peer changes its state to
41  * XenbusStateClose, an event will also be sent from Xen to xvdi framework,
42  * who will detach and remove this devinfo node (see i_xvdi_oestate_handler).
43  * I/O requests get from ring buffer and event coming from xenstore cannot be
44  * trusted. We verify them in xdb_get_buf() and xdb_check_state_transition().
45  *
46  * Virtual device configuration is read/written from/to the database via
47  * xenbus_* interfaces. Driver also use xvdi_* to interact with hypervisor.
48  * There is an on-going effort to make xvdi_* cover all xenbus_*.
49  */
50 
51 #include <sys/types.h>
52 #include <sys/conf.h>
53 #include <sys/ddi.h>
54 #include <sys/dditypes.h>
55 #include <sys/sunddi.h>
56 #include <sys/list.h>
57 #include <sys/dkio.h>
58 #include <sys/cmlb.h>
59 #include <sys/vtoc.h>
60 #include <sys/modctl.h>
61 #include <sys/bootconf.h>
62 #include <sys/promif.h>
63 #include <sys/sysmacros.h>
64 #include <public/io/xenbus.h>
65 #include <public/io/xs_wire.h>
66 #include <xen/sys/xenbus_impl.h>
67 #include <xen/sys/xendev.h>
68 #include <sys/gnttab.h>
69 #include <sys/scsi/generic/inquiry.h>
70 #include <vm/seg_kmem.h>
71 #include <vm/hat_i86.h>
72 #include <sys/gnttab.h>
73 #include <sys/lofi.h>
74 #include <io/xdf.h>
75 #include <xen/io/blkif_impl.h>
76 #include <io/xdb.h>
77 
78 static xdb_t *xdb_statep;
79 static int xdb_debug = 0;
80 
81 static void xdb_close(dev_info_t *);
82 static int xdb_push_response(xdb_t *, uint64_t, uint8_t, uint16_t);
83 static int xdb_get_request(xdb_t *, blkif_request_t *);
84 static void blkif_get_x86_32_req(blkif_request_t *, blkif_x86_32_request_t *);
85 static void blkif_get_x86_64_req(blkif_request_t *, blkif_x86_64_request_t *);
86 static int xdb_biodone(buf_t *);
87 
88 
89 #ifdef DEBUG
90 /*
91  * debug aid functions
92  */
93 
94 static void
95 logva(xdb_t *vdp, uint64_t va)
96 {
97 	uint64_t *page_addrs;
98 	int i;
99 
100 	page_addrs = vdp->page_addrs;
101 	for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) {
102 		if (page_addrs[i] == va)
103 			debug_enter("VA remapping found!");
104 	}
105 
106 	for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) {
107 		if (page_addrs[i] == 0) {
108 			page_addrs[i] = va;
109 			break;
110 		}
111 	}
112 	ASSERT(i < XDB_MAX_IO_PAGES(vdp));
113 }
114 
115 static void
116 unlogva(xdb_t *vdp, uint64_t va)
117 {
118 	uint64_t *page_addrs;
119 	int i;
120 
121 	page_addrs = vdp->page_addrs;
122 	for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) {
123 		if (page_addrs[i] == va) {
124 			page_addrs[i] = 0;
125 			break;
126 		}
127 	}
128 	ASSERT(i < XDB_MAX_IO_PAGES(vdp));
129 }
130 
131 static void
132 xdb_dump_request_oe(blkif_request_t *req)
133 {
134 	int i;
135 
136 	/*
137 	 * Exploit the public interface definitions for BLKIF_OP_READ
138 	 * etc..
139 	 */
140 	char *op_name[] = { "read", "write", "barrier", "flush" };
141 
142 	XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "op=%s", op_name[req->operation]));
143 	XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "num of segments=%d",
144 	    req->nr_segments));
145 	XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "handle=%d", req->handle));
146 	XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "id=%llu",
147 	    (unsigned long long)req->id));
148 	XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "start sector=%llu",
149 	    (unsigned long long)req->sector_number));
150 	for (i = 0; i < req->nr_segments; i++) {
151 		XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "gref=%d, first sec=%d,"
152 		    "last sec=%d", req->seg[i].gref, req->seg[i].first_sect,
153 		    req->seg[i].last_sect));
154 	}
155 }
156 #endif /* DEBUG */
157 
158 /*
159  * Statistics.
160  */
161 static char *xdb_stats[] = {
162 	"rd_reqs",
163 	"wr_reqs",
164 	"br_reqs",
165 	"fl_reqs",
166 	"oo_reqs"
167 };
168 
169 static int
170 xdb_kstat_update(kstat_t *ksp, int flag)
171 {
172 	xdb_t *vdp;
173 	kstat_named_t *knp;
174 
175 	if (flag != KSTAT_READ)
176 		return (EACCES);
177 
178 	vdp = ksp->ks_private;
179 	knp = ksp->ks_data;
180 
181 	/*
182 	 * Assignment order should match that of the names in
183 	 * xdb_stats.
184 	 */
185 	(knp++)->value.ui64 = vdp->xs_stat_req_reads;
186 	(knp++)->value.ui64 = vdp->xs_stat_req_writes;
187 	(knp++)->value.ui64 = vdp->xs_stat_req_barriers;
188 	(knp++)->value.ui64 = vdp->xs_stat_req_flushes;
189 	(knp++)->value.ui64 = 0; /* oo_req */
190 
191 	return (0);
192 }
193 
194 static boolean_t
195 xdb_kstat_init(xdb_t *vdp)
196 {
197 	int nstat = sizeof (xdb_stats) / sizeof (xdb_stats[0]);
198 	char **cp = xdb_stats;
199 	kstat_named_t *knp;
200 
201 	if ((vdp->xs_kstats = kstat_create("xdb",
202 	    ddi_get_instance(vdp->xs_dip),
203 	    "req_statistics", "block", KSTAT_TYPE_NAMED,
204 	    nstat, 0)) == NULL)
205 		return (B_FALSE);
206 
207 	vdp->xs_kstats->ks_private = vdp;
208 	vdp->xs_kstats->ks_update = xdb_kstat_update;
209 
210 	knp = vdp->xs_kstats->ks_data;
211 	while (nstat > 0) {
212 		kstat_named_init(knp, *cp, KSTAT_DATA_UINT64);
213 		knp++;
214 		cp++;
215 		nstat--;
216 	}
217 
218 	kstat_install(vdp->xs_kstats);
219 
220 	return (B_TRUE);
221 }
222 
223 static char *
224 i_pathname(dev_info_t *dip)
225 {
226 	char *path, *rv;
227 
228 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
229 	(void) ddi_pathname(dip, path);
230 	rv = strdup(path);
231 	kmem_free(path, MAXPATHLEN);
232 
233 	return (rv);
234 }
235 
236 static buf_t *
237 xdb_get_buf(xdb_t *vdp, blkif_request_t *req, xdb_request_t *xreq)
238 {
239 	buf_t *bp;
240 	uint8_t segs, curseg;
241 	int sectors;
242 	int i, err;
243 	gnttab_map_grant_ref_t mapops[BLKIF_MAX_SEGMENTS_PER_REQUEST];
244 	ddi_acc_handle_t acchdl;
245 
246 	acchdl = vdp->xs_ring_hdl;
247 	bp = XDB_XREQ2BP(xreq);
248 	curseg = xreq->xr_curseg;
249 	/* init a new xdb request */
250 	if (req != NULL) {
251 		ASSERT(MUTEX_HELD(&vdp->xs_iomutex));
252 		boolean_t pagemapok = B_TRUE;
253 		uint8_t op = ddi_get8(acchdl, &req->operation);
254 
255 		xreq->xr_vdp = vdp;
256 		xreq->xr_op = op;
257 		xreq->xr_id = ddi_get64(acchdl, &req->id);
258 		segs = xreq->xr_buf_pages = ddi_get8(acchdl, &req->nr_segments);
259 		if (segs == 0) {
260 			if (op != BLKIF_OP_FLUSH_DISKCACHE)
261 				cmn_err(CE_WARN, "!non-BLKIF_OP_FLUSH_DISKCACHE"
262 				    " is seen from domain %d with zero "
263 				    "length data buffer!", vdp->xs_peer);
264 			bioinit(bp);
265 			bp->b_bcount = 0;
266 			bp->b_lblkno = 0;
267 			bp->b_un.b_addr = NULL;
268 			return (bp);
269 		} else if (op == BLKIF_OP_FLUSH_DISKCACHE) {
270 			cmn_err(CE_WARN, "!BLKIF_OP_FLUSH_DISKCACHE"
271 			    " is seen from domain %d with non-zero "
272 			    "length data buffer!", vdp->xs_peer);
273 		}
274 
275 		/*
276 		 * segs should be no bigger than BLKIF_MAX_SEGMENTS_PER_REQUEST
277 		 * according to the definition of blk interface by Xen
278 		 * we do sanity check here
279 		 */
280 		if (segs > BLKIF_MAX_SEGMENTS_PER_REQUEST)
281 			segs = xreq->xr_buf_pages =
282 			    BLKIF_MAX_SEGMENTS_PER_REQUEST;
283 
284 		for (i = 0; i < segs; i++) {
285 			uint8_t fs, ls;
286 
287 			mapops[i].host_addr =
288 			    (uint64_t)(uintptr_t)XDB_IOPAGE_VA(
289 			    vdp->xs_iopage_va, xreq->xr_idx, i);
290 			mapops[i].dom = vdp->xs_peer;
291 			mapops[i].ref = ddi_get32(acchdl, &req->seg[i].gref);
292 			mapops[i].flags = GNTMAP_host_map;
293 			if (op != BLKIF_OP_READ)
294 				mapops[i].flags |= GNTMAP_readonly;
295 
296 			fs = ddi_get8(acchdl, &req->seg[i].first_sect);
297 			ls = ddi_get8(acchdl, &req->seg[i].last_sect);
298 
299 			/*
300 			 * first_sect should be no bigger than last_sect and
301 			 * both of them should be no bigger than
302 			 * XB_LAST_SECTOR_IN_SEG according to definition
303 			 * of blk interface by Xen, so sanity check again
304 			 */
305 			if (fs > XB_LAST_SECTOR_IN_SEG)
306 				fs = XB_LAST_SECTOR_IN_SEG;
307 			if (ls > XB_LAST_SECTOR_IN_SEG)
308 				ls = XB_LAST_SECTOR_IN_SEG;
309 			if (fs > ls)
310 				fs = ls;
311 
312 			xreq->xr_segs[i].fs = fs;
313 			xreq->xr_segs[i].ls = ls;
314 		}
315 
316 		/* map in io pages */
317 		err = xen_map_gref(GNTTABOP_map_grant_ref, mapops, i, B_FALSE);
318 		if (err != 0)
319 			return (NULL);
320 		for (i = 0; i < segs; i++) {
321 			/*
322 			 * Although HYPERVISOR_grant_table_op() returned no
323 			 * error, mapping of each single page can fail. So,
324 			 * we have to do the check here and handle the error
325 			 * if needed
326 			 */
327 			if (mapops[i].status != GNTST_okay) {
328 				int j;
329 				for (j = 0; j < i; j++) {
330 #ifdef DEBUG
331 					unlogva(vdp, mapops[j].host_addr);
332 #endif
333 					xen_release_pfn(
334 					    xreq->xr_plist[j].p_pagenum);
335 				}
336 				pagemapok = B_FALSE;
337 				break;
338 			}
339 			/* record page mapping handle for unmapping later */
340 			xreq->xr_page_hdls[i] = mapops[i].handle;
341 #ifdef DEBUG
342 			logva(vdp, mapops[i].host_addr);
343 #endif
344 			/*
345 			 * Pass the MFNs down using the shadow list (xr_pplist)
346 			 *
347 			 * This is pretty ugly since we have implict knowledge
348 			 * of how the rootnex binds buffers.
349 			 * The GNTTABOP_map_grant_ref op makes us do some ugly
350 			 * stuff since we're not allowed to touch these PTEs
351 			 * from the VM.
352 			 *
353 			 * Obviously, these aren't real page_t's. The rootnex
354 			 * only needs p_pagenum.
355 			 * Also, don't use btop() here or 32 bit PAE breaks.
356 			 */
357 			xreq->xr_pplist[i] = &xreq->xr_plist[i];
358 			xreq->xr_plist[i].p_pagenum =
359 			    xen_assign_pfn(mapops[i].dev_bus_addr >> PAGESHIFT);
360 		}
361 
362 		/*
363 		 * not all pages mapped in successfully, unmap those mapped-in
364 		 * page and return failure
365 		 */
366 		if (!pagemapok) {
367 			gnttab_unmap_grant_ref_t unmapop;
368 
369 			for (i = 0; i < segs; i++) {
370 				if (mapops[i].status != GNTST_okay)
371 					continue;
372 				unmapop.host_addr =
373 				    (uint64_t)(uintptr_t)XDB_IOPAGE_VA(
374 				    vdp->xs_iopage_va, xreq->xr_idx, i);
375 				unmapop.dev_bus_addr = NULL;
376 				unmapop.handle = mapops[i].handle;
377 				(void) HYPERVISOR_grant_table_op(
378 				    GNTTABOP_unmap_grant_ref, &unmapop, 1);
379 			}
380 
381 			return (NULL);
382 		}
383 		bioinit(bp);
384 		bp->b_lblkno = ddi_get64(acchdl, &req->sector_number);
385 		bp->b_flags = B_BUSY | B_SHADOW | B_PHYS;
386 		bp->b_flags |= (ddi_get8(acchdl, &req->operation) ==
387 		    BLKIF_OP_READ) ? B_READ : (B_WRITE | B_ASYNC);
388 	} else {
389 		uint64_t blkst;
390 		int isread;
391 
392 		/* reuse this buf */
393 		blkst = bp->b_lblkno + bp->b_bcount / DEV_BSIZE;
394 		isread = bp->b_flags & B_READ;
395 		bioreset(bp);
396 		bp->b_lblkno = blkst;
397 		bp->b_flags = B_BUSY | B_SHADOW | B_PHYS;
398 		bp->b_flags |= isread ? B_READ : (B_WRITE | B_ASYNC);
399 		XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "reuse buf, xreq is %d!!",
400 		    xreq->xr_idx));
401 	}
402 
403 	/* form a buf */
404 	bp->b_un.b_addr = XDB_IOPAGE_VA(vdp->xs_iopage_va, xreq->xr_idx,
405 	    curseg) + xreq->xr_segs[curseg].fs * DEV_BSIZE;
406 	bp->b_shadow = &xreq->xr_pplist[curseg];
407 	bp->b_iodone = xdb_biodone;
408 	sectors = 0;
409 
410 	/*
411 	 * Run through the segments. There are XB_NUM_SECTORS_PER_SEG sectors
412 	 * per segment. On some OSes (e.g. Linux), there may be empty gaps
413 	 * between segments. (i.e. the first segment may end on sector 6 and
414 	 * the second segment start on sector 4).
415 	 *
416 	 * if a segments first sector is not set to 0, and this is not the
417 	 * first segment in our buf, end this buf now.
418 	 *
419 	 * if a segments last sector is not set to XB_LAST_SECTOR_IN_SEG, and
420 	 * this is not the last segment in the request, add this segment into
421 	 * the buf, then end this buf (updating the pointer to point to the
422 	 * next segment next time around).
423 	 */
424 	for (i = curseg; i < xreq->xr_buf_pages; i++) {
425 		if ((xreq->xr_segs[i].fs != 0) && (i != curseg)) {
426 			break;
427 		}
428 		sectors += (xreq->xr_segs[i].ls - xreq->xr_segs[i].fs + 1);
429 		if ((xreq->xr_segs[i].ls != XB_LAST_SECTOR_IN_SEG) &&
430 		    (i != (xreq->xr_buf_pages - 1))) {
431 			i++;
432 			break;
433 		}
434 	}
435 	xreq->xr_curseg = i;
436 	bp->b_bcount = sectors * DEV_BSIZE;
437 	bp->b_bufsize = bp->b_bcount;
438 
439 	return (bp);
440 }
441 
442 static xdb_request_t *
443 xdb_get_req(xdb_t *vdp)
444 {
445 	xdb_request_t *req;
446 	int idx;
447 
448 	ASSERT(MUTEX_HELD(&vdp->xs_iomutex));
449 	ASSERT(vdp->xs_free_req != -1);
450 	req = &vdp->xs_req[vdp->xs_free_req];
451 	vdp->xs_free_req = req->xr_next;
452 	idx = req->xr_idx;
453 	bzero(req, sizeof (xdb_request_t));
454 	req->xr_idx = idx;
455 	return (req);
456 }
457 
458 static void
459 xdb_free_req(xdb_request_t *req)
460 {
461 	xdb_t *vdp = req->xr_vdp;
462 
463 	ASSERT(MUTEX_HELD(&vdp->xs_iomutex));
464 	req->xr_next = vdp->xs_free_req;
465 	vdp->xs_free_req = req->xr_idx;
466 }
467 
468 static void
469 xdb_response(xdb_t *vdp, blkif_request_t *req, boolean_t ok)
470 {
471 	ddi_acc_handle_t acchdl = vdp->xs_ring_hdl;
472 
473 	if (xdb_push_response(vdp, ddi_get64(acchdl, &req->id),
474 	    ddi_get8(acchdl, &req->operation), ok))
475 		xvdi_notify_oe(vdp->xs_dip);
476 }
477 
478 static void
479 xdb_init_ioreqs(xdb_t *vdp)
480 {
481 	int i;
482 
483 	ASSERT(vdp->xs_nentry);
484 
485 	if (vdp->xs_req == NULL)
486 		vdp->xs_req = kmem_alloc(vdp->xs_nentry *
487 		    sizeof (xdb_request_t), KM_SLEEP);
488 #ifdef DEBUG
489 	if (vdp->page_addrs == NULL)
490 		vdp->page_addrs = kmem_zalloc(XDB_MAX_IO_PAGES(vdp) *
491 		    sizeof (uint64_t), KM_SLEEP);
492 #endif
493 	for (i = 0; i < vdp->xs_nentry; i++) {
494 		vdp->xs_req[i].xr_idx = i;
495 		vdp->xs_req[i].xr_next = i + 1;
496 	}
497 	vdp->xs_req[vdp->xs_nentry - 1].xr_next = -1;
498 	vdp->xs_free_req = 0;
499 
500 	/* alloc va in host dom for io page mapping */
501 	vdp->xs_iopage_va = vmem_xalloc(heap_arena,
502 	    XDB_MAX_IO_PAGES(vdp) * PAGESIZE, PAGESIZE, 0, 0, 0, 0,
503 	    VM_SLEEP);
504 	for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++)
505 		hat_prepare_mapping(kas.a_hat,
506 		    vdp->xs_iopage_va + i * PAGESIZE, NULL);
507 }
508 
509 static void
510 xdb_uninit_ioreqs(xdb_t *vdp)
511 {
512 	int i;
513 
514 	for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++)
515 		hat_release_mapping(kas.a_hat,
516 		    vdp->xs_iopage_va + i * PAGESIZE);
517 	vmem_xfree(heap_arena, vdp->xs_iopage_va,
518 	    XDB_MAX_IO_PAGES(vdp) * PAGESIZE);
519 	if (vdp->xs_req != NULL) {
520 		kmem_free(vdp->xs_req, vdp->xs_nentry * sizeof (xdb_request_t));
521 		vdp->xs_req = NULL;
522 	}
523 #ifdef DEBUG
524 	if (vdp->page_addrs != NULL) {
525 		kmem_free(vdp->page_addrs, XDB_MAX_IO_PAGES(vdp) *
526 		    sizeof (uint64_t));
527 		vdp->page_addrs = NULL;
528 	}
529 #endif
530 }
531 
532 static uint_t
533 xdb_intr(caddr_t arg)
534 {
535 	xdb_t		*vdp = (xdb_t *)arg;
536 	dev_info_t	*dip = vdp->xs_dip;
537 	blkif_request_t	req, *reqp = &req;
538 	xdb_request_t	*xreq;
539 	buf_t		*bp;
540 	uint8_t		op;
541 	int		ret = DDI_INTR_UNCLAIMED;
542 
543 	XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE,
544 	    "xdb@%s: I/O request received from dom %d",
545 	    ddi_get_name_addr(dip), vdp->xs_peer));
546 
547 	mutex_enter(&vdp->xs_iomutex);
548 
549 	/* shouldn't touch ring buffer if not in connected state */
550 	if (!vdp->xs_if_connected) {
551 		mutex_exit(&vdp->xs_iomutex);
552 		return (DDI_INTR_UNCLAIMED);
553 	}
554 	ASSERT(vdp->xs_hp_connected && vdp->xs_fe_initialised);
555 
556 	/*
557 	 * We'll loop till there is no more request in the ring
558 	 * We won't stuck in this loop for ever since the size of ring buffer
559 	 * is limited, and frontend will stop pushing requests into it when
560 	 * the ring buffer is full
561 	 */
562 
563 	/* req_event will be increased in xvdi_ring_get_request() */
564 	while (xdb_get_request(vdp, reqp)) {
565 		ret = DDI_INTR_CLAIMED;
566 
567 		op = ddi_get8(vdp->xs_ring_hdl, &reqp->operation);
568 		if (op == BLKIF_OP_READ			||
569 		    op == BLKIF_OP_WRITE		||
570 		    op == BLKIF_OP_WRITE_BARRIER	||
571 		    op == BLKIF_OP_FLUSH_DISKCACHE) {
572 #ifdef DEBUG
573 			xdb_dump_request_oe(reqp);
574 #endif
575 			xreq = xdb_get_req(vdp);
576 			ASSERT(xreq);
577 			switch (op) {
578 			case BLKIF_OP_READ:
579 				vdp->xs_stat_req_reads++;
580 				break;
581 			case BLKIF_OP_WRITE_BARRIER:
582 				vdp->xs_stat_req_barriers++;
583 				/* FALLTHRU */
584 			case BLKIF_OP_WRITE:
585 				vdp->xs_stat_req_writes++;
586 				break;
587 			case BLKIF_OP_FLUSH_DISKCACHE:
588 				vdp->xs_stat_req_flushes++;
589 				break;
590 			}
591 
592 			xreq->xr_curseg = 0; /* start from first segment */
593 			bp = xdb_get_buf(vdp, reqp, xreq);
594 			if (bp == NULL) {
595 				/* failed to form a buf */
596 				xdb_free_req(xreq);
597 				xdb_response(vdp, reqp, B_FALSE);
598 				continue;
599 			}
600 			bp->av_forw = NULL;
601 
602 			XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE,
603 			    " buf %p, blkno %lld, size %lu, addr %p",
604 			    (void *)bp, (longlong_t)bp->b_blkno,
605 			    (ulong_t)bp->b_bcount, (void *)bp->b_un.b_addr));
606 
607 			/* send bp to underlying blk driver */
608 			if (vdp->xs_f_iobuf == NULL) {
609 				vdp->xs_f_iobuf = vdp->xs_l_iobuf = bp;
610 			} else {
611 				vdp->xs_l_iobuf->av_forw = bp;
612 				vdp->xs_l_iobuf = bp;
613 			}
614 		} else {
615 			xdb_response(vdp, reqp, B_FALSE);
616 			XDB_DBPRINT(XDB_DBG_IO, (CE_WARN, "xdb@%s: "
617 			    "Unsupported cmd received from dom %d",
618 			    ddi_get_name_addr(dip), vdp->xs_peer));
619 		}
620 	}
621 	/* notify our taskq to push buf to underlying blk driver */
622 	if (ret == DDI_INTR_CLAIMED)
623 		cv_broadcast(&vdp->xs_iocv);
624 
625 	mutex_exit(&vdp->xs_iomutex);
626 
627 	return (ret);
628 }
629 
630 static int
631 xdb_biodone(buf_t *bp)
632 {
633 	int i, err, bioerr;
634 	uint8_t segs;
635 	gnttab_unmap_grant_ref_t unmapops[BLKIF_MAX_SEGMENTS_PER_REQUEST];
636 	xdb_request_t *xreq = XDB_BP2XREQ(bp);
637 	xdb_t *vdp = xreq->xr_vdp;
638 	buf_t *nbp;
639 
640 	bioerr = geterror(bp);
641 	if (bioerr)
642 		XDB_DBPRINT(XDB_DBG_IO, (CE_WARN, "xdb@%s: I/O error %d",
643 		    ddi_get_name_addr(vdp->xs_dip), bioerr));
644 
645 	/* check if we are done w/ this I/O request */
646 	if ((bioerr == 0) && (xreq->xr_curseg < xreq->xr_buf_pages)) {
647 		nbp = xdb_get_buf(vdp, NULL, xreq);
648 		if (nbp) {
649 			err = ldi_strategy(vdp->xs_ldi_hdl, nbp);
650 			if (err == 0) {
651 				XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE,
652 				    "sent buf to backend ok"));
653 				return (DDI_SUCCESS);
654 			}
655 			bioerr = EIO;
656 			XDB_DBPRINT(XDB_DBG_IO, (CE_WARN, "xdb@%s: "
657 			    "sent buf to backend dev failed, err=%d",
658 			    ddi_get_name_addr(vdp->xs_dip), err));
659 		} else {
660 			bioerr = EIO;
661 		}
662 	}
663 
664 	/* unmap io pages */
665 	segs = xreq->xr_buf_pages;
666 	/*
667 	 * segs should be no bigger than BLKIF_MAX_SEGMENTS_PER_REQUEST
668 	 * according to the definition of blk interface by Xen
669 	 */
670 	ASSERT(segs <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
671 	for (i = 0; i < segs; i++) {
672 		unmapops[i].host_addr = (uint64_t)(uintptr_t)XDB_IOPAGE_VA(
673 		    vdp->xs_iopage_va, xreq->xr_idx, i);
674 #ifdef DEBUG
675 		mutex_enter(&vdp->xs_iomutex);
676 		unlogva(vdp, unmapops[i].host_addr);
677 		mutex_exit(&vdp->xs_iomutex);
678 #endif
679 		unmapops[i].dev_bus_addr = NULL;
680 		unmapops[i].handle = xreq->xr_page_hdls[i];
681 	}
682 	err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
683 	    unmapops, segs);
684 	ASSERT(!err);
685 
686 	/*
687 	 * If we have reached a barrier write or a cache flush , then we must
688 	 * flush all our I/Os.
689 	 */
690 	if (xreq->xr_op == BLKIF_OP_WRITE_BARRIER ||
691 	    xreq->xr_op == BLKIF_OP_FLUSH_DISKCACHE) {
692 		/*
693 		 * XXX At this point the write did succeed, so I don't
694 		 * believe we should report an error because the flush
695 		 * failed. However, this is a debatable point, so
696 		 * maybe we need to think more carefully about this.
697 		 * For now, just cast to void.
698 		 */
699 		(void) ldi_ioctl(vdp->xs_ldi_hdl,
700 		    DKIOCFLUSHWRITECACHE, NULL, FKIOCTL, kcred, NULL);
701 	}
702 
703 	mutex_enter(&vdp->xs_iomutex);
704 
705 	/* send response back to frontend */
706 	if (vdp->xs_if_connected) {
707 		ASSERT(vdp->xs_hp_connected && vdp->xs_fe_initialised);
708 		if (xdb_push_response(vdp, xreq->xr_id, xreq->xr_op, bioerr))
709 			xvdi_notify_oe(vdp->xs_dip);
710 		XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE,
711 		    "sent resp back to frontend, id=%llu",
712 		    (unsigned long long)xreq->xr_id));
713 	}
714 	/* free io resources */
715 	biofini(bp);
716 	xdb_free_req(xreq);
717 
718 	vdp->xs_ionum--;
719 	if (!vdp->xs_if_connected && (vdp->xs_ionum == 0)) {
720 		/* we're closing, someone is waiting for I/O clean-up */
721 		cv_signal(&vdp->xs_ionumcv);
722 	}
723 
724 	mutex_exit(&vdp->xs_iomutex);
725 
726 	return (DDI_SUCCESS);
727 }
728 
729 static int
730 xdb_bindto_frontend(xdb_t *vdp)
731 {
732 	int err;
733 	char *oename;
734 	grant_ref_t gref;
735 	evtchn_port_t evtchn;
736 	dev_info_t *dip = vdp->xs_dip;
737 	char protocol[64] = "";
738 
739 	ASSERT(MUTEX_HELD(&vdp->xs_cbmutex));
740 
741 	/*
742 	 * Switch to the XenbusStateInitialised state.  This let's the
743 	 * frontend know that we're about to negotiate a connection.
744 	 */
745 	(void) xvdi_switch_state(dip, XBT_NULL, XenbusStateInitialised);
746 
747 	/*
748 	 * Gather info from frontend
749 	 */
750 	oename = xvdi_get_oename(dip);
751 	if (oename == NULL)
752 		return (DDI_FAILURE);
753 
754 	err = xenbus_gather(XBT_NULL, oename,
755 	    XBP_RING_REF, "%lu", &gref,
756 	    XBP_EVENT_CHAN, "%u", &evtchn,
757 	    NULL);
758 	if (err != 0) {
759 		xvdi_dev_error(dip, err,
760 		    "Getting ring-ref and evtchn from frontend");
761 		return (DDI_FAILURE);
762 	}
763 
764 	vdp->xs_blk_protocol = BLKIF_PROTOCOL_NATIVE;
765 	vdp->xs_nentry = BLKIF_RING_SIZE;
766 	vdp->xs_entrysize = sizeof (union blkif_sring_entry);
767 
768 	err = xenbus_gather(XBT_NULL, oename,
769 	    XBP_PROTOCOL, "%63s", protocol, NULL);
770 	if (err)
771 		(void) strcpy(protocol, "unspecified, assuming native");
772 	else {
773 		/*
774 		 * We must check for NATIVE first, so that the fast path
775 		 * is taken for copying data from the guest to the host.
776 		 */
777 		if (strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE) != 0) {
778 			if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) {
779 				vdp->xs_blk_protocol = BLKIF_PROTOCOL_X86_32;
780 				vdp->xs_nentry = BLKIF_X86_32_RING_SIZE;
781 				vdp->xs_entrysize =
782 				    sizeof (union blkif_x86_32_sring_entry);
783 			} else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_64) ==
784 			    0) {
785 				vdp->xs_blk_protocol = BLKIF_PROTOCOL_X86_64;
786 				vdp->xs_nentry = BLKIF_X86_64_RING_SIZE;
787 				vdp->xs_entrysize =
788 				    sizeof (union blkif_x86_64_sring_entry);
789 			} else {
790 				xvdi_fatal_error(dip, err, "unknown protocol");
791 				return (DDI_FAILURE);
792 			}
793 		}
794 	}
795 #ifdef DEBUG
796 	cmn_err(CE_NOTE, "!xdb@%s: blkif protocol '%s' ",
797 	    ddi_get_name_addr(dip), protocol);
798 #endif
799 
800 	/*
801 	 * Map and init ring.  The ring parameters must match those which
802 	 * have been allocated in the front end.
803 	 */
804 	if (xvdi_map_ring(dip, vdp->xs_nentry, vdp->xs_entrysize,
805 	    gref, &vdp->xs_ring) != DDI_SUCCESS)
806 		return (DDI_FAILURE);
807 
808 	/*
809 	 * This will be removed after we use shadow I/O ring request since
810 	 * we don't need to access the ring itself directly, thus the access
811 	 * handle is not needed
812 	 */
813 	vdp->xs_ring_hdl = vdp->xs_ring->xr_acc_hdl;
814 
815 	/* bind event channel */
816 	err = xvdi_bind_evtchn(dip, evtchn);
817 	if (err != DDI_SUCCESS) {
818 		xvdi_unmap_ring(vdp->xs_ring);
819 		return (DDI_FAILURE);
820 	}
821 
822 	return (DDI_SUCCESS);
823 }
824 
825 static void
826 xdb_unbindfrom_frontend(xdb_t *vdp)
827 {
828 	ASSERT(MUTEX_HELD(&vdp->xs_cbmutex));
829 
830 	xvdi_free_evtchn(vdp->xs_dip);
831 	xvdi_unmap_ring(vdp->xs_ring);
832 }
833 
834 /*
835  * xdb_params_change() initiates a allows change to the underlying device/file
836  * that the backend is accessing.  It does this by disconnecting from the
837  * frontend, closing the old device, clearing a bunch of xenbus parameters,
838  * and switching back to the XenbusStateInitialising state.  The frontend
839  * should notice this transition to the XenbusStateInitialising state and
840  * should attempt to reconnect to us (the backend).
841  */
842 static void
843 xdb_params_change(xdb_t *vdp, char *params, boolean_t update_xs)
844 {
845 	xenbus_transaction_t	xbt;
846 	dev_info_t		*dip = vdp->xs_dip;
847 	char			*xsname;
848 	int			err;
849 
850 	ASSERT(MUTEX_HELD(&vdp->xs_cbmutex));
851 	ASSERT(vdp->xs_params_path != NULL);
852 
853 	if ((xsname = xvdi_get_xsname(dip)) == NULL)
854 		return;
855 	if (strcmp(vdp->xs_params_path, params) == 0)
856 		return;
857 
858 	/*
859 	 * Close the device we're currently accessing and update the
860 	 * path which points to our backend device/file.
861 	 */
862 	xdb_close(dip);
863 	vdp->xs_fe_initialised = B_FALSE;
864 
865 trans_retry:
866 	if ((err = xenbus_transaction_start(&xbt)) != 0) {
867 		xvdi_dev_error(dip, err, "params change transaction init");
868 		goto errout;
869 	}
870 
871 	/*
872 	 * Delete all the xenbus properties that are connection dependant
873 	 * and go back to the initializing state so that the frontend
874 	 * driver can re-negotiate a connection.
875 	 */
876 	if (((err = xenbus_rm(xbt, xsname, XBP_FB)) != 0) ||
877 	    ((err = xenbus_rm(xbt, xsname, XBP_INFO)) != 0) ||
878 	    ((err = xenbus_rm(xbt, xsname, "sector-size")) != 0) ||
879 	    ((err = xenbus_rm(xbt, xsname, XBP_SECTORS)) != 0) ||
880 	    ((err = xenbus_rm(xbt, xsname, "instance")) != 0) ||
881 	    ((err = xenbus_rm(xbt, xsname, "node")) != 0) ||
882 	    (update_xs && ((err = xenbus_printf(xbt, xsname,
883 	    "params", "%s", params)) != 0)) ||
884 	    ((err = xvdi_switch_state(dip,
885 	    xbt, XenbusStateInitialising) > 0))) {
886 		(void) xenbus_transaction_end(xbt, 1);
887 		xvdi_dev_error(dip, err, "params change transaction setup");
888 		goto errout;
889 	}
890 
891 	if ((err = xenbus_transaction_end(xbt, 0)) != 0) {
892 		if (err == EAGAIN) {
893 			/* transaction is ended, don't need to abort it */
894 			goto trans_retry;
895 		}
896 		xvdi_dev_error(dip, err, "params change transaction commit");
897 		goto errout;
898 	}
899 
900 	/* Change the device that we plan to access */
901 	strfree(vdp->xs_params_path);
902 	vdp->xs_params_path = strdup(params);
903 	return;
904 
905 errout:
906 	(void) xvdi_switch_state(dip, xbt, XenbusStateInitialising);
907 }
908 
909 /*
910  * xdb_watch_params_cb() - This callback is invoked whenever there
911  * is an update to the following xenbus parameter:
912  *     /local/domain/0/backend/vbd/<domU_id>/<domU_dev>/params
913  *
914  * This normally happens during xm block-configure operations, which
915  * are used to change CD device images for HVM domUs.
916  */
917 /*ARGSUSED*/
918 static void
919 xdb_watch_params_cb(dev_info_t *dip, const char *path, void *arg)
920 {
921 	xdb_t			*vdp = (xdb_t *)ddi_get_driver_private(dip);
922 	char			*xsname, *oename, *str, *str2;
923 
924 	if (((xsname = xvdi_get_xsname(dip)) == NULL) ||
925 	    ((oename = xvdi_get_oename(dip)) == NULL)) {
926 		return;
927 	}
928 
929 	mutex_enter(&vdp->xs_cbmutex);
930 
931 	if (xenbus_read_str(xsname, "params", &str) != 0) {
932 		mutex_exit(&vdp->xs_cbmutex);
933 		return;
934 	}
935 
936 	if (strcmp(vdp->xs_params_path, str) == 0) {
937 		/* Nothing todo */
938 		mutex_exit(&vdp->xs_cbmutex);
939 		strfree(str);
940 		return;
941 	}
942 
943 	/*
944 	 * If the frontend isn't a cd device, doesn't support media
945 	 * requests, or has locked the media, then we can't change
946 	 * the params value.  restore the current value.
947 	 */
948 	str2 = NULL;
949 	if (!XDB_IS_FE_CD(vdp) ||
950 	    (xenbus_read_str(oename, XBP_MEDIA_REQ, &str2) != 0) ||
951 	    (strcmp(str2, XBV_MEDIA_REQ_LOCK) == 0)) {
952 		if (str2 != NULL)
953 			strfree(str2);
954 		strfree(str);
955 
956 		str = i_pathname(dip);
957 		cmn_err(CE_NOTE,
958 		    "!%s: media locked, ignoring params update", str);
959 		strfree(str);
960 
961 		mutex_exit(&vdp->xs_cbmutex);
962 		return;
963 	}
964 
965 	XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE,
966 	    "block-configure params request: \"%s\"", str));
967 
968 	xdb_params_change(vdp, str, B_FALSE);
969 	mutex_exit(&vdp->xs_cbmutex);
970 	strfree(str);
971 }
972 
973 /*
974  * xdb_watch_media_req_cb() - This callback is invoked whenever there
975  * is an update to the following xenbus parameter:
976  *     /local/domain/<domU_id>/device/vbd/<domU_dev>/media-req
977  *
978  * Media requests are only supported on CD devices and are issued by
979  * the frontend.  Currently the only supported media request operaions
980  * are "lock" and "eject".  A "lock" prevents the backend from changing
981  * the backing device/file (via xm block-configure).  An "eject" requests
982  * tells the backend device that it should disconnect from the frontend
983  * and closing the backing device/file that is currently in use.
984  */
985 /*ARGSUSED*/
986 static void
987 xdb_watch_media_req_cb(dev_info_t *dip, const char *path, void *arg)
988 {
989 	xdb_t			*vdp = (xdb_t *)ddi_get_driver_private(dip);
990 	char			*oename, *str;
991 
992 	mutex_enter(&vdp->xs_cbmutex);
993 
994 	if ((oename = xvdi_get_oename(dip)) == NULL) {
995 		mutex_exit(&vdp->xs_cbmutex);
996 		return;
997 	}
998 
999 	if (xenbus_read_str(oename, XBP_MEDIA_REQ, &str) != 0) {
1000 		mutex_exit(&vdp->xs_cbmutex);
1001 		return;
1002 	}
1003 
1004 	if (!XDB_IS_FE_CD(vdp)) {
1005 		xvdi_dev_error(dip, EINVAL,
1006 		    "media-req only supported for cdrom devices");
1007 		mutex_exit(&vdp->xs_cbmutex);
1008 		return;
1009 	}
1010 
1011 	if (strcmp(str, XBV_MEDIA_REQ_EJECT) != 0) {
1012 		mutex_exit(&vdp->xs_cbmutex);
1013 		strfree(str);
1014 		return;
1015 	}
1016 	strfree(str);
1017 
1018 	XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "media eject request"));
1019 
1020 	xdb_params_change(vdp, "", B_TRUE);
1021 	(void) xenbus_printf(XBT_NULL, oename,
1022 	    XBP_MEDIA_REQ, "%s", XBV_MEDIA_REQ_NONE);
1023 	mutex_exit(&vdp->xs_cbmutex);
1024 }
1025 
1026 /*
1027  * If we're dealing with a cdrom device, let the frontend know that
1028  * we support media requests via XBP_MEDIA_REQ_SUP, and setup a watch
1029  * to handle those frontend media request changes, which modify the
1030  * following xenstore parameter:
1031  *	/local/domain/<domU_id>/device/vbd/<domU_dev>/media-req
1032  */
1033 static boolean_t
1034 xdb_media_req_init(xdb_t *vdp)
1035 {
1036 	dev_info_t		*dip = vdp->xs_dip;
1037 	char			*xsname, *oename;
1038 
1039 	ASSERT(MUTEX_HELD(&vdp->xs_cbmutex));
1040 
1041 	if (((xsname = xvdi_get_xsname(dip)) == NULL) ||
1042 	    ((oename = xvdi_get_oename(dip)) == NULL))
1043 		return (B_FALSE);
1044 
1045 	if (!XDB_IS_FE_CD(vdp))
1046 		return (B_TRUE);
1047 
1048 	if (xenbus_printf(XBT_NULL, xsname, XBP_MEDIA_REQ_SUP, "%d", 1) != 0)
1049 		return (B_FALSE);
1050 
1051 	if (xvdi_add_xb_watch_handler(dip, oename,
1052 	    XBP_MEDIA_REQ, xdb_watch_media_req_cb, NULL) != DDI_SUCCESS) {
1053 		xvdi_dev_error(dip, EAGAIN,
1054 		    "Failed to register watch for cdrom media requests");
1055 		return (B_FALSE);
1056 	}
1057 
1058 	return (B_TRUE);
1059 }
1060 
1061 /*
1062  * Get our params value.  Also, if we're using "params" then setup a
1063  * watch to handle xm block-configure operations which modify the
1064  * following xenstore parameter:
1065  *	/local/domain/0/backend/vbd/<domU_id>/<domU_dev>/params
1066  */
1067 static boolean_t
1068 xdb_params_init(xdb_t *vdp)
1069 {
1070 	dev_info_t		*dip = vdp->xs_dip;
1071 	char			*str, *xsname;
1072 	int			err;
1073 
1074 	ASSERT(MUTEX_HELD(&vdp->xs_cbmutex));
1075 	ASSERT(vdp->xs_params_path == NULL);
1076 
1077 	if ((xsname = xvdi_get_xsname(dip)) == NULL)
1078 		return (B_FALSE);
1079 
1080 	err = xenbus_read_str(xsname, "params", &str);
1081 	if (err != 0) {
1082 		return (B_FALSE);
1083 	}
1084 	vdp->xs_params_path = str;
1085 
1086 	if (xvdi_add_xb_watch_handler(dip, xsname, "params",
1087 	    xdb_watch_params_cb, NULL) != DDI_SUCCESS) {
1088 		strfree(vdp->xs_params_path);
1089 		vdp->xs_params_path = NULL;
1090 		return (B_FALSE);
1091 	}
1092 
1093 	return (B_TRUE);
1094 }
1095 
1096 #define	LOFI_CTRL_NODE	"/dev/lofictl"
1097 #define	LOFI_DEV_NODE	"/devices/pseudo/lofi@0:"
1098 #define	LOFI_MODE	(FREAD | FWRITE | FEXCL)
1099 
1100 static int
1101 xdb_setup_node(xdb_t *vdp, char *path)
1102 {
1103 	dev_info_t		*dip = vdp->xs_dip;
1104 	char			*xsname, *str;
1105 	ldi_handle_t		ldi_hdl;
1106 	struct lofi_ioctl	*li;
1107 	int			minor, err;
1108 
1109 	ASSERT(MUTEX_HELD(&vdp->xs_cbmutex));
1110 
1111 	if ((xsname = xvdi_get_xsname(dip)) == NULL)
1112 		return (DDI_FAILURE);
1113 
1114 	if ((err = xenbus_read_str(xsname, "type", &str)) != 0) {
1115 		xvdi_dev_error(dip, err, "Getting type from backend device");
1116 		return (DDI_FAILURE);
1117 	}
1118 	if (strcmp(str, "file") == 0)
1119 		vdp->xs_type |= XDB_DEV_BE_LOFI;
1120 	strfree(str);
1121 
1122 	if (!XDB_IS_BE_LOFI(vdp)) {
1123 		(void) strlcpy(path, vdp->xs_params_path, MAXPATHLEN);
1124 		ASSERT(vdp->xs_lofi_path == NULL);
1125 		return (DDI_SUCCESS);
1126 	}
1127 
1128 	do {
1129 		err = ldi_open_by_name(LOFI_CTRL_NODE, LOFI_MODE, kcred,
1130 		    &ldi_hdl, vdp->xs_ldi_li);
1131 	} while (err == EBUSY);
1132 	if (err != 0) {
1133 		return (DDI_FAILURE);
1134 	}
1135 
1136 	li = kmem_zalloc(sizeof (*li), KM_SLEEP);
1137 	(void) strlcpy(li->li_filename, vdp->xs_params_path,
1138 	    sizeof (li->li_filename));
1139 	err = ldi_ioctl(ldi_hdl, LOFI_MAP_FILE, (intptr_t)li,
1140 	    LOFI_MODE | FKIOCTL, kcred, &minor);
1141 	(void) ldi_close(ldi_hdl, LOFI_MODE, kcred);
1142 	kmem_free(li, sizeof (*li));
1143 
1144 	if (err != 0) {
1145 		cmn_err(CE_WARN, "xdb@%s: Failed to create lofi dev for %s",
1146 		    ddi_get_name_addr(dip), vdp->xs_params_path);
1147 		return (DDI_FAILURE);
1148 	}
1149 
1150 	/*
1151 	 * return '/devices/...' instead of '/dev/lofi/...' since the
1152 	 * former is available immediately after calling ldi_ioctl
1153 	 */
1154 	(void) snprintf(path, MAXPATHLEN, LOFI_DEV_NODE "%d", minor);
1155 	(void) xenbus_printf(XBT_NULL, xsname, "node", "%s", path);
1156 
1157 	ASSERT(vdp->xs_lofi_path == NULL);
1158 	vdp->xs_lofi_path = strdup(path);
1159 
1160 	return (DDI_SUCCESS);
1161 }
1162 
1163 static void
1164 xdb_teardown_node(xdb_t *vdp)
1165 {
1166 	dev_info_t *dip = vdp->xs_dip;
1167 	ldi_handle_t ldi_hdl;
1168 	struct lofi_ioctl *li;
1169 	int err;
1170 
1171 	ASSERT(MUTEX_HELD(&vdp->xs_cbmutex));
1172 
1173 	if (!XDB_IS_BE_LOFI(vdp))
1174 		return;
1175 
1176 	vdp->xs_type &= ~XDB_DEV_BE_LOFI;
1177 	ASSERT(vdp->xs_lofi_path != NULL);
1178 
1179 	li = kmem_zalloc(sizeof (*li), KM_SLEEP);
1180 	(void) strlcpy(li->li_filename, vdp->xs_params_path,
1181 	    sizeof (li->li_filename));
1182 
1183 	do {
1184 		err = ldi_open_by_name(LOFI_CTRL_NODE, LOFI_MODE, kcred,
1185 		    &ldi_hdl, vdp->xs_ldi_li);
1186 	} while (err == EBUSY);
1187 
1188 	if (err != 0) {
1189 		kmem_free(li, sizeof (*li));
1190 		return;
1191 	}
1192 
1193 	if (ldi_ioctl(ldi_hdl, LOFI_UNMAP_FILE, (intptr_t)li,
1194 	    LOFI_MODE | FKIOCTL, kcred, NULL) != 0) {
1195 		cmn_err(CE_WARN, "xdb@%s: Failed to delete lofi dev for %s",
1196 		    ddi_get_name_addr(dip), li->li_filename);
1197 	}
1198 
1199 	(void) ldi_close(ldi_hdl, LOFI_MODE, kcred);
1200 	kmem_free(li, sizeof (*li));
1201 
1202 	strfree(vdp->xs_lofi_path);
1203 	vdp->xs_lofi_path = NULL;
1204 }
1205 
1206 static int
1207 xdb_open_device(xdb_t *vdp)
1208 {
1209 	dev_info_t *dip = vdp->xs_dip;
1210 	uint64_t devsize;
1211 	int blksize;
1212 	char *nodepath;
1213 	char *xsname;
1214 	char *str;
1215 	int err;
1216 
1217 	ASSERT(MUTEX_HELD(&vdp->xs_cbmutex));
1218 
1219 	if (strlen(vdp->xs_params_path) == 0) {
1220 		/*
1221 		 * it's possible to have no backing device when dealing
1222 		 * with a pv cdrom drive that has no virtual cd associated
1223 		 * with it.
1224 		 */
1225 		ASSERT(XDB_IS_FE_CD(vdp));
1226 		ASSERT(vdp->xs_sectors == 0);
1227 		ASSERT(vdp->xs_ldi_li == NULL);
1228 		ASSERT(vdp->xs_ldi_hdl == NULL);
1229 		return (DDI_SUCCESS);
1230 	}
1231 
1232 	/*
1233 	 * after the hotplug scripts have "connected" the device, check to see
1234 	 * if we're using a dynamic device.  If so, replace the params path
1235 	 * with the dynamic one.
1236 	 */
1237 	xsname = xvdi_get_xsname(dip);
1238 	err = xenbus_read_str(xsname, "dynamic-device-path", &str);
1239 	if (err == 0) {
1240 		strfree(vdp->xs_params_path);
1241 		vdp->xs_params_path = str;
1242 	}
1243 
1244 	if (ldi_ident_from_dip(dip, &vdp->xs_ldi_li) != 0)
1245 		return (DDI_FAILURE);
1246 
1247 	nodepath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1248 
1249 	/* try to open backend device */
1250 	if (xdb_setup_node(vdp, nodepath) != DDI_SUCCESS) {
1251 		xvdi_dev_error(dip, ENXIO,
1252 		    "Getting device path of backend device");
1253 		ldi_ident_release(vdp->xs_ldi_li);
1254 		kmem_free(nodepath, MAXPATHLEN);
1255 		return (DDI_FAILURE);
1256 	}
1257 
1258 	if (ldi_open_by_name(nodepath,
1259 	    FREAD | (XDB_IS_RO(vdp) ? 0 : FWRITE),
1260 	    kcred, &vdp->xs_ldi_hdl, vdp->xs_ldi_li) != 0) {
1261 		xdb_teardown_node(vdp);
1262 		ldi_ident_release(vdp->xs_ldi_li);
1263 		cmn_err(CE_WARN, "xdb@%s: Failed to open: %s",
1264 		    ddi_get_name_addr(dip), nodepath);
1265 		kmem_free(nodepath, MAXPATHLEN);
1266 		return (DDI_FAILURE);
1267 	}
1268 
1269 	if (ldi_get_size(vdp->xs_ldi_hdl, &devsize) != DDI_SUCCESS) {
1270 		(void) ldi_close(vdp->xs_ldi_hdl,
1271 		    FREAD | (XDB_IS_RO(vdp) ? 0 : FWRITE), kcred);
1272 		xdb_teardown_node(vdp);
1273 		ldi_ident_release(vdp->xs_ldi_li);
1274 		kmem_free(nodepath, MAXPATHLEN);
1275 		return (DDI_FAILURE);
1276 	}
1277 
1278 	blksize = ldi_prop_get_int64(vdp->xs_ldi_hdl,
1279 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1280 	    "blksize", DEV_BSIZE);
1281 	if (blksize == DEV_BSIZE)
1282 		blksize = ldi_prop_get_int(vdp->xs_ldi_hdl,
1283 		    LDI_DEV_T_ANY | DDI_PROP_DONTPASS |
1284 		    DDI_PROP_NOTPROM, "device-blksize", DEV_BSIZE);
1285 
1286 	vdp->xs_sec_size = blksize;
1287 	vdp->xs_sectors = devsize / blksize;
1288 
1289 	/* check if the underlying device is a CD/DVD disc */
1290 	if (ldi_prop_get_int(vdp->xs_ldi_hdl, LDI_DEV_T_ANY | DDI_PROP_DONTPASS,
1291 	    INQUIRY_DEVICE_TYPE, DTYPE_DIRECT) == DTYPE_RODIRECT)
1292 		vdp->xs_type |= XDB_DEV_BE_CD;
1293 
1294 	/* check if the underlying device is a removable disk */
1295 	if (ldi_prop_exists(vdp->xs_ldi_hdl,
1296 	    LDI_DEV_T_ANY | DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1297 	    "removable-media"))
1298 		vdp->xs_type |= XDB_DEV_BE_RMB;
1299 
1300 	kmem_free(nodepath, MAXPATHLEN);
1301 	return (DDI_SUCCESS);
1302 }
1303 
1304 static void
1305 xdb_close_device(xdb_t *vdp)
1306 {
1307 	ASSERT(MUTEX_HELD(&vdp->xs_cbmutex));
1308 
1309 	if (strlen(vdp->xs_params_path) == 0) {
1310 		ASSERT(XDB_IS_FE_CD(vdp));
1311 		ASSERT(vdp->xs_sectors == 0);
1312 		ASSERT(vdp->xs_ldi_li == NULL);
1313 		ASSERT(vdp->xs_ldi_hdl == NULL);
1314 		return;
1315 	}
1316 
1317 	(void) ldi_close(vdp->xs_ldi_hdl,
1318 	    FREAD | (XDB_IS_RO(vdp) ? 0 : FWRITE), kcred);
1319 	xdb_teardown_node(vdp);
1320 	ldi_ident_release(vdp->xs_ldi_li);
1321 	vdp->xs_type &= ~(XDB_DEV_BE_CD | XDB_DEV_BE_RMB);
1322 	vdp->xs_sectors = 0;
1323 	vdp->xs_ldi_li = NULL;
1324 	vdp->xs_ldi_hdl = NULL;
1325 }
1326 
1327 /*
1328  * Kick-off connect process
1329  * If xs_fe_initialised == B_TRUE and xs_hp_connected == B_TRUE
1330  * the xs_if_connected will be changed to B_TRUE on success,
1331  */
1332 static void
1333 xdb_start_connect(xdb_t *vdp)
1334 {
1335 	xenbus_transaction_t	xbt;
1336 	dev_info_t		*dip = vdp->xs_dip;
1337 	boolean_t		fb_exists;
1338 	int			err, instance = ddi_get_instance(dip);
1339 	uint64_t		sectors;
1340 	uint_t			dinfo, ssize;
1341 	char			*xsname;
1342 
1343 	ASSERT(MUTEX_HELD(&vdp->xs_cbmutex));
1344 
1345 	if (((xsname = xvdi_get_xsname(dip)) == NULL) ||
1346 	    ((vdp->xs_peer = xvdi_get_oeid(dip)) == (domid_t)-1))
1347 		return;
1348 
1349 	mutex_enter(&vdp->xs_iomutex);
1350 	/*
1351 	 * if the hotplug scripts haven't run or if the frontend is not
1352 	 * initialized, then we can't try to connect.
1353 	 */
1354 	if (!vdp->xs_hp_connected || !vdp->xs_fe_initialised) {
1355 		ASSERT(!vdp->xs_if_connected);
1356 		mutex_exit(&vdp->xs_iomutex);
1357 		return;
1358 	}
1359 
1360 	/* If we're already connected then there's nothing todo */
1361 	if (vdp->xs_if_connected) {
1362 		mutex_exit(&vdp->xs_iomutex);
1363 		return;
1364 	}
1365 	mutex_exit(&vdp->xs_iomutex);
1366 
1367 	/*
1368 	 * Start connect to frontend only when backend device are ready
1369 	 * and frontend has moved to XenbusStateInitialised, which means
1370 	 * ready to connect.
1371 	 */
1372 	XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE,
1373 	    "xdb@%s: starting connection process", ddi_get_name_addr(dip)));
1374 
1375 	if (xdb_open_device(vdp) != DDI_SUCCESS)
1376 		return;
1377 
1378 	if (xdb_bindto_frontend(vdp) != DDI_SUCCESS) {
1379 		xdb_close_device(vdp);
1380 		return;
1381 	}
1382 
1383 	/* init i/o requests */
1384 	xdb_init_ioreqs(vdp);
1385 
1386 	if (ddi_add_intr(dip, 0, NULL, NULL, xdb_intr, (caddr_t)vdp)
1387 	    != DDI_SUCCESS) {
1388 		xdb_uninit_ioreqs(vdp);
1389 		xdb_unbindfrom_frontend(vdp);
1390 		xdb_close_device(vdp);
1391 		return;
1392 	}
1393 
1394 	dinfo = 0;
1395 	if (XDB_IS_RO(vdp))
1396 		dinfo |= VDISK_READONLY;
1397 	if (XDB_IS_BE_RMB(vdp))
1398 		dinfo |= VDISK_REMOVABLE;
1399 	if (XDB_IS_BE_CD(vdp))
1400 		dinfo |= VDISK_CDROM;
1401 	if (XDB_IS_FE_CD(vdp))
1402 		dinfo |= VDISK_REMOVABLE | VDISK_CDROM;
1403 
1404 	/*
1405 	 * we can recieve intr any time from now on
1406 	 * mark that we're ready to take intr
1407 	 */
1408 	mutex_enter(&vdp->xs_iomutex);
1409 	ASSERT(vdp->xs_fe_initialised);
1410 	vdp->xs_if_connected = B_TRUE;
1411 	mutex_exit(&vdp->xs_iomutex);
1412 
1413 trans_retry:
1414 	/* write into xenstore the info needed by frontend */
1415 	if ((err = xenbus_transaction_start(&xbt)) != 0) {
1416 		xvdi_dev_error(dip, err, "connect transaction init");
1417 		goto errout;
1418 	}
1419 
1420 	/* If feature-barrier isn't present in xenstore, add it.  */
1421 	fb_exists = xenbus_exists(xsname, XBP_FB);
1422 
1423 	ssize = (vdp->xs_sec_size == 0) ? DEV_BSIZE : vdp->xs_sec_size;
1424 	sectors = vdp->xs_sectors;
1425 	if (((!fb_exists &&
1426 	    (err = xenbus_printf(xbt, xsname, XBP_FB, "%d", 1)))) ||
1427 	    (err = xenbus_printf(xbt, xsname, XBP_INFO, "%u", dinfo)) ||
1428 	    (err = xenbus_printf(xbt, xsname, XBP_SECTOR_SIZE, "%u", ssize)) ||
1429 	    (err = xenbus_printf(xbt, xsname,
1430 	    XBP_SECTORS, "%"PRIu64, sectors)) ||
1431 	    (err = xenbus_printf(xbt, xsname, "instance", "%d", instance)) ||
1432 	    ((err = xvdi_switch_state(dip, xbt, XenbusStateConnected)) > 0)) {
1433 		(void) xenbus_transaction_end(xbt, 1);
1434 		xvdi_dev_error(dip, err, "connect transaction setup");
1435 		goto errout;
1436 	}
1437 
1438 	if ((err = xenbus_transaction_end(xbt, 0)) != 0) {
1439 		if (err == EAGAIN) {
1440 			/* transaction is ended, don't need to abort it */
1441 			goto trans_retry;
1442 		}
1443 		xvdi_dev_error(dip, err, "connect transaction commit");
1444 		goto errout;
1445 	}
1446 
1447 	return;
1448 
1449 errout:
1450 	xdb_close(dip);
1451 }
1452 
1453 /*
1454  * Disconnect from frontend and close backend device
1455  */
1456 static void
1457 xdb_close(dev_info_t *dip)
1458 {
1459 	xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip);
1460 
1461 	ASSERT(MUTEX_HELD(&vdp->xs_cbmutex));
1462 	mutex_enter(&vdp->xs_iomutex);
1463 
1464 	/*
1465 	 * if the hotplug scripts haven't run or if the frontend is not
1466 	 * initialized, then we can't be connected, so there's no
1467 	 * connection to close.
1468 	 */
1469 	if (!vdp->xs_hp_connected || !vdp->xs_fe_initialised) {
1470 		ASSERT(!vdp->xs_if_connected);
1471 		mutex_exit(&vdp->xs_iomutex);
1472 		return;
1473 	}
1474 
1475 	/* if we're not connected, there's nothing to do */
1476 	if (!vdp->xs_if_connected) {
1477 		cv_broadcast(&vdp->xs_iocv);
1478 		mutex_exit(&vdp->xs_iomutex);
1479 		return;
1480 	}
1481 
1482 	XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "closing while connected"));
1483 
1484 	vdp->xs_if_connected = B_FALSE;
1485 	cv_broadcast(&vdp->xs_iocv);
1486 
1487 	mutex_exit(&vdp->xs_iomutex);
1488 
1489 	/* stop accepting I/O request from frontend */
1490 	ddi_remove_intr(dip, 0, NULL);
1491 
1492 	/* clear all on-going I/Os, if any */
1493 	mutex_enter(&vdp->xs_iomutex);
1494 	while (vdp->xs_ionum > 0)
1495 		cv_wait(&vdp->xs_ionumcv, &vdp->xs_iomutex);
1496 	mutex_exit(&vdp->xs_iomutex);
1497 
1498 	/* clean up resources and close this interface */
1499 	xdb_uninit_ioreqs(vdp);
1500 	xdb_unbindfrom_frontend(vdp);
1501 	xdb_close_device(vdp);
1502 	vdp->xs_peer = (domid_t)-1;
1503 }
1504 
1505 static void
1506 xdb_send_buf(void *arg)
1507 {
1508 	xdb_t	*vdp = (xdb_t *)arg;
1509 	buf_t	*bp;
1510 	int	err;
1511 
1512 	mutex_enter(&vdp->xs_iomutex);
1513 	while (vdp->xs_send_buf) {
1514 		if ((bp = vdp->xs_f_iobuf) == NULL) {
1515 			/* wait for some io to send */
1516 			XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE,
1517 			    "send buf waiting for io"));
1518 			cv_wait(&vdp->xs_iocv, &vdp->xs_iomutex);
1519 			continue;
1520 		}
1521 
1522 		vdp->xs_f_iobuf = bp->av_forw;
1523 		bp->av_forw = NULL;
1524 		vdp->xs_ionum++;
1525 
1526 		mutex_exit(&vdp->xs_iomutex);
1527 		if (bp->b_bcount == 0) {
1528 			/* no I/O needs to be done */
1529 			(void) xdb_biodone(bp);
1530 			mutex_enter(&vdp->xs_iomutex);
1531 			continue;
1532 		}
1533 
1534 		err = EIO;
1535 		if (vdp->xs_ldi_hdl != NULL)
1536 			err = ldi_strategy(vdp->xs_ldi_hdl, bp);
1537 		if (err != 0) {
1538 			bp->b_flags |= B_ERROR;
1539 			(void) xdb_biodone(bp);
1540 			XDB_DBPRINT(XDB_DBG_IO, (CE_WARN,
1541 			    "xdb@%s: sent buf to backend devfailed, err=%d",
1542 			    ddi_get_name_addr(vdp->xs_dip), err));
1543 		} else {
1544 			XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE,
1545 			    "sent buf to backend ok"));
1546 		}
1547 		mutex_enter(&vdp->xs_iomutex);
1548 	}
1549 	XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "send buf finishing"));
1550 	mutex_exit(&vdp->xs_iomutex);
1551 }
1552 
1553 /*ARGSUSED*/
1554 static void
1555 xdb_hp_state_change(dev_info_t *dip, ddi_eventcookie_t id, void *arg,
1556     void *impl_data)
1557 {
1558 	xendev_hotplug_state_t state = *(xendev_hotplug_state_t *)impl_data;
1559 	xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip);
1560 
1561 	XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: "
1562 	    "hotplug status change to %d!", ddi_get_name_addr(dip), state));
1563 
1564 	if (state != Connected)
1565 		return;
1566 
1567 	mutex_enter(&vdp->xs_cbmutex);
1568 
1569 	/* If hotplug script have already run, there's nothing todo */
1570 	if (vdp->xs_hp_connected) {
1571 		mutex_exit(&vdp->xs_cbmutex);
1572 		return;
1573 	}
1574 
1575 	vdp->xs_hp_connected = B_TRUE;
1576 	xdb_start_connect(vdp);
1577 	mutex_exit(&vdp->xs_cbmutex);
1578 }
1579 
1580 /*ARGSUSED*/
1581 static void
1582 xdb_oe_state_change(dev_info_t *dip, ddi_eventcookie_t id, void *arg,
1583     void *impl_data)
1584 {
1585 	XenbusState new_state = *(XenbusState *)impl_data;
1586 	xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip);
1587 
1588 	XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: "
1589 	    "otherend state change to %d!", ddi_get_name_addr(dip), new_state));
1590 
1591 	mutex_enter(&vdp->xs_cbmutex);
1592 
1593 	/*
1594 	 * Now it'd really be nice if there was a well defined state
1595 	 * transition model for xen frontend drivers, but unfortunatly
1596 	 * there isn't.  So we're stuck with assuming that all state
1597 	 * transitions are possible, and we'll just have to deal with
1598 	 * them regardless of what state we're in.
1599 	 */
1600 	switch (new_state) {
1601 	case XenbusStateUnknown:
1602 	case XenbusStateInitialising:
1603 	case XenbusStateInitWait:
1604 		/* tear down our connection to the frontend */
1605 		xdb_close(dip);
1606 		vdp->xs_fe_initialised = B_FALSE;
1607 		break;
1608 
1609 	case XenbusStateInitialised:
1610 		/*
1611 		 * If we were conected, then we need to drop the connection
1612 		 * and re-negotiate it.
1613 		 */
1614 		xdb_close(dip);
1615 		vdp->xs_fe_initialised = B_TRUE;
1616 		xdb_start_connect(vdp);
1617 		break;
1618 
1619 	case XenbusStateConnected:
1620 		/* nothing todo here other than congratulate the frontend */
1621 		break;
1622 
1623 	case XenbusStateClosing:
1624 		/* monkey see monkey do */
1625 		(void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosing);
1626 		break;
1627 
1628 	case XenbusStateClosed:
1629 		/* tear down our connection to the frontend */
1630 		xdb_close(dip);
1631 		vdp->xs_fe_initialised = B_FALSE;
1632 		(void) xvdi_switch_state(dip, XBT_NULL, new_state);
1633 		break;
1634 	}
1635 
1636 	mutex_exit(&vdp->xs_cbmutex);
1637 }
1638 
1639 static int
1640 xdb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1641 {
1642 	ddi_iblock_cookie_t	ibc;
1643 	xdb_t			*vdp;
1644 	int			instance = ddi_get_instance(dip);
1645 	char			*xsname, *oename;
1646 	char			*str;
1647 
1648 	switch (cmd) {
1649 	case DDI_RESUME:
1650 		return (DDI_FAILURE);
1651 	case DDI_ATTACH:
1652 		break;
1653 	default:
1654 		return (DDI_FAILURE);
1655 	}
1656 	/* DDI_ATTACH */
1657 
1658 	if (((xsname = xvdi_get_xsname(dip)) == NULL) ||
1659 	    ((oename = xvdi_get_oename(dip)) == NULL))
1660 		return (DDI_FAILURE);
1661 
1662 	/*
1663 	 * Disable auto-detach.  This is necessary so that we don't get
1664 	 * detached while we're disconnected from the front end.
1665 	 */
1666 	(void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, 1);
1667 
1668 	if (ddi_get_iblock_cookie(dip, 0, &ibc) != DDI_SUCCESS)
1669 		return (DDI_FAILURE);
1670 
1671 	if (ddi_soft_state_zalloc(xdb_statep, instance) != DDI_SUCCESS)
1672 		return (DDI_FAILURE);
1673 
1674 	vdp = ddi_get_soft_state(xdb_statep, instance);
1675 	vdp->xs_dip = dip;
1676 	mutex_init(&vdp->xs_iomutex, NULL, MUTEX_DRIVER, (void *)ibc);
1677 	mutex_init(&vdp->xs_cbmutex, NULL, MUTEX_DRIVER, (void *)ibc);
1678 	cv_init(&vdp->xs_iocv, NULL, CV_DRIVER, NULL);
1679 	cv_init(&vdp->xs_ionumcv, NULL, CV_DRIVER, NULL);
1680 	ddi_set_driver_private(dip, vdp);
1681 
1682 	if (!xdb_kstat_init(vdp))
1683 		goto errout1;
1684 
1685 	/* Check if the frontend device is supposed to be a cdrom */
1686 	if (xenbus_read_str(oename, XBP_DEV_TYPE, &str) != 0)
1687 		return (DDI_FAILURE);
1688 	if (strcmp(str, XBV_DEV_TYPE_CD) == 0)
1689 		vdp->xs_type |= XDB_DEV_FE_CD;
1690 	strfree(str);
1691 
1692 	/* Check if the frontend device is supposed to be read only */
1693 	if (xenbus_read_str(xsname, "mode", &str) != 0)
1694 		return (DDI_FAILURE);
1695 	if ((strcmp(str, "r") == NULL) || (strcmp(str, "ro") == NULL))
1696 		vdp->xs_type |= XDB_DEV_RO;
1697 	strfree(str);
1698 
1699 	mutex_enter(&vdp->xs_cbmutex);
1700 	if (!xdb_media_req_init(vdp) || !xdb_params_init(vdp)) {
1701 		xvdi_remove_xb_watch_handlers(dip);
1702 		mutex_exit(&vdp->xs_cbmutex);
1703 		goto errout2;
1704 	}
1705 	mutex_exit(&vdp->xs_cbmutex);
1706 
1707 	vdp->xs_send_buf = B_TRUE;
1708 	vdp->xs_iotaskq = ddi_taskq_create(dip, "xdb_iotask", 1,
1709 	    TASKQ_DEFAULTPRI, 0);
1710 	(void) ddi_taskq_dispatch(vdp->xs_iotaskq, xdb_send_buf, vdp,
1711 	    DDI_SLEEP);
1712 
1713 	/* Watch frontend and hotplug state change */
1714 	if ((xvdi_add_event_handler(dip, XS_OE_STATE, xdb_oe_state_change,
1715 	    NULL) != DDI_SUCCESS) ||
1716 	    (xvdi_add_event_handler(dip, XS_HP_STATE, xdb_hp_state_change,
1717 	    NULL) != DDI_SUCCESS))
1718 		goto errout3;
1719 
1720 	/*
1721 	 * Kick-off hotplug script
1722 	 */
1723 	if (xvdi_post_event(dip, XEN_HP_ADD) != DDI_SUCCESS) {
1724 		cmn_err(CE_WARN, "xdb@%s: failed to start hotplug script",
1725 		    ddi_get_name_addr(dip));
1726 		goto errout3;
1727 	}
1728 
1729 	/*
1730 	 * start waiting for hotplug event and otherend state event
1731 	 * mainly for debugging, frontend will not take any op seeing this
1732 	 */
1733 	(void) xvdi_switch_state(dip, XBT_NULL, XenbusStateInitWait);
1734 
1735 	XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: attached!",
1736 	    ddi_get_name_addr(dip)));
1737 	return (DDI_SUCCESS);
1738 
1739 errout3:
1740 	ASSERT(vdp->xs_hp_connected && vdp->xs_if_connected);
1741 
1742 	xvdi_remove_event_handler(dip, NULL);
1743 
1744 	/* Disconnect from the backend */
1745 	mutex_enter(&vdp->xs_cbmutex);
1746 	mutex_enter(&vdp->xs_iomutex);
1747 	vdp->xs_send_buf = B_FALSE;
1748 	cv_broadcast(&vdp->xs_iocv);
1749 	mutex_exit(&vdp->xs_iomutex);
1750 	mutex_exit(&vdp->xs_cbmutex);
1751 
1752 	/* wait for all io to dtrain and destroy io taskq */
1753 	ddi_taskq_destroy(vdp->xs_iotaskq);
1754 
1755 	/* tear down block-configure watch */
1756 	mutex_enter(&vdp->xs_cbmutex);
1757 	xvdi_remove_xb_watch_handlers(dip);
1758 	mutex_exit(&vdp->xs_cbmutex);
1759 
1760 errout2:
1761 	/* remove kstats */
1762 	kstat_delete(vdp->xs_kstats);
1763 
1764 errout1:
1765 	/* free up driver state */
1766 	ddi_set_driver_private(dip, NULL);
1767 	cv_destroy(&vdp->xs_iocv);
1768 	cv_destroy(&vdp->xs_ionumcv);
1769 	mutex_destroy(&vdp->xs_cbmutex);
1770 	mutex_destroy(&vdp->xs_iomutex);
1771 	ddi_soft_state_free(xdb_statep, instance);
1772 
1773 	return (DDI_FAILURE);
1774 }
1775 
1776 /*ARGSUSED*/
1777 static int
1778 xdb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1779 {
1780 	int instance = ddi_get_instance(dip);
1781 	xdb_t *vdp = XDB_INST2SOFTS(instance);
1782 
1783 	switch (cmd) {
1784 	case DDI_SUSPEND:
1785 		return (DDI_FAILURE);
1786 	case DDI_DETACH:
1787 		break;
1788 	default:
1789 		return (DDI_FAILURE);
1790 	}
1791 
1792 	/* DDI_DETACH handling */
1793 
1794 	/* refuse to detach if we're still in use by the frontend */
1795 	mutex_enter(&vdp->xs_iomutex);
1796 	if (vdp->xs_if_connected) {
1797 		mutex_exit(&vdp->xs_iomutex);
1798 		return (DDI_FAILURE);
1799 	}
1800 	vdp->xs_send_buf = B_FALSE;
1801 	cv_broadcast(&vdp->xs_iocv);
1802 	mutex_exit(&vdp->xs_iomutex);
1803 
1804 	xvdi_remove_event_handler(dip, NULL);
1805 	(void) xvdi_post_event(dip, XEN_HP_REMOVE);
1806 
1807 	ddi_taskq_destroy(vdp->xs_iotaskq);
1808 
1809 	mutex_enter(&vdp->xs_cbmutex);
1810 	xvdi_remove_xb_watch_handlers(dip);
1811 	mutex_exit(&vdp->xs_cbmutex);
1812 
1813 	cv_destroy(&vdp->xs_iocv);
1814 	cv_destroy(&vdp->xs_ionumcv);
1815 	mutex_destroy(&vdp->xs_cbmutex);
1816 	mutex_destroy(&vdp->xs_iomutex);
1817 	kstat_delete(vdp->xs_kstats);
1818 	ddi_set_driver_private(dip, NULL);
1819 	ddi_soft_state_free(xdb_statep, instance);
1820 
1821 	XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: detached!",
1822 	    ddi_get_name_addr(dip)));
1823 	return (DDI_SUCCESS);
1824 }
1825 
1826 static struct dev_ops xdb_dev_ops = {
1827 	DEVO_REV,	/* devo_rev */
1828 	0,		/* devo_refcnt */
1829 	ddi_getinfo_1to1, /* devo_getinfo */
1830 	nulldev,	/* devo_identify */
1831 	nulldev,	/* devo_probe */
1832 	xdb_attach,	/* devo_attach */
1833 	xdb_detach,	/* devo_detach */
1834 	nodev,		/* devo_reset */
1835 	NULL,		/* devo_cb_ops */
1836 	NULL,		/* devo_bus_ops */
1837 	NULL,		/* power */
1838 	ddi_quiesce_not_needed, /* quiesce */
1839 };
1840 
1841 /*
1842  * Module linkage information for the kernel.
1843  */
1844 static struct modldrv modldrv = {
1845 	&mod_driverops,			/* Type of module. */
1846 	"vbd backend driver",		/* Name of the module */
1847 	&xdb_dev_ops			/* driver ops */
1848 };
1849 
1850 static struct modlinkage xdb_modlinkage = {
1851 	MODREV_1,
1852 	&modldrv,
1853 	NULL
1854 };
1855 
1856 int
1857 _init(void)
1858 {
1859 	int rv;
1860 
1861 	if ((rv = ddi_soft_state_init((void **)&xdb_statep,
1862 	    sizeof (xdb_t), 0)) == 0)
1863 		if ((rv = mod_install(&xdb_modlinkage)) != 0)
1864 			ddi_soft_state_fini((void **)&xdb_statep);
1865 	return (rv);
1866 }
1867 
1868 int
1869 _fini(void)
1870 {
1871 	int rv;
1872 
1873 	if ((rv = mod_remove(&xdb_modlinkage)) != 0)
1874 		return (rv);
1875 	ddi_soft_state_fini((void **)&xdb_statep);
1876 	return (rv);
1877 }
1878 
1879 int
1880 _info(struct modinfo *modinfop)
1881 {
1882 	return (mod_info(&xdb_modlinkage, modinfop));
1883 }
1884 
1885 static int
1886 xdb_get_request(xdb_t *vdp, blkif_request_t *req)
1887 {
1888 	void *src = xvdi_ring_get_request(vdp->xs_ring);
1889 
1890 	if (src == NULL)
1891 		return (0);
1892 
1893 	switch (vdp->xs_blk_protocol) {
1894 	case BLKIF_PROTOCOL_NATIVE:
1895 		(void) memcpy(req, src, sizeof (*req));
1896 		break;
1897 	case BLKIF_PROTOCOL_X86_32:
1898 		blkif_get_x86_32_req(req, src);
1899 		break;
1900 	case BLKIF_PROTOCOL_X86_64:
1901 		blkif_get_x86_64_req(req, src);
1902 		break;
1903 	default:
1904 		cmn_err(CE_PANIC, "xdb@%s: unrecognised protocol: %d",
1905 		    ddi_get_name_addr(vdp->xs_dip),
1906 		    vdp->xs_blk_protocol);
1907 	}
1908 	return (1);
1909 }
1910 
1911 static int
1912 xdb_push_response(xdb_t *vdp, uint64_t id, uint8_t op, uint16_t status)
1913 {
1914 	ddi_acc_handle_t acchdl = vdp->xs_ring_hdl;
1915 	blkif_response_t *rsp = xvdi_ring_get_response(vdp->xs_ring);
1916 	blkif_x86_32_response_t *rsp_32 = (blkif_x86_32_response_t *)rsp;
1917 	blkif_x86_64_response_t *rsp_64 = (blkif_x86_64_response_t *)rsp;
1918 
1919 	ASSERT(rsp);
1920 
1921 	switch (vdp->xs_blk_protocol) {
1922 	case BLKIF_PROTOCOL_NATIVE:
1923 		ddi_put64(acchdl, &rsp->id, id);
1924 		ddi_put8(acchdl, &rsp->operation, op);
1925 		ddi_put16(acchdl, (uint16_t *)&rsp->status,
1926 		    status == 0 ? BLKIF_RSP_OKAY : BLKIF_RSP_ERROR);
1927 		break;
1928 	case BLKIF_PROTOCOL_X86_32:
1929 		ddi_put64(acchdl, &rsp_32->id, id);
1930 		ddi_put8(acchdl, &rsp_32->operation, op);
1931 		ddi_put16(acchdl, (uint16_t *)&rsp_32->status,
1932 		    status == 0 ? BLKIF_RSP_OKAY : BLKIF_RSP_ERROR);
1933 		break;
1934 	case BLKIF_PROTOCOL_X86_64:
1935 		ddi_put64(acchdl, &rsp_64->id, id);
1936 		ddi_put8(acchdl, &rsp_64->operation, op);
1937 		ddi_put16(acchdl, (uint16_t *)&rsp_64->status,
1938 		    status == 0 ? BLKIF_RSP_OKAY : BLKIF_RSP_ERROR);
1939 		break;
1940 	default:
1941 		cmn_err(CE_PANIC, "xdb@%s: unrecognised protocol: %d",
1942 		    ddi_get_name_addr(vdp->xs_dip),
1943 		    vdp->xs_blk_protocol);
1944 	}
1945 
1946 	return (xvdi_ring_push_response(vdp->xs_ring));
1947 }
1948 
1949 static void
1950 blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_request_t *src)
1951 {
1952 	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
1953 	dst->operation = src->operation;
1954 	dst->nr_segments = src->nr_segments;
1955 	dst->handle = src->handle;
1956 	dst->id = src->id;
1957 	dst->sector_number = src->sector_number;
1958 	if (n > src->nr_segments)
1959 		n = src->nr_segments;
1960 	for (i = 0; i < n; i++)
1961 		dst->seg[i] = src->seg[i];
1962 }
1963 
1964 static void
1965 blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_request_t *src)
1966 {
1967 	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
1968 	dst->operation = src->operation;
1969 	dst->nr_segments = src->nr_segments;
1970 	dst->handle = src->handle;
1971 	dst->id = src->id;
1972 	dst->sector_number = src->sector_number;
1973 	if (n > src->nr_segments)
1974 		n = src->nr_segments;
1975 	for (i = 0; i < n; i++)
1976 		dst->seg[i] = src->seg[i];
1977 }
1978