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__ 3589e0f4d2SKip Macy #include <xen/interface/io/blkif.h> 3689e0f4d2SKip Macy 3789e0f4d2SKip Macy struct xlbd_type_info 3889e0f4d2SKip Macy { 3989e0f4d2SKip Macy int partn_shift; 4089e0f4d2SKip Macy int disks_per_major; 4189e0f4d2SKip Macy char *devname; 4289e0f4d2SKip Macy char *diskname; 4389e0f4d2SKip Macy }; 4489e0f4d2SKip Macy 4589e0f4d2SKip Macy struct xlbd_major_info 4689e0f4d2SKip Macy { 4789e0f4d2SKip Macy int major; 4889e0f4d2SKip Macy int index; 4989e0f4d2SKip Macy int usage; 5089e0f4d2SKip Macy struct xlbd_type_info *type; 5189e0f4d2SKip Macy }; 5289e0f4d2SKip Macy 53e4808c4bSKip Macy struct xb_command { 54e4808c4bSKip Macy TAILQ_ENTRY(xb_command) cm_link; 55e4808c4bSKip Macy struct xb_softc *cm_sc; 56e4808c4bSKip Macy u_int cm_flags; 57e4808c4bSKip Macy #define XB_CMD_FROZEN (1<<0) 58e4808c4bSKip Macy #define XB_CMD_POLLED (1<<1) 59e4808c4bSKip Macy #define XB_ON_XBQ_FREE (1<<2) 60e4808c4bSKip Macy #define XB_ON_XBQ_READY (1<<3) 61e4808c4bSKip Macy #define XB_ON_XBQ_BUSY (1<<4) 62e4808c4bSKip Macy #define XB_ON_XBQ_COMPLETE (1<<5) 63e4808c4bSKip Macy #define XB_ON_XBQ_MASK ((1<<2)|(1<<3)|(1<<4)|(1<<5)) 64e4808c4bSKip Macy bus_dmamap_t map; 6589e0f4d2SKip Macy blkif_request_t req; 66e4808c4bSKip Macy struct bio *bp; 67e4808c4bSKip Macy grant_ref_t gref_head; 68e4808c4bSKip Macy void *data; 69e4808c4bSKip Macy size_t datalen; 70e4808c4bSKip Macy int operation; 71e4808c4bSKip Macy blkif_sector_t sector_number; 72e4808c4bSKip Macy int status; 73e4808c4bSKip Macy void (* cm_complete)(struct xb_command *); 7489e0f4d2SKip Macy }; 7589e0f4d2SKip Macy 7689e0f4d2SKip Macy #define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE) 7789e0f4d2SKip Macy 78e4808c4bSKip Macy #define XBQ_FREE 0 79e4808c4bSKip Macy #define XBQ_BIO 1 80e4808c4bSKip Macy #define XBQ_READY 2 81e4808c4bSKip Macy #define XBQ_BUSY 3 82e4808c4bSKip Macy #define XBQ_COMPLETE 4 83e4808c4bSKip Macy #define XBQ_COUNT 5 8489e0f4d2SKip Macy 85e4808c4bSKip Macy struct xb_qstat { 86e4808c4bSKip Macy uint32_t q_length; 87e4808c4bSKip Macy uint32_t q_max; 88e4808c4bSKip Macy }; 89e4808c4bSKip Macy 90e4808c4bSKip Macy union xb_statrequest { 91e4808c4bSKip Macy uint32_t ms_item; 92e4808c4bSKip Macy struct xb_qstat ms_qstat; 93e4808c4bSKip Macy }; 94e4808c4bSKip Macy 95e4808c4bSKip Macy /* 96e4808c4bSKip Macy * We have one of these per vbd, whether ide, scsi or 'other'. 97e4808c4bSKip Macy */ 9889e0f4d2SKip Macy struct xb_softc { 9989e0f4d2SKip Macy device_t xb_dev; 10089e0f4d2SKip Macy struct disk *xb_disk; /* disk params */ 10189e0f4d2SKip Macy struct bio_queue_head xb_bioq; /* sort queue */ 10289e0f4d2SKip Macy int xb_unit; 10389e0f4d2SKip Macy int xb_flags; 10489e0f4d2SKip Macy #define XB_OPEN (1<<0) /* drive is open (can't shut down) */ 105e4808c4bSKip Macy #define XB_BARRIER (1 << 1) /* backend supports barriers */ 106e4808c4bSKip Macy #define XB_READY (1 << 2) /* Is ready */ 107e4808c4bSKip Macy #define XB_FROZEN (1 << 3) /* Waiting for resources */ 10889e0f4d2SKip Macy int vdevice; 10989e0f4d2SKip Macy blkif_vdev_t handle; 11089e0f4d2SKip Macy int connected; 11189e0f4d2SKip Macy int ring_ref; 11289e0f4d2SKip Macy blkif_front_ring_t ring; 11389e0f4d2SKip Macy unsigned int irq; 11489e0f4d2SKip Macy struct xlbd_major_info *mi; 11589e0f4d2SKip Macy struct gnttab_free_callback callback; 116e4808c4bSKip Macy TAILQ_HEAD(,xb_command) cm_free; 117e4808c4bSKip Macy TAILQ_HEAD(,xb_command) cm_ready; 118e4808c4bSKip Macy TAILQ_HEAD(,xb_command) cm_busy; 119e4808c4bSKip Macy TAILQ_HEAD(,xb_command) cm_complete; 120e4808c4bSKip Macy struct xb_qstat xb_qstat[XBQ_COUNT]; 121e4808c4bSKip Macy bus_dma_tag_t xb_io_dmat; 122e4808c4bSKip Macy 12389e0f4d2SKip Macy /** 12489e0f4d2SKip Macy * The number of people holding this device open. We won't allow a 12589e0f4d2SKip Macy * hot-unplug unless this is 0. 12689e0f4d2SKip Macy */ 12789e0f4d2SKip Macy int users; 128e4808c4bSKip Macy struct mtx xb_io_lock; 129e4808c4bSKip Macy struct xb_command shadow[BLK_RING_SIZE]; 13089e0f4d2SKip Macy }; 131e4808c4bSKip Macy 132e4808c4bSKip Macy int xlvbd_add(struct xb_softc *, blkif_sector_t capacity, int device, 133e4808c4bSKip Macy uint16_t vdisk_info, uint16_t sector_size); 134e4808c4bSKip Macy void xlvbd_del(struct xb_softc *); 135e4808c4bSKip Macy 136e4808c4bSKip Macy #define XBQ_ADD(sc, qname) \ 137e4808c4bSKip Macy do { \ 138e4808c4bSKip Macy struct xb_qstat *qs; \ 139e4808c4bSKip Macy \ 140e4808c4bSKip Macy qs = &(sc)->xb_qstat[qname]; \ 141e4808c4bSKip Macy qs->q_length++; \ 142e4808c4bSKip Macy if (qs->q_length > qs->q_max) \ 143e4808c4bSKip Macy qs->q_max = qs->q_length; \ 144e4808c4bSKip Macy } while (0) 145e4808c4bSKip Macy 146e4808c4bSKip Macy #define XBQ_REMOVE(sc, qname) (sc)->xb_qstat[qname].q_length-- 147e4808c4bSKip Macy 148e4808c4bSKip Macy #define XBQ_INIT(sc, qname) \ 149e4808c4bSKip Macy do { \ 150e4808c4bSKip Macy sc->xb_qstat[qname].q_length = 0; \ 151e4808c4bSKip Macy sc->xb_qstat[qname].q_max = 0; \ 152e4808c4bSKip Macy } while (0) 153e4808c4bSKip Macy 154e4808c4bSKip Macy #define XBQ_COMMAND_QUEUE(name, index) \ 155e4808c4bSKip Macy static __inline void \ 156e4808c4bSKip Macy xb_initq_ ## name (struct xb_softc *sc) \ 157e4808c4bSKip Macy { \ 158e4808c4bSKip Macy TAILQ_INIT(&sc->cm_ ## name); \ 159e4808c4bSKip Macy XBQ_INIT(sc, index); \ 160e4808c4bSKip Macy } \ 161e4808c4bSKip Macy static __inline void \ 162e4808c4bSKip Macy xb_enqueue_ ## name (struct xb_command *cm) \ 163e4808c4bSKip Macy { \ 164e4808c4bSKip Macy if ((cm->cm_flags & XB_ON_XBQ_MASK) != 0) { \ 165e4808c4bSKip Macy printf("command %p is on another queue, " \ 166e4808c4bSKip Macy "flags = %#x\n", cm, cm->cm_flags); \ 167e4808c4bSKip Macy panic("command is on another queue"); \ 168e4808c4bSKip Macy } \ 169e4808c4bSKip Macy TAILQ_INSERT_TAIL(&cm->cm_sc->cm_ ## name, cm, cm_link); \ 170e4808c4bSKip Macy cm->cm_flags |= XB_ON_ ## index; \ 171e4808c4bSKip Macy XBQ_ADD(cm->cm_sc, index); \ 172e4808c4bSKip Macy } \ 173e4808c4bSKip Macy static __inline void \ 174e4808c4bSKip Macy xb_requeue_ ## name (struct xb_command *cm) \ 175e4808c4bSKip Macy { \ 176e4808c4bSKip Macy if ((cm->cm_flags & XB_ON_XBQ_MASK) != 0) { \ 177e4808c4bSKip Macy printf("command %p is on another queue, " \ 178e4808c4bSKip Macy "flags = %#x\n", cm, cm->cm_flags); \ 179e4808c4bSKip Macy panic("command is on another queue"); \ 180e4808c4bSKip Macy } \ 181e4808c4bSKip Macy TAILQ_INSERT_HEAD(&cm->cm_sc->cm_ ## name, cm, cm_link); \ 182e4808c4bSKip Macy cm->cm_flags |= XB_ON_ ## index; \ 183e4808c4bSKip Macy XBQ_ADD(cm->cm_sc, index); \ 184e4808c4bSKip Macy } \ 185e4808c4bSKip Macy static __inline struct xb_command * \ 186e4808c4bSKip Macy xb_dequeue_ ## name (struct xb_softc *sc) \ 187e4808c4bSKip Macy { \ 188e4808c4bSKip Macy struct xb_command *cm; \ 189e4808c4bSKip Macy \ 190e4808c4bSKip Macy if ((cm = TAILQ_FIRST(&sc->cm_ ## name)) != NULL) { \ 191e4808c4bSKip Macy if ((cm->cm_flags & XB_ON_ ## index) == 0) { \ 192e4808c4bSKip Macy printf("command %p not in queue, " \ 193e4808c4bSKip Macy "flags = %#x, bit = %#x\n", cm, \ 194e4808c4bSKip Macy cm->cm_flags, XB_ON_ ## index); \ 195e4808c4bSKip Macy panic("command not in queue"); \ 196e4808c4bSKip Macy } \ 197e4808c4bSKip Macy TAILQ_REMOVE(&sc->cm_ ## name, cm, cm_link); \ 198e4808c4bSKip Macy cm->cm_flags &= ~XB_ON_ ## index; \ 199e4808c4bSKip Macy XBQ_REMOVE(sc, index); \ 200e4808c4bSKip Macy } \ 201e4808c4bSKip Macy return (cm); \ 202e4808c4bSKip Macy } \ 203e4808c4bSKip Macy static __inline void \ 204e4808c4bSKip Macy xb_remove_ ## name (struct xb_command *cm) \ 205e4808c4bSKip Macy { \ 206e4808c4bSKip Macy if ((cm->cm_flags & XB_ON_ ## index) == 0) { \ 207e4808c4bSKip Macy printf("command %p not in queue, flags = %#x, " \ 208e4808c4bSKip Macy "bit = %#x\n", cm, cm->cm_flags, \ 209e4808c4bSKip Macy XB_ON_ ## index); \ 210e4808c4bSKip Macy panic("command not in queue"); \ 211e4808c4bSKip Macy } \ 212e4808c4bSKip Macy TAILQ_REMOVE(&cm->cm_sc->cm_ ## name, cm, cm_link); \ 213e4808c4bSKip Macy cm->cm_flags &= ~XB_ON_ ## index; \ 214e4808c4bSKip Macy XBQ_REMOVE(cm->cm_sc, index); \ 215e4808c4bSKip Macy } \ 216e4808c4bSKip Macy struct hack 217e4808c4bSKip Macy 218e4808c4bSKip Macy XBQ_COMMAND_QUEUE(free, XBQ_FREE); 219e4808c4bSKip Macy XBQ_COMMAND_QUEUE(ready, XBQ_READY); 220e4808c4bSKip Macy XBQ_COMMAND_QUEUE(busy, XBQ_BUSY); 221e4808c4bSKip Macy XBQ_COMMAND_QUEUE(complete, XBQ_COMPLETE); 222e4808c4bSKip Macy 223e4808c4bSKip Macy static __inline void 224e4808c4bSKip Macy xb_initq_bio(struct xb_softc *sc) 225e4808c4bSKip Macy { 226e4808c4bSKip Macy bioq_init(&sc->xb_bioq); 227e4808c4bSKip Macy XBQ_INIT(sc, XBQ_BIO); 228e4808c4bSKip Macy } 229e4808c4bSKip Macy 230e4808c4bSKip Macy static __inline void 231e4808c4bSKip Macy xb_enqueue_bio(struct xb_softc *sc, struct bio *bp) 232e4808c4bSKip Macy { 233e4808c4bSKip Macy bioq_insert_tail(&sc->xb_bioq, bp); 234e4808c4bSKip Macy XBQ_ADD(sc, XBQ_BIO); 235e4808c4bSKip Macy } 236e4808c4bSKip Macy 237e4808c4bSKip Macy static __inline void 238e4808c4bSKip Macy xb_requeue_bio(struct xb_softc *sc, struct bio *bp) 239e4808c4bSKip Macy { 240e4808c4bSKip Macy bioq_insert_head(&sc->xb_bioq, bp); 241e4808c4bSKip Macy XBQ_ADD(sc, XBQ_BIO); 242e4808c4bSKip Macy } 243e4808c4bSKip Macy 244e4808c4bSKip Macy static __inline struct bio * 245e4808c4bSKip Macy xb_dequeue_bio(struct xb_softc *sc) 246e4808c4bSKip Macy { 247e4808c4bSKip Macy struct bio *bp; 248e4808c4bSKip Macy 249e4808c4bSKip Macy if ((bp = bioq_first(&sc->xb_bioq)) != NULL) { 250e4808c4bSKip Macy bioq_remove(&sc->xb_bioq, bp); 251e4808c4bSKip Macy XBQ_REMOVE(sc, XBQ_BIO); 252e4808c4bSKip Macy } 253e4808c4bSKip Macy return (bp); 254e4808c4bSKip Macy } 25589e0f4d2SKip Macy 25689e0f4d2SKip Macy #endif /* __XEN_DRIVERS_BLOCK_H__ */ 25789e0f4d2SKip Macy 258