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 }