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 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #ifndef _SYS_XDF_H 29 #define _SYS_XDF_H 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 38 #include <sys/types.h> 39 #include <sys/conf.h> 40 #include <sys/ddi.h> 41 #include <sys/dditypes.h> 42 #include <sys/sunddi.h> 43 #include <sys/list.h> 44 #include <sys/dkio.h> 45 #include <sys/vtoc.h> 46 #include <sys/modctl.h> 47 #include <sys/bootconf.h> 48 #include <sys/promif.h> 49 #include <sys/open.h> 50 #include <sys/sysmacros.h> 51 #include <sys/kstat.h> 52 #include <sys/gnttab.h> 53 #include <xen/sys/xenbus_impl.h> 54 #include <xen/sys/xendev.h> 55 #include <sys/cmlb.h> 56 #include <sys/scsi/generic/inquiry.h> 57 58 #define BLKIF_RING_SIZE __RING_SIZE((blkif_sring_t *)NULL, PAGESIZE) 59 60 /* 61 * VBDs have standard 512 byte blocks 62 * A single blkif_request can transfer up to 11 pages of data, 1 page/segment 63 */ 64 #define XB_BSIZE DEV_BSIZE 65 #define XB_BMASK (XB_BSIZE - 1) 66 #define XB_BSHIFT 9 67 #define XB_DTOB(bn) ((bn) << XB_BSHIFT) 68 69 #define XB_MAX_SEGLEN (8 * XB_BSIZE) 70 #define XB_SEGOFFSET (XB_MAX_SEGLEN - 1) 71 #define XB_MAX_XFER (XB_MAX_SEGLEN * BLKIF_MAX_SEGMENTS_PER_REQUEST) 72 #define XB_MAXPHYS (XB_MAX_XFER * BLKIF_RING_SIZE) 73 74 /* 75 * blkif status 76 */ 77 enum xdf_state { 78 /* 79 * initial state 80 */ 81 XD_UNKNOWN, 82 /* 83 * ring and evtchn alloced, xenbus state changed to 84 * XenbusStateInitialised, wait for backend to connect 85 */ 86 XD_INIT, 87 /* 88 * backend's xenbus state has changed to XenbusStateConnected, 89 * this is the only state allowing I/Os 90 */ 91 XD_READY, 92 /* 93 * vbd interface close request received from backend, no more I/O 94 * requestis allowed to be put into ring buffer, while interrupt handler 95 * is allowed to run to finish any outstanding I/O request, disconnect 96 * process is kicked off by changing xenbus state to XenbusStateClosed 97 */ 98 XD_CLOSING, 99 /* 100 * disconnection process finished, both backend and frontend's 101 * xenbus state has been changed to XenbusStateClosed, can be detached 102 */ 103 XD_CLOSED, 104 /* 105 * disconnection process finished, frontend is suspended 106 */ 107 XD_SUSPEND 108 }; 109 110 /* 111 * 16 paritions + fdisk 112 */ 113 #define XDF_PSHIFT 6 114 #define XDF_PMASK ((1 << XDF_PSHIFT) - 1) 115 #define XDF_PEXT (1 << XDF_PSHIFT) 116 #define XDF_MINOR(i, m) (((i) << XDF_PSHIFT) | (m)) 117 #define XDF_INST(m) ((m) >> XDF_PSHIFT) 118 #define XDF_PART(m) ((m) & XDF_PMASK) 119 120 /* 121 * one blkif_request_t will have one corresponding ge_slot_t 122 * where we save those grant table refs used in this blkif_request_t 123 * 124 * the id of this ge_slot_t will also be put into 'id' field in 125 * each blkif_request_t when sent out to the ring buffer. 126 */ 127 typedef struct ge_slot { 128 list_node_t link; 129 domid_t oeid; 130 struct v_req *vreq; 131 int isread; 132 grant_ref_t ghead; 133 int ngrefs; 134 grant_ref_t ge[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 135 } ge_slot_t; 136 137 /* 138 * vbd I/O request 139 * 140 * An instance of this structure is bound to each buf passed to 141 * the driver's strategy by setting the pointer into bp->av_back. 142 * The id of this vreq will also be put into 'id' field in each 143 * blkif_request_t when sent out to the ring buffer for one DMA 144 * window of this buf. 145 * 146 * Vreq mainly contains DMA information for this buf. In one vreq/buf, 147 * there could be more than one DMA window, each of which will be 148 * mapped to one blkif_request_t/ge_slot_t. Ge_slot_t contains all grant 149 * table entry information for this buf. The ge_slot_t for current DMA 150 * window is pointed to by v_gs in vreq. 151 * 152 * So, grant table entries will only be alloc'ed when the DMA window is 153 * about to be transferred via blkif_request_t to the ring buffer. And 154 * they will be freed right after the blkif_response_t is seen. By this 155 * means, we can make use of grant table entries more efficiently. 156 */ 157 typedef struct v_req { 158 list_node_t v_link; 159 int v_status; 160 buf_t *v_buf; 161 ddi_dma_handle_t v_dmahdl; 162 ddi_dma_cookie_t v_dmac; 163 uint_t v_ndmacs; 164 uint_t v_dmaw; 165 uint_t v_ndmaws; 166 uint_t v_nslots; 167 ge_slot_t *v_gs; 168 uint64_t v_blkno; 169 ddi_acc_handle_t v_align; 170 caddr_t v_abuf; 171 ddi_dma_handle_t v_memdmahdl; 172 uint8_t v_flush_diskcache; 173 } v_req_t; 174 175 /* 176 * Status set and checked in vreq->v_status by vreq_setup() 177 * 178 * These flags will help us to continue the vreq setup work from last failure 179 * point, instead of starting from scrath after each failure. 180 */ 181 #define VREQ_INIT 0x0 182 #define VREQ_INIT_DONE 0x1 183 #define VREQ_DMAHDL_ALLOCED 0x2 184 #define VREQ_MEMDMAHDL_ALLOCED 0x3 185 #define VREQ_DMAMEM_ALLOCED 0x4 186 #define VREQ_DMABUF_BOUND 0x5 187 #define VREQ_GS_ALLOCED 0x6 188 #define VREQ_DMAWIN_DONE 0x7 189 190 /* 191 * virtual block device per-instance softstate 192 */ 193 typedef struct xdf { 194 dev_info_t *xdf_dip; 195 domid_t xdf_peer; /* otherend's dom ID */ 196 xendev_ring_t *xdf_xb_ring; /* I/O ring buffer */ 197 ddi_acc_handle_t xdf_xb_ring_hdl; /* access handler for ring buffer */ 198 list_t xdf_vreq_act; /* active vreq list */ 199 list_t xdf_gs_act; /* active grant table slot list */ 200 buf_t *xdf_f_act; /* active buf list head */ 201 buf_t *xdf_l_act; /* active buf list tail */ 202 enum xdf_state xdf_status; /* status of this virtual disk */ 203 ulong_t xdf_vd_open[OTYPCNT]; 204 ulong_t xdf_vd_lyropen[XDF_PEXT]; 205 ulong_t xdf_vd_exclopen; 206 kmutex_t xdf_dev_lk; /* mutex lock for I/O path */ 207 kmutex_t xdf_cb_lk; /* mutex lock for event handling path */ 208 kcondvar_t xdf_dev_cv; /* cv used in I/O path */ 209 uint_t xdf_xdev_info; /* disk info from backend xenstore */ 210 diskaddr_t xdf_xdev_nblocks; /* total size in block */ 211 kstat_t *xdf_xdev_iostat; 212 cmlb_handle_t xdf_vd_lbl; 213 ddi_softintr_t xdf_softintr_id; 214 timeout_id_t xdf_timeout_id; 215 struct gnttab_free_callback xdf_gnt_callback; 216 int xdf_feature_barrier; 217 int xdf_flush_supported; 218 int xdf_wce; 219 char *xdf_flush_mem; 220 char *xdf_cache_flush_block; 221 #ifdef DEBUG 222 int xdf_dmacallback_num; 223 #endif 224 } xdf_t; 225 226 #define BP2VREQ(bp) ((v_req_t *)((bp)->av_back)) 227 228 /* 229 * VBD I/O requests must be aligned on a 512-byte boundary and specify 230 * a transfer size which is a mutiple of 512-bytes 231 */ 232 #define ALIGNED_XFER(bp) \ 233 ((((uintptr_t)((bp)->b_un.b_addr) & XB_BMASK) == 0) && \ 234 (((bp)->b_bcount & XB_BMASK) == 0)) 235 236 #define U_INVAL(u) (((u)->uio_loffset & (offset_t)(XB_BMASK)) || \ 237 ((u)->uio_iov->iov_len & (offset_t)(XB_BMASK))) 238 239 /* wrap pa_to_ma() for xdf to run in dom0 */ 240 #define PATOMA(addr) (DOMAIN_IS_INITDOMAIN(xen_info) ? addr : pa_to_ma(addr)) 241 242 #define XD_IS_RO(vbd) ((vbd)->xdf_xdev_info & VDISK_READONLY) 243 #define XD_IS_CD(vbd) ((vbd)->xdf_xdev_info & VDISK_CDROM) 244 #define XD_IS_RM(vbd) ((vbd)->xdf_xdev_info & VDISK_REMOVABLE) 245 #define IS_READ(bp) ((bp)->b_flags & B_READ) 246 #define IS_ERROR(bp) ((bp)->b_flags & B_ERROR) 247 248 #define XDF_UPDATE_IO_STAT(vdp, bp) \ 249 if ((vdp)->xdf_xdev_iostat != NULL) { \ 250 kstat_io_t *kip = KSTAT_IO_PTR((vdp)->xdf_xdev_iostat); \ 251 size_t n_done = (bp)->b_bcount - (bp)->b_resid; \ 252 if ((bp)->b_flags & B_READ) { \ 253 kip->reads++; \ 254 kip->nread += n_done; \ 255 } else { \ 256 kip->writes++; \ 257 kip->nwritten += n_done; \ 258 } \ 259 } 260 261 extern int xdfdebug; 262 #ifdef DEBUG 263 #define DPRINTF(flag, args) {if (xdfdebug & (flag)) prom_printf args; } 264 #define SETDMACBON(vbd) {(vbd)->xdf_dmacallback_num++; } 265 #define SETDMACBOFF(vbd) {(vbd)->xdf_dmacallback_num--; } 266 #define ISDMACBON(vbd) ((vbd)->xdf_dmacallback_num > 0) 267 #else 268 #define DPRINTF(flag, args) 269 #define SETDMACBON(vbd) 270 #define SETDMACBOFF(vbd) 271 #define ISDMACBON(vbd) 272 #endif /* DEBUG */ 273 274 #define DDI_DBG 0x1 275 #define DMA_DBG 0x2 276 #define INTR_DBG 0x8 277 #define IO_DBG 0x10 278 #define IOCTL_DBG 0x20 279 #define SUSRES_DBG 0x40 280 #define LBL_DBG 0x80 281 282 #ifdef __cplusplus 283 } 284 #endif 285 286 #endif /* _SYS_XDF_H */ 287