189e0f4d2SKip Macy /* 29999d2cbSKip Macy * XenBSD block device driver 39999d2cbSKip Macy * 4*33eebb6aSJustin T. Gibbs * Copyright (c) 2010-2013 Spectra Logic Corporation 5e4808c4bSKip Macy * Copyright (c) 2009 Scott Long, Yahoo! 69999d2cbSKip Macy * Copyright (c) 2009 Frank Suchomel, Citrix 79999d2cbSKip Macy * Copyright (c) 2009 Doug F. Rabson, Citrix 89999d2cbSKip Macy * Copyright (c) 2005 Kip Macy 99999d2cbSKip Macy * Copyright (c) 2003-2004, Keir Fraser & Steve Hand 109999d2cbSKip Macy * Modifications by Mark A. Williamson are (c) Intel Research Cambridge 119999d2cbSKip Macy * 129999d2cbSKip Macy * 139999d2cbSKip Macy * Permission is hereby granted, free of charge, to any person obtaining a copy 149999d2cbSKip Macy * of this software and associated documentation files (the "Software"), to 159999d2cbSKip Macy * deal in the Software without restriction, including without limitation the 169999d2cbSKip Macy * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 179999d2cbSKip Macy * sell copies of the Software, and to permit persons to whom the Software is 189999d2cbSKip Macy * furnished to do so, subject to the following conditions: 199999d2cbSKip Macy * 209999d2cbSKip Macy * The above copyright notice and this permission notice shall be included in 219999d2cbSKip Macy * all copies or substantial portions of the Software. 2289e0f4d2SKip Macy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2389e0f4d2SKip Macy * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2489e0f4d2SKip Macy * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2589e0f4d2SKip Macy * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2689e0f4d2SKip Macy * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27e4808c4bSKip Macy * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28e4808c4bSKip Macy * DEALINGS IN THE SOFTWARE. 2989e0f4d2SKip Macy * 3089e0f4d2SKip Macy * $FreeBSD$ 3189e0f4d2SKip Macy */ 3289e0f4d2SKip Macy 3389e0f4d2SKip Macy 34*33eebb6aSJustin T. Gibbs #ifndef __XEN_BLKFRONT_BLOCK_H__ 35*33eebb6aSJustin T. Gibbs #define __XEN_BLKFRONT_BLOCK_H__ 36ff662b5cSJustin T. Gibbs #include <xen/blkif.h> 37ff662b5cSJustin T. Gibbs 38ff662b5cSJustin T. Gibbs /** 39443cc4d4SJustin T. Gibbs * Given a number of blkif segments, compute the maximum I/O size supported. 40443cc4d4SJustin T. Gibbs * 41443cc4d4SJustin T. Gibbs * \note This calculation assumes that all but the first and last segments 42443cc4d4SJustin T. Gibbs * of the I/O are fully utilized. 43443cc4d4SJustin T. Gibbs * 44443cc4d4SJustin T. Gibbs * \note We reserve a segement from the maximum supported by the transport to 45443cc4d4SJustin T. Gibbs * guarantee we can handle an unaligned transfer without the need to 46443cc4d4SJustin T. Gibbs * use a bounce buffer. 47443cc4d4SJustin T. Gibbs */ 48*33eebb6aSJustin T. Gibbs #define XBD_SEGS_TO_SIZE(segs) \ 49443cc4d4SJustin T. Gibbs (((segs) - 1) * PAGE_SIZE) 50443cc4d4SJustin T. Gibbs 51443cc4d4SJustin T. Gibbs /** 52443cc4d4SJustin T. Gibbs * Compute the maximum number of blkif segments requried to represent 53443cc4d4SJustin T. Gibbs * an I/O of the given size. 54443cc4d4SJustin T. Gibbs * 55443cc4d4SJustin T. Gibbs * \note This calculation assumes that all but the first and last segments 56443cc4d4SJustin T. Gibbs * of the I/O are fully utilized. 57443cc4d4SJustin T. Gibbs * 58443cc4d4SJustin T. Gibbs * \note We reserve a segement to guarantee we can handle an unaligned 59443cc4d4SJustin T. Gibbs * transfer without the need to use a bounce buffer. 60443cc4d4SJustin T. Gibbs */ 61*33eebb6aSJustin T. Gibbs #define XBD_SIZE_TO_SEGS(size) \ 62443cc4d4SJustin T. Gibbs ((size / PAGE_SIZE) + 1) 63443cc4d4SJustin T. Gibbs 64443cc4d4SJustin T. Gibbs /** 65ff662b5cSJustin T. Gibbs * The maximum number of outstanding requests blocks (request headers plus 66ff662b5cSJustin T. Gibbs * additional segment blocks) we will allow in a negotiated block-front/back 67ff662b5cSJustin T. Gibbs * communication channel. 68ff662b5cSJustin T. Gibbs */ 69*33eebb6aSJustin T. Gibbs #define XBD_MAX_REQUESTS 256 70ff662b5cSJustin T. Gibbs 71ff662b5cSJustin T. Gibbs /** 72ff662b5cSJustin T. Gibbs * The maximum mapped region size per request we will allow in a negotiated 73ff662b5cSJustin T. Gibbs * block-front/back communication channel. 74ff662b5cSJustin T. Gibbs */ 75*33eebb6aSJustin T. Gibbs #define XBD_MAX_REQUEST_SIZE \ 76*33eebb6aSJustin T. Gibbs MIN(MAXPHYS, XBD_SEGS_TO_SIZE(BLKIF_MAX_SEGMENTS_PER_REQUEST)) 77ff662b5cSJustin T. Gibbs 78ff662b5cSJustin T. Gibbs /** 79ff662b5cSJustin T. Gibbs * The maximum number of segments (within a request header and accompanying 80ff662b5cSJustin T. Gibbs * segment blocks) per request we will allow in a negotiated block-front/back 81ff662b5cSJustin T. Gibbs * communication channel. 82ff662b5cSJustin T. Gibbs */ 83*33eebb6aSJustin T. Gibbs #define XBD_MAX_SEGMENTS_PER_REQUEST \ 84ff662b5cSJustin T. Gibbs (MIN(BLKIF_MAX_SEGMENTS_PER_REQUEST, \ 85*33eebb6aSJustin T. Gibbs XBD_SIZE_TO_SEGS(XBD_MAX_REQUEST_SIZE))) 86ff662b5cSJustin T. Gibbs 87ff662b5cSJustin T. Gibbs /** 88ff662b5cSJustin T. Gibbs * The maximum number of shared memory ring pages we will allow in a 89ff662b5cSJustin T. Gibbs * negotiated block-front/back communication channel. Allow enough 90*33eebb6aSJustin T. Gibbs * ring space for all requests to be XBD_MAX_REQUEST_SIZE'd. 91ff662b5cSJustin T. Gibbs */ 92*33eebb6aSJustin T. Gibbs #define XBD_MAX_RING_PAGES \ 93*33eebb6aSJustin T. Gibbs BLKIF_RING_PAGES(BLKIF_SEGS_TO_BLOCKS(XBD_MAX_SEGMENTS_PER_REQUEST) \ 94*33eebb6aSJustin T. Gibbs * XBD_MAX_REQUESTS) 9589e0f4d2SKip Macy 96*33eebb6aSJustin T. Gibbs struct xbd_command; 97*33eebb6aSJustin T. Gibbs typedef void xbd_cbcf_t(struct xbd_command *); 9889e0f4d2SKip Macy 99*33eebb6aSJustin T. Gibbs struct xbd_command { 100*33eebb6aSJustin T. Gibbs TAILQ_ENTRY(xbd_command) cm_link; 101*33eebb6aSJustin T. Gibbs struct xbd_softc *cm_sc; 102e4808c4bSKip Macy u_int cm_flags; 103*33eebb6aSJustin T. Gibbs #define XBD_CMD_FROZEN (1<<0) 104*33eebb6aSJustin T. Gibbs #define XBD_CMD_POLLED (1<<1) 105*33eebb6aSJustin T. Gibbs #define XBD_ON_XBDQ_FREE (1<<2) 106*33eebb6aSJustin T. Gibbs #define XBD_ON_XBDQ_READY (1<<3) 107*33eebb6aSJustin T. Gibbs #define XBD_ON_XBDQ_BUSY (1<<4) 108*33eebb6aSJustin T. Gibbs #define XBD_ON_XBDQ_COMPLETE (1<<5) 109*33eebb6aSJustin T. Gibbs #define XBD_ON_XBDQ_MASK ((1<<2)|(1<<3)|(1<<4)|(1<<5)) 110*33eebb6aSJustin T. Gibbs bus_dmamap_t cm_map; 111*33eebb6aSJustin T. Gibbs uint64_t cm_id; 112*33eebb6aSJustin T. Gibbs grant_ref_t *cm_sg_refs; 113*33eebb6aSJustin T. Gibbs struct bio *cm_bp; 114*33eebb6aSJustin T. Gibbs grant_ref_t cm_gref_head; 115*33eebb6aSJustin T. Gibbs void *cm_data; 116*33eebb6aSJustin T. Gibbs size_t cm_datalen; 117*33eebb6aSJustin T. Gibbs u_int cm_nseg; 118*33eebb6aSJustin T. Gibbs int cm_operation; 119*33eebb6aSJustin T. Gibbs blkif_sector_t cm_sector_number; 120*33eebb6aSJustin T. Gibbs int cm_status; 121*33eebb6aSJustin T. Gibbs xbd_cbcf_t *cm_complete; 12289e0f4d2SKip Macy }; 12389e0f4d2SKip Macy 124*33eebb6aSJustin T. Gibbs #define XBDQ_FREE 0 125*33eebb6aSJustin T. Gibbs #define XBDQ_BIO 1 126*33eebb6aSJustin T. Gibbs #define XBDQ_READY 2 127*33eebb6aSJustin T. Gibbs #define XBDQ_BUSY 3 128*33eebb6aSJustin T. Gibbs #define XBDQ_COMPLETE 4 129*33eebb6aSJustin T. Gibbs #define XBDQ_COUNT 5 13089e0f4d2SKip Macy 131*33eebb6aSJustin T. Gibbs struct xbd_qstat { 132e4808c4bSKip Macy uint32_t q_length; 133e4808c4bSKip Macy uint32_t q_max; 134e4808c4bSKip Macy }; 135e4808c4bSKip Macy 136*33eebb6aSJustin T. Gibbs union xbd_statrequest { 137e4808c4bSKip Macy uint32_t ms_item; 138*33eebb6aSJustin T. Gibbs struct xbd_qstat ms_qstat; 139e4808c4bSKip Macy }; 140e4808c4bSKip Macy 141e4808c4bSKip Macy /* 142e4808c4bSKip Macy * We have one of these per vbd, whether ide, scsi or 'other'. 143e4808c4bSKip Macy */ 144*33eebb6aSJustin T. Gibbs struct xbd_softc { 145*33eebb6aSJustin T. Gibbs device_t xbd_dev; 146*33eebb6aSJustin T. Gibbs struct disk *xbd_disk; /* disk params */ 147*33eebb6aSJustin T. Gibbs struct bio_queue_head xbd_bioq; /* sort queue */ 148*33eebb6aSJustin T. Gibbs int xbd_unit; 149*33eebb6aSJustin T. Gibbs int xbd_flags; 150*33eebb6aSJustin T. Gibbs #define XBD_OPEN (1<<0) /* drive is open (can't shut down) */ 151*33eebb6aSJustin T. Gibbs #define XBD_BARRIER (1 << 1) /* backend supports barriers */ 152*33eebb6aSJustin T. Gibbs #define XBD_READY (1 << 2) /* Is ready */ 153*33eebb6aSJustin T. Gibbs #define XBD_FROZEN (1 << 3) /* Waiting for resources */ 154*33eebb6aSJustin T. Gibbs int xbd_vdevice; 155*33eebb6aSJustin T. Gibbs int xbd_connected; 156*33eebb6aSJustin T. Gibbs u_int xbd_ring_pages; 157*33eebb6aSJustin T. Gibbs uint32_t xbd_max_requests; 158*33eebb6aSJustin T. Gibbs uint32_t xbd_max_request_segments; 159*33eebb6aSJustin T. Gibbs uint32_t xbd_max_request_blocks; 160*33eebb6aSJustin T. Gibbs uint32_t xbd_max_request_size; 161*33eebb6aSJustin T. Gibbs grant_ref_t xbd_ring_ref[XBD_MAX_RING_PAGES]; 162*33eebb6aSJustin T. Gibbs blkif_front_ring_t xbd_ring; 163*33eebb6aSJustin T. Gibbs unsigned int xbd_irq; 164*33eebb6aSJustin T. Gibbs struct gnttab_free_callback xbd_callback; 165*33eebb6aSJustin T. Gibbs TAILQ_HEAD(,xbd_command) xbd_cm_free; 166*33eebb6aSJustin T. Gibbs TAILQ_HEAD(,xbd_command) xbd_cm_ready; 167*33eebb6aSJustin T. Gibbs TAILQ_HEAD(,xbd_command) xbd_cm_busy; 168*33eebb6aSJustin T. Gibbs TAILQ_HEAD(,xbd_command) xbd_cm_complete; 169*33eebb6aSJustin T. Gibbs struct xbd_qstat xbd_qstat[XBDQ_COUNT]; 170*33eebb6aSJustin T. Gibbs bus_dma_tag_t xbd_io_dmat; 171e4808c4bSKip Macy 17289e0f4d2SKip Macy /** 17389e0f4d2SKip Macy * The number of people holding this device open. We won't allow a 17489e0f4d2SKip Macy * hot-unplug unless this is 0. 17589e0f4d2SKip Macy */ 176*33eebb6aSJustin T. Gibbs int xbd_users; 177*33eebb6aSJustin T. Gibbs struct mtx xbd_io_lock; 178ff662b5cSJustin T. Gibbs 179*33eebb6aSJustin T. Gibbs struct xbd_command *xbd_shadow; 18089e0f4d2SKip Macy }; 181e4808c4bSKip Macy 182*33eebb6aSJustin T. Gibbs int xbd_instance_create(struct xbd_softc *, blkif_sector_t sectors, int device, 183ff662b5cSJustin T. Gibbs uint16_t vdisk_info, unsigned long sector_size); 184e4808c4bSKip Macy 185*33eebb6aSJustin T. Gibbs #define XBDQ_ADD(sc, qname) \ 186e4808c4bSKip Macy do { \ 187*33eebb6aSJustin T. Gibbs struct xbd_qstat *qs; \ 188e4808c4bSKip Macy \ 189*33eebb6aSJustin T. Gibbs qs = &(sc)->xbd_qstat[qname]; \ 190e4808c4bSKip Macy qs->q_length++; \ 191e4808c4bSKip Macy if (qs->q_length > qs->q_max) \ 192e4808c4bSKip Macy qs->q_max = qs->q_length; \ 193e4808c4bSKip Macy } while (0) 194e4808c4bSKip Macy 195*33eebb6aSJustin T. Gibbs #define XBDQ_REMOVE(sc, qname) (sc)->xbd_qstat[qname].q_length-- 196e4808c4bSKip Macy 197*33eebb6aSJustin T. Gibbs #define XBDQ_INIT(sc, qname) \ 198e4808c4bSKip Macy do { \ 199*33eebb6aSJustin T. Gibbs sc->xbd_qstat[qname].q_length = 0; \ 200*33eebb6aSJustin T. Gibbs sc->xbd_qstat[qname].q_max = 0; \ 201e4808c4bSKip Macy } while (0) 202e4808c4bSKip Macy 203*33eebb6aSJustin T. Gibbs #define XBDQ_COMMAND_QUEUE(name, index) \ 204e4808c4bSKip Macy static __inline void \ 205*33eebb6aSJustin T. Gibbs xbd_initq_ ## name (struct xbd_softc *sc) \ 206e4808c4bSKip Macy { \ 207*33eebb6aSJustin T. Gibbs TAILQ_INIT(&sc->xbd_cm_ ## name); \ 208*33eebb6aSJustin T. Gibbs XBDQ_INIT(sc, index); \ 209e4808c4bSKip Macy } \ 210e4808c4bSKip Macy static __inline void \ 211*33eebb6aSJustin T. Gibbs xbd_enqueue_ ## name (struct xbd_command *cm) \ 212e4808c4bSKip Macy { \ 213*33eebb6aSJustin T. Gibbs if ((cm->cm_flags & XBD_ON_XBDQ_MASK) != 0) { \ 214e4808c4bSKip Macy printf("command %p is on another queue, " \ 215e4808c4bSKip Macy "flags = %#x\n", cm, cm->cm_flags); \ 216e4808c4bSKip Macy panic("command is on another queue"); \ 217e4808c4bSKip Macy } \ 218*33eebb6aSJustin T. Gibbs TAILQ_INSERT_TAIL(&cm->cm_sc->xbd_cm_ ## name, cm, cm_link); \ 219*33eebb6aSJustin T. Gibbs cm->cm_flags |= XBD_ON_ ## index; \ 220*33eebb6aSJustin T. Gibbs XBDQ_ADD(cm->cm_sc, index); \ 221e4808c4bSKip Macy } \ 222e4808c4bSKip Macy static __inline void \ 223*33eebb6aSJustin T. Gibbs xbd_requeue_ ## name (struct xbd_command *cm) \ 224e4808c4bSKip Macy { \ 225*33eebb6aSJustin T. Gibbs if ((cm->cm_flags & XBD_ON_XBDQ_MASK) != 0) { \ 226e4808c4bSKip Macy printf("command %p is on another queue, " \ 227e4808c4bSKip Macy "flags = %#x\n", cm, cm->cm_flags); \ 228e4808c4bSKip Macy panic("command is on another queue"); \ 229e4808c4bSKip Macy } \ 230*33eebb6aSJustin T. Gibbs TAILQ_INSERT_HEAD(&cm->cm_sc->xbd_cm_ ## name, cm, cm_link); \ 231*33eebb6aSJustin T. Gibbs cm->cm_flags |= XBD_ON_ ## index; \ 232*33eebb6aSJustin T. Gibbs XBDQ_ADD(cm->cm_sc, index); \ 233e4808c4bSKip Macy } \ 234*33eebb6aSJustin T. Gibbs static __inline struct xbd_command * \ 235*33eebb6aSJustin T. Gibbs xbd_dequeue_ ## name (struct xbd_softc *sc) \ 236e4808c4bSKip Macy { \ 237*33eebb6aSJustin T. Gibbs struct xbd_command *cm; \ 238e4808c4bSKip Macy \ 239*33eebb6aSJustin T. Gibbs if ((cm = TAILQ_FIRST(&sc->xbd_cm_ ## name)) != NULL) { \ 240*33eebb6aSJustin T. Gibbs if ((cm->cm_flags & XBD_ON_XBDQ_MASK) != \ 241*33eebb6aSJustin T. Gibbs XBD_ON_ ## index) { \ 242e4808c4bSKip Macy printf("command %p not in queue, " \ 243e4808c4bSKip Macy "flags = %#x, bit = %#x\n", cm, \ 244*33eebb6aSJustin T. Gibbs cm->cm_flags, XBD_ON_ ## index); \ 245e4808c4bSKip Macy panic("command not in queue"); \ 246e4808c4bSKip Macy } \ 247*33eebb6aSJustin T. Gibbs TAILQ_REMOVE(&sc->xbd_cm_ ## name, cm, cm_link);\ 248*33eebb6aSJustin T. Gibbs cm->cm_flags &= ~XBD_ON_ ## index; \ 249*33eebb6aSJustin T. Gibbs XBDQ_REMOVE(sc, index); \ 250e4808c4bSKip Macy } \ 251e4808c4bSKip Macy return (cm); \ 252e4808c4bSKip Macy } \ 253e4808c4bSKip Macy static __inline void \ 254*33eebb6aSJustin T. Gibbs xbd_remove_ ## name (struct xbd_command *cm) \ 255e4808c4bSKip Macy { \ 256*33eebb6aSJustin T. Gibbs if ((cm->cm_flags & XBD_ON_XBDQ_MASK) != XBD_ON_ ## index){\ 257e4808c4bSKip Macy printf("command %p not in queue, flags = %#x, " \ 258e4808c4bSKip Macy "bit = %#x\n", cm, cm->cm_flags, \ 259*33eebb6aSJustin T. Gibbs XBD_ON_ ## index); \ 260e4808c4bSKip Macy panic("command not in queue"); \ 261e4808c4bSKip Macy } \ 262*33eebb6aSJustin T. Gibbs TAILQ_REMOVE(&cm->cm_sc->xbd_cm_ ## name, cm, cm_link); \ 263*33eebb6aSJustin T. Gibbs cm->cm_flags &= ~XBD_ON_ ## index; \ 264*33eebb6aSJustin T. Gibbs XBDQ_REMOVE(cm->cm_sc, index); \ 265e4808c4bSKip Macy } \ 266e4808c4bSKip Macy struct hack 267e4808c4bSKip Macy 268*33eebb6aSJustin T. Gibbs XBDQ_COMMAND_QUEUE(free, XBDQ_FREE); 269*33eebb6aSJustin T. Gibbs XBDQ_COMMAND_QUEUE(ready, XBDQ_READY); 270*33eebb6aSJustin T. Gibbs XBDQ_COMMAND_QUEUE(busy, XBDQ_BUSY); 271*33eebb6aSJustin T. Gibbs XBDQ_COMMAND_QUEUE(complete, XBDQ_COMPLETE); 272e4808c4bSKip Macy 273e4808c4bSKip Macy static __inline void 274*33eebb6aSJustin T. Gibbs xbd_initq_bio(struct xbd_softc *sc) 275e4808c4bSKip Macy { 276*33eebb6aSJustin T. Gibbs bioq_init(&sc->xbd_bioq); 277*33eebb6aSJustin T. Gibbs XBDQ_INIT(sc, XBDQ_BIO); 278e4808c4bSKip Macy } 279e4808c4bSKip Macy 280e4808c4bSKip Macy static __inline void 281*33eebb6aSJustin T. Gibbs xbd_enqueue_bio(struct xbd_softc *sc, struct bio *bp) 282e4808c4bSKip Macy { 283*33eebb6aSJustin T. Gibbs bioq_insert_tail(&sc->xbd_bioq, bp); 284*33eebb6aSJustin T. Gibbs XBDQ_ADD(sc, XBDQ_BIO); 285e4808c4bSKip Macy } 286e4808c4bSKip Macy 287e4808c4bSKip Macy static __inline void 288*33eebb6aSJustin T. Gibbs xbd_requeue_bio(struct xbd_softc *sc, struct bio *bp) 289e4808c4bSKip Macy { 290*33eebb6aSJustin T. Gibbs bioq_insert_head(&sc->xbd_bioq, bp); 291*33eebb6aSJustin T. Gibbs XBDQ_ADD(sc, XBDQ_BIO); 292e4808c4bSKip Macy } 293e4808c4bSKip Macy 294e4808c4bSKip Macy static __inline struct bio * 295*33eebb6aSJustin T. Gibbs xbd_dequeue_bio(struct xbd_softc *sc) 296e4808c4bSKip Macy { 297e4808c4bSKip Macy struct bio *bp; 298e4808c4bSKip Macy 299*33eebb6aSJustin T. Gibbs if ((bp = bioq_first(&sc->xbd_bioq)) != NULL) { 300*33eebb6aSJustin T. Gibbs bioq_remove(&sc->xbd_bioq, bp); 301*33eebb6aSJustin T. Gibbs XBDQ_REMOVE(sc, XBDQ_BIO); 302e4808c4bSKip Macy } 303e4808c4bSKip Macy return (bp); 304e4808c4bSKip Macy } 30589e0f4d2SKip Macy 306*33eebb6aSJustin T. Gibbs #endif /* __XEN_BLKFRONT_BLOCK_H__ */ 307