189e0f4d2SKip Macy /* 29999d2cbSKip Macy * XenBSD block device driver 39999d2cbSKip Macy * 4e4808c4bSKip Macy * Copyright (c) 2009 Scott Long, Yahoo! 59999d2cbSKip Macy * Copyright (c) 2009 Frank Suchomel, Citrix 69999d2cbSKip Macy * Copyright (c) 2009 Doug F. Rabson, Citrix 79999d2cbSKip Macy * Copyright (c) 2005 Kip Macy 89999d2cbSKip Macy * Copyright (c) 2003-2004, Keir Fraser & Steve Hand 99999d2cbSKip Macy * Modifications by Mark A. Williamson are (c) Intel Research Cambridge 109999d2cbSKip Macy * 119999d2cbSKip Macy * 129999d2cbSKip Macy * Permission is hereby granted, free of charge, to any person obtaining a copy 139999d2cbSKip Macy * of this software and associated documentation files (the "Software"), to 149999d2cbSKip Macy * deal in the Software without restriction, including without limitation the 159999d2cbSKip Macy * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 169999d2cbSKip Macy * sell copies of the Software, and to permit persons to whom the Software is 179999d2cbSKip Macy * furnished to do so, subject to the following conditions: 189999d2cbSKip Macy * 199999d2cbSKip Macy * The above copyright notice and this permission notice shall be included in 209999d2cbSKip Macy * all copies or substantial portions of the Software. 2189e0f4d2SKip Macy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2289e0f4d2SKip Macy * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2389e0f4d2SKip Macy * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2489e0f4d2SKip Macy * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2589e0f4d2SKip Macy * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26e4808c4bSKip Macy * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27e4808c4bSKip Macy * DEALINGS IN THE SOFTWARE. 2889e0f4d2SKip Macy * 2989e0f4d2SKip Macy * $FreeBSD$ 3089e0f4d2SKip Macy */ 3189e0f4d2SKip Macy 3289e0f4d2SKip Macy 3389e0f4d2SKip Macy #ifndef __XEN_DRIVERS_BLOCK_H__ 3489e0f4d2SKip Macy #define __XEN_DRIVERS_BLOCK_H__ 35ff662b5cSJustin T. Gibbs #include <xen/blkif.h> 36ff662b5cSJustin T. Gibbs 37ff662b5cSJustin T. Gibbs /** 38*443cc4d4SJustin T. Gibbs * Given a number of blkif segments, compute the maximum I/O size supported. 39*443cc4d4SJustin T. Gibbs * 40*443cc4d4SJustin T. Gibbs * \note This calculation assumes that all but the first and last segments 41*443cc4d4SJustin T. Gibbs * of the I/O are fully utilized. 42*443cc4d4SJustin T. Gibbs * 43*443cc4d4SJustin T. Gibbs * \note We reserve a segement from the maximum supported by the transport to 44*443cc4d4SJustin T. Gibbs * guarantee we can handle an unaligned transfer without the need to 45*443cc4d4SJustin T. Gibbs * use a bounce buffer. 46*443cc4d4SJustin T. Gibbs */ 47*443cc4d4SJustin T. Gibbs #define XBF_SEGS_TO_SIZE(segs) \ 48*443cc4d4SJustin T. Gibbs (((segs) - 1) * PAGE_SIZE) 49*443cc4d4SJustin T. Gibbs 50*443cc4d4SJustin T. Gibbs /** 51*443cc4d4SJustin T. Gibbs * Compute the maximum number of blkif segments requried to represent 52*443cc4d4SJustin T. Gibbs * an I/O of the given size. 53*443cc4d4SJustin T. Gibbs * 54*443cc4d4SJustin T. Gibbs * \note This calculation assumes that all but the first and last segments 55*443cc4d4SJustin T. Gibbs * of the I/O are fully utilized. 56*443cc4d4SJustin T. Gibbs * 57*443cc4d4SJustin T. Gibbs * \note We reserve a segement to guarantee we can handle an unaligned 58*443cc4d4SJustin T. Gibbs * transfer without the need to use a bounce buffer. 59*443cc4d4SJustin T. Gibbs */ 60*443cc4d4SJustin T. Gibbs #define XBF_SIZE_TO_SEGS(size) \ 61*443cc4d4SJustin T. Gibbs ((size / PAGE_SIZE) + 1) 62*443cc4d4SJustin T. Gibbs 63*443cc4d4SJustin T. Gibbs /** 64ff662b5cSJustin T. Gibbs * The maximum number of outstanding requests blocks (request headers plus 65ff662b5cSJustin T. Gibbs * additional segment blocks) we will allow in a negotiated block-front/back 66ff662b5cSJustin T. Gibbs * communication channel. 67ff662b5cSJustin T. Gibbs */ 68ff662b5cSJustin T. Gibbs #define XBF_MAX_REQUESTS 256 69ff662b5cSJustin T. Gibbs 70ff662b5cSJustin T. Gibbs /** 71ff662b5cSJustin T. Gibbs * The maximum mapped region size per request we will allow in a negotiated 72ff662b5cSJustin T. Gibbs * block-front/back communication channel. 73ff662b5cSJustin T. Gibbs */ 74ff662b5cSJustin T. Gibbs #define XBF_MAX_REQUEST_SIZE \ 75*443cc4d4SJustin T. Gibbs MIN(MAXPHYS, XBF_SEGS_TO_SIZE(BLKIF_MAX_SEGMENTS_PER_REQUEST)) 76ff662b5cSJustin T. Gibbs 77ff662b5cSJustin T. Gibbs /** 78ff662b5cSJustin T. Gibbs * The maximum number of segments (within a request header and accompanying 79ff662b5cSJustin T. Gibbs * segment blocks) per request we will allow in a negotiated block-front/back 80ff662b5cSJustin T. Gibbs * communication channel. 81ff662b5cSJustin T. Gibbs */ 82ff662b5cSJustin T. Gibbs #define XBF_MAX_SEGMENTS_PER_REQUEST \ 83ff662b5cSJustin T. Gibbs (MIN(BLKIF_MAX_SEGMENTS_PER_REQUEST, \ 84*443cc4d4SJustin T. Gibbs XBF_SIZE_TO_SEGS(XBF_MAX_REQUEST_SIZE))) 85ff662b5cSJustin T. Gibbs 86ff662b5cSJustin T. Gibbs /** 87ff662b5cSJustin T. Gibbs * The maximum number of shared memory ring pages we will allow in a 88ff662b5cSJustin T. Gibbs * negotiated block-front/back communication channel. Allow enough 89ff662b5cSJustin T. Gibbs * ring space for all requests to be XBF_MAX_REQUEST_SIZE'd. 90ff662b5cSJustin T. Gibbs */ 91ff662b5cSJustin T. Gibbs #define XBF_MAX_RING_PAGES \ 92ff662b5cSJustin T. Gibbs BLKIF_RING_PAGES(BLKIF_SEGS_TO_BLOCKS(XBF_MAX_SEGMENTS_PER_REQUEST) \ 93ff662b5cSJustin T. Gibbs * XBF_MAX_REQUESTS) 9489e0f4d2SKip Macy 9589e0f4d2SKip Macy struct xlbd_type_info 9689e0f4d2SKip Macy { 9789e0f4d2SKip Macy int partn_shift; 9889e0f4d2SKip Macy int disks_per_major; 9989e0f4d2SKip Macy char *devname; 10089e0f4d2SKip Macy char *diskname; 10189e0f4d2SKip Macy }; 10289e0f4d2SKip Macy 10389e0f4d2SKip Macy struct xlbd_major_info 10489e0f4d2SKip Macy { 10589e0f4d2SKip Macy int major; 10689e0f4d2SKip Macy int index; 10789e0f4d2SKip Macy int usage; 10889e0f4d2SKip Macy struct xlbd_type_info *type; 10989e0f4d2SKip Macy }; 11089e0f4d2SKip Macy 111e4808c4bSKip Macy struct xb_command { 112e4808c4bSKip Macy TAILQ_ENTRY(xb_command) cm_link; 113e4808c4bSKip Macy struct xb_softc *cm_sc; 114e4808c4bSKip Macy u_int cm_flags; 115e4808c4bSKip Macy #define XB_CMD_FROZEN (1<<0) 116e4808c4bSKip Macy #define XB_CMD_POLLED (1<<1) 117e4808c4bSKip Macy #define XB_ON_XBQ_FREE (1<<2) 118e4808c4bSKip Macy #define XB_ON_XBQ_READY (1<<3) 119e4808c4bSKip Macy #define XB_ON_XBQ_BUSY (1<<4) 120e4808c4bSKip Macy #define XB_ON_XBQ_COMPLETE (1<<5) 121e4808c4bSKip Macy #define XB_ON_XBQ_MASK ((1<<2)|(1<<3)|(1<<4)|(1<<5)) 122e4808c4bSKip Macy bus_dmamap_t map; 123ff662b5cSJustin T. Gibbs uint64_t id; 124ff662b5cSJustin T. Gibbs grant_ref_t *sg_refs; 125e4808c4bSKip Macy struct bio *bp; 126e4808c4bSKip Macy grant_ref_t gref_head; 127e4808c4bSKip Macy void *data; 128e4808c4bSKip Macy size_t datalen; 129ff662b5cSJustin T. Gibbs u_int nseg; 130e4808c4bSKip Macy int operation; 131e4808c4bSKip Macy blkif_sector_t sector_number; 132e4808c4bSKip Macy int status; 133e4808c4bSKip Macy void (* cm_complete)(struct xb_command *); 13489e0f4d2SKip Macy }; 13589e0f4d2SKip Macy 136e4808c4bSKip Macy #define XBQ_FREE 0 137e4808c4bSKip Macy #define XBQ_BIO 1 138e4808c4bSKip Macy #define XBQ_READY 2 139e4808c4bSKip Macy #define XBQ_BUSY 3 140e4808c4bSKip Macy #define XBQ_COMPLETE 4 141e4808c4bSKip Macy #define XBQ_COUNT 5 14289e0f4d2SKip Macy 143e4808c4bSKip Macy struct xb_qstat { 144e4808c4bSKip Macy uint32_t q_length; 145e4808c4bSKip Macy uint32_t q_max; 146e4808c4bSKip Macy }; 147e4808c4bSKip Macy 148e4808c4bSKip Macy union xb_statrequest { 149e4808c4bSKip Macy uint32_t ms_item; 150e4808c4bSKip Macy struct xb_qstat ms_qstat; 151e4808c4bSKip Macy }; 152e4808c4bSKip Macy 153e4808c4bSKip Macy /* 154e4808c4bSKip Macy * We have one of these per vbd, whether ide, scsi or 'other'. 155e4808c4bSKip Macy */ 15689e0f4d2SKip Macy struct xb_softc { 15789e0f4d2SKip Macy device_t xb_dev; 15889e0f4d2SKip Macy struct disk *xb_disk; /* disk params */ 15989e0f4d2SKip Macy struct bio_queue_head xb_bioq; /* sort queue */ 16089e0f4d2SKip Macy int xb_unit; 16189e0f4d2SKip Macy int xb_flags; 16289e0f4d2SKip Macy #define XB_OPEN (1<<0) /* drive is open (can't shut down) */ 163e4808c4bSKip Macy #define XB_BARRIER (1 << 1) /* backend supports barriers */ 164e4808c4bSKip Macy #define XB_READY (1 << 2) /* Is ready */ 165e4808c4bSKip Macy #define XB_FROZEN (1 << 3) /* Waiting for resources */ 16689e0f4d2SKip Macy int vdevice; 16789e0f4d2SKip Macy int connected; 168ff662b5cSJustin T. Gibbs u_int ring_pages; 169ff662b5cSJustin T. Gibbs uint32_t max_requests; 170ff662b5cSJustin T. Gibbs uint32_t max_request_segments; 171ff662b5cSJustin T. Gibbs uint32_t max_request_blocks; 172ff662b5cSJustin T. Gibbs uint32_t max_request_size; 173ff662b5cSJustin T. Gibbs grant_ref_t ring_ref[XBF_MAX_RING_PAGES]; 17489e0f4d2SKip Macy blkif_front_ring_t ring; 17589e0f4d2SKip Macy unsigned int irq; 17689e0f4d2SKip Macy struct gnttab_free_callback callback; 177e4808c4bSKip Macy TAILQ_HEAD(,xb_command) cm_free; 178e4808c4bSKip Macy TAILQ_HEAD(,xb_command) cm_ready; 179e4808c4bSKip Macy TAILQ_HEAD(,xb_command) cm_busy; 180e4808c4bSKip Macy TAILQ_HEAD(,xb_command) cm_complete; 181e4808c4bSKip Macy struct xb_qstat xb_qstat[XBQ_COUNT]; 182e4808c4bSKip Macy bus_dma_tag_t xb_io_dmat; 183e4808c4bSKip Macy 18489e0f4d2SKip Macy /** 18589e0f4d2SKip Macy * The number of people holding this device open. We won't allow a 18689e0f4d2SKip Macy * hot-unplug unless this is 0. 18789e0f4d2SKip Macy */ 18889e0f4d2SKip Macy int users; 189e4808c4bSKip Macy struct mtx xb_io_lock; 190ff662b5cSJustin T. Gibbs 191ff662b5cSJustin T. Gibbs struct xb_command *shadow; 19289e0f4d2SKip Macy }; 193e4808c4bSKip Macy 194ff662b5cSJustin T. Gibbs int xlvbd_add(struct xb_softc *, blkif_sector_t sectors, int device, 195ff662b5cSJustin T. Gibbs uint16_t vdisk_info, unsigned long sector_size); 196e4808c4bSKip Macy void xlvbd_del(struct xb_softc *); 197e4808c4bSKip Macy 198e4808c4bSKip Macy #define XBQ_ADD(sc, qname) \ 199e4808c4bSKip Macy do { \ 200e4808c4bSKip Macy struct xb_qstat *qs; \ 201e4808c4bSKip Macy \ 202e4808c4bSKip Macy qs = &(sc)->xb_qstat[qname]; \ 203e4808c4bSKip Macy qs->q_length++; \ 204e4808c4bSKip Macy if (qs->q_length > qs->q_max) \ 205e4808c4bSKip Macy qs->q_max = qs->q_length; \ 206e4808c4bSKip Macy } while (0) 207e4808c4bSKip Macy 208e4808c4bSKip Macy #define XBQ_REMOVE(sc, qname) (sc)->xb_qstat[qname].q_length-- 209e4808c4bSKip Macy 210e4808c4bSKip Macy #define XBQ_INIT(sc, qname) \ 211e4808c4bSKip Macy do { \ 212e4808c4bSKip Macy sc->xb_qstat[qname].q_length = 0; \ 213e4808c4bSKip Macy sc->xb_qstat[qname].q_max = 0; \ 214e4808c4bSKip Macy } while (0) 215e4808c4bSKip Macy 216e4808c4bSKip Macy #define XBQ_COMMAND_QUEUE(name, index) \ 217e4808c4bSKip Macy static __inline void \ 218e4808c4bSKip Macy xb_initq_ ## name (struct xb_softc *sc) \ 219e4808c4bSKip Macy { \ 220e4808c4bSKip Macy TAILQ_INIT(&sc->cm_ ## name); \ 221e4808c4bSKip Macy XBQ_INIT(sc, index); \ 222e4808c4bSKip Macy } \ 223e4808c4bSKip Macy static __inline void \ 224e4808c4bSKip Macy xb_enqueue_ ## name (struct xb_command *cm) \ 225e4808c4bSKip Macy { \ 226e4808c4bSKip Macy if ((cm->cm_flags & XB_ON_XBQ_MASK) != 0) { \ 227e4808c4bSKip Macy printf("command %p is on another queue, " \ 228e4808c4bSKip Macy "flags = %#x\n", cm, cm->cm_flags); \ 229e4808c4bSKip Macy panic("command is on another queue"); \ 230e4808c4bSKip Macy } \ 231e4808c4bSKip Macy TAILQ_INSERT_TAIL(&cm->cm_sc->cm_ ## name, cm, cm_link); \ 232e4808c4bSKip Macy cm->cm_flags |= XB_ON_ ## index; \ 233e4808c4bSKip Macy XBQ_ADD(cm->cm_sc, index); \ 234e4808c4bSKip Macy } \ 235e4808c4bSKip Macy static __inline void \ 236e4808c4bSKip Macy xb_requeue_ ## name (struct xb_command *cm) \ 237e4808c4bSKip Macy { \ 238e4808c4bSKip Macy if ((cm->cm_flags & XB_ON_XBQ_MASK) != 0) { \ 239e4808c4bSKip Macy printf("command %p is on another queue, " \ 240e4808c4bSKip Macy "flags = %#x\n", cm, cm->cm_flags); \ 241e4808c4bSKip Macy panic("command is on another queue"); \ 242e4808c4bSKip Macy } \ 243e4808c4bSKip Macy TAILQ_INSERT_HEAD(&cm->cm_sc->cm_ ## name, cm, cm_link); \ 244e4808c4bSKip Macy cm->cm_flags |= XB_ON_ ## index; \ 245e4808c4bSKip Macy XBQ_ADD(cm->cm_sc, index); \ 246e4808c4bSKip Macy } \ 247e4808c4bSKip Macy static __inline struct xb_command * \ 248e4808c4bSKip Macy xb_dequeue_ ## name (struct xb_softc *sc) \ 249e4808c4bSKip Macy { \ 250e4808c4bSKip Macy struct xb_command *cm; \ 251e4808c4bSKip Macy \ 252e4808c4bSKip Macy if ((cm = TAILQ_FIRST(&sc->cm_ ## name)) != NULL) { \ 253ff662b5cSJustin T. Gibbs if ((cm->cm_flags & XB_ON_XBQ_MASK) != \ 254ff662b5cSJustin T. Gibbs XB_ON_ ## index) { \ 255e4808c4bSKip Macy printf("command %p not in queue, " \ 256e4808c4bSKip Macy "flags = %#x, bit = %#x\n", cm, \ 257e4808c4bSKip Macy cm->cm_flags, XB_ON_ ## index); \ 258e4808c4bSKip Macy panic("command not in queue"); \ 259e4808c4bSKip Macy } \ 260e4808c4bSKip Macy TAILQ_REMOVE(&sc->cm_ ## name, cm, cm_link); \ 261e4808c4bSKip Macy cm->cm_flags &= ~XB_ON_ ## index; \ 262e4808c4bSKip Macy XBQ_REMOVE(sc, index); \ 263e4808c4bSKip Macy } \ 264e4808c4bSKip Macy return (cm); \ 265e4808c4bSKip Macy } \ 266e4808c4bSKip Macy static __inline void \ 267e4808c4bSKip Macy xb_remove_ ## name (struct xb_command *cm) \ 268e4808c4bSKip Macy { \ 269ff662b5cSJustin T. Gibbs if ((cm->cm_flags & XB_ON_XBQ_MASK) != XB_ON_ ## index){\ 270e4808c4bSKip Macy printf("command %p not in queue, flags = %#x, " \ 271e4808c4bSKip Macy "bit = %#x\n", cm, cm->cm_flags, \ 272e4808c4bSKip Macy XB_ON_ ## index); \ 273e4808c4bSKip Macy panic("command not in queue"); \ 274e4808c4bSKip Macy } \ 275e4808c4bSKip Macy TAILQ_REMOVE(&cm->cm_sc->cm_ ## name, cm, cm_link); \ 276e4808c4bSKip Macy cm->cm_flags &= ~XB_ON_ ## index; \ 277e4808c4bSKip Macy XBQ_REMOVE(cm->cm_sc, index); \ 278e4808c4bSKip Macy } \ 279e4808c4bSKip Macy struct hack 280e4808c4bSKip Macy 281e4808c4bSKip Macy XBQ_COMMAND_QUEUE(free, XBQ_FREE); 282e4808c4bSKip Macy XBQ_COMMAND_QUEUE(ready, XBQ_READY); 283e4808c4bSKip Macy XBQ_COMMAND_QUEUE(busy, XBQ_BUSY); 284e4808c4bSKip Macy XBQ_COMMAND_QUEUE(complete, XBQ_COMPLETE); 285e4808c4bSKip Macy 286e4808c4bSKip Macy static __inline void 287e4808c4bSKip Macy xb_initq_bio(struct xb_softc *sc) 288e4808c4bSKip Macy { 289e4808c4bSKip Macy bioq_init(&sc->xb_bioq); 290e4808c4bSKip Macy XBQ_INIT(sc, XBQ_BIO); 291e4808c4bSKip Macy } 292e4808c4bSKip Macy 293e4808c4bSKip Macy static __inline void 294e4808c4bSKip Macy xb_enqueue_bio(struct xb_softc *sc, struct bio *bp) 295e4808c4bSKip Macy { 296e4808c4bSKip Macy bioq_insert_tail(&sc->xb_bioq, bp); 297e4808c4bSKip Macy XBQ_ADD(sc, XBQ_BIO); 298e4808c4bSKip Macy } 299e4808c4bSKip Macy 300e4808c4bSKip Macy static __inline void 301e4808c4bSKip Macy xb_requeue_bio(struct xb_softc *sc, struct bio *bp) 302e4808c4bSKip Macy { 303e4808c4bSKip Macy bioq_insert_head(&sc->xb_bioq, bp); 304e4808c4bSKip Macy XBQ_ADD(sc, XBQ_BIO); 305e4808c4bSKip Macy } 306e4808c4bSKip Macy 307e4808c4bSKip Macy static __inline struct bio * 308e4808c4bSKip Macy xb_dequeue_bio(struct xb_softc *sc) 309e4808c4bSKip Macy { 310e4808c4bSKip Macy struct bio *bp; 311e4808c4bSKip Macy 312e4808c4bSKip Macy if ((bp = bioq_first(&sc->xb_bioq)) != NULL) { 313e4808c4bSKip Macy bioq_remove(&sc->xb_bioq, bp); 314e4808c4bSKip Macy XBQ_REMOVE(sc, XBQ_BIO); 315e4808c4bSKip Macy } 316e4808c4bSKip Macy return (bp); 317e4808c4bSKip Macy } 31889e0f4d2SKip Macy 31989e0f4d2SKip Macy #endif /* __XEN_DRIVERS_BLOCK_H__ */ 32089e0f4d2SKip Macy 321