1 /* 2 * XenBSD block device driver 3 * 4 * Copyright (c) 2009 Scott Long, Yahoo! 5 * Copyright (c) 2009 Frank Suchomel, Citrix 6 * Copyright (c) 2009 Doug F. Rabson, Citrix 7 * Copyright (c) 2005 Kip Macy 8 * Copyright (c) 2003-2004, Keir Fraser & Steve Hand 9 * Modifications by Mark A. Williamson are (c) Intel Research Cambridge 10 * 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a copy 13 * of this software and associated documentation files (the "Software"), to 14 * deal in the Software without restriction, including without limitation the 15 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 * sell copies of the Software, and to permit persons to whom the Software is 17 * furnished to do so, subject to the following conditions: 18 * 19 * The above copyright notice and this permission notice shall be included in 20 * all copies or substantial portions of the Software. 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 * DEALINGS IN THE SOFTWARE. 28 * 29 * $FreeBSD$ 30 */ 31 32 33 #ifndef __XEN_DRIVERS_BLOCK_H__ 34 #define __XEN_DRIVERS_BLOCK_H__ 35 #include <xen/interface/io/blkif.h> 36 37 struct xlbd_type_info 38 { 39 int partn_shift; 40 int disks_per_major; 41 char *devname; 42 char *diskname; 43 }; 44 45 struct xlbd_major_info 46 { 47 int major; 48 int index; 49 int usage; 50 struct xlbd_type_info *type; 51 }; 52 53 struct xb_command { 54 TAILQ_ENTRY(xb_command) cm_link; 55 struct xb_softc *cm_sc; 56 u_int cm_flags; 57 #define XB_CMD_FROZEN (1<<0) 58 #define XB_CMD_POLLED (1<<1) 59 #define XB_ON_XBQ_FREE (1<<2) 60 #define XB_ON_XBQ_READY (1<<3) 61 #define XB_ON_XBQ_BUSY (1<<4) 62 #define XB_ON_XBQ_COMPLETE (1<<5) 63 #define XB_ON_XBQ_MASK ((1<<2)|(1<<3)|(1<<4)|(1<<5)) 64 bus_dmamap_t map; 65 blkif_request_t req; 66 struct bio *bp; 67 grant_ref_t gref_head; 68 void *data; 69 size_t datalen; 70 int operation; 71 blkif_sector_t sector_number; 72 int status; 73 void (* cm_complete)(struct xb_command *); 74 }; 75 76 #define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE) 77 78 #define XBQ_FREE 0 79 #define XBQ_BIO 1 80 #define XBQ_READY 2 81 #define XBQ_BUSY 3 82 #define XBQ_COMPLETE 4 83 #define XBQ_COUNT 5 84 85 struct xb_qstat { 86 uint32_t q_length; 87 uint32_t q_max; 88 }; 89 90 union xb_statrequest { 91 uint32_t ms_item; 92 struct xb_qstat ms_qstat; 93 }; 94 95 /* 96 * We have one of these per vbd, whether ide, scsi or 'other'. 97 */ 98 struct xb_softc { 99 device_t xb_dev; 100 struct disk *xb_disk; /* disk params */ 101 struct bio_queue_head xb_bioq; /* sort queue */ 102 int xb_unit; 103 int xb_flags; 104 #define XB_OPEN (1<<0) /* drive is open (can't shut down) */ 105 #define XB_BARRIER (1 << 1) /* backend supports barriers */ 106 #define XB_READY (1 << 2) /* Is ready */ 107 #define XB_FROZEN (1 << 3) /* Waiting for resources */ 108 int vdevice; 109 blkif_vdev_t handle; 110 int connected; 111 int ring_ref; 112 blkif_front_ring_t ring; 113 unsigned int irq; 114 struct xlbd_major_info *mi; 115 struct gnttab_free_callback callback; 116 TAILQ_HEAD(,xb_command) cm_free; 117 TAILQ_HEAD(,xb_command) cm_ready; 118 TAILQ_HEAD(,xb_command) cm_busy; 119 TAILQ_HEAD(,xb_command) cm_complete; 120 struct xb_qstat xb_qstat[XBQ_COUNT]; 121 bus_dma_tag_t xb_io_dmat; 122 123 /** 124 * The number of people holding this device open. We won't allow a 125 * hot-unplug unless this is 0. 126 */ 127 int users; 128 struct mtx xb_io_lock; 129 struct xb_command shadow[BLK_RING_SIZE]; 130 }; 131 132 int xlvbd_add(struct xb_softc *, blkif_sector_t capacity, int device, 133 uint16_t vdisk_info, uint16_t sector_size); 134 void xlvbd_del(struct xb_softc *); 135 136 #define XBQ_ADD(sc, qname) \ 137 do { \ 138 struct xb_qstat *qs; \ 139 \ 140 qs = &(sc)->xb_qstat[qname]; \ 141 qs->q_length++; \ 142 if (qs->q_length > qs->q_max) \ 143 qs->q_max = qs->q_length; \ 144 } while (0) 145 146 #define XBQ_REMOVE(sc, qname) (sc)->xb_qstat[qname].q_length-- 147 148 #define XBQ_INIT(sc, qname) \ 149 do { \ 150 sc->xb_qstat[qname].q_length = 0; \ 151 sc->xb_qstat[qname].q_max = 0; \ 152 } while (0) 153 154 #define XBQ_COMMAND_QUEUE(name, index) \ 155 static __inline void \ 156 xb_initq_ ## name (struct xb_softc *sc) \ 157 { \ 158 TAILQ_INIT(&sc->cm_ ## name); \ 159 XBQ_INIT(sc, index); \ 160 } \ 161 static __inline void \ 162 xb_enqueue_ ## name (struct xb_command *cm) \ 163 { \ 164 if ((cm->cm_flags & XB_ON_XBQ_MASK) != 0) { \ 165 printf("command %p is on another queue, " \ 166 "flags = %#x\n", cm, cm->cm_flags); \ 167 panic("command is on another queue"); \ 168 } \ 169 TAILQ_INSERT_TAIL(&cm->cm_sc->cm_ ## name, cm, cm_link); \ 170 cm->cm_flags |= XB_ON_ ## index; \ 171 XBQ_ADD(cm->cm_sc, index); \ 172 } \ 173 static __inline void \ 174 xb_requeue_ ## name (struct xb_command *cm) \ 175 { \ 176 if ((cm->cm_flags & XB_ON_XBQ_MASK) != 0) { \ 177 printf("command %p is on another queue, " \ 178 "flags = %#x\n", cm, cm->cm_flags); \ 179 panic("command is on another queue"); \ 180 } \ 181 TAILQ_INSERT_HEAD(&cm->cm_sc->cm_ ## name, cm, cm_link); \ 182 cm->cm_flags |= XB_ON_ ## index; \ 183 XBQ_ADD(cm->cm_sc, index); \ 184 } \ 185 static __inline struct xb_command * \ 186 xb_dequeue_ ## name (struct xb_softc *sc) \ 187 { \ 188 struct xb_command *cm; \ 189 \ 190 if ((cm = TAILQ_FIRST(&sc->cm_ ## name)) != NULL) { \ 191 if ((cm->cm_flags & XB_ON_ ## index) == 0) { \ 192 printf("command %p not in queue, " \ 193 "flags = %#x, bit = %#x\n", cm, \ 194 cm->cm_flags, XB_ON_ ## index); \ 195 panic("command not in queue"); \ 196 } \ 197 TAILQ_REMOVE(&sc->cm_ ## name, cm, cm_link); \ 198 cm->cm_flags &= ~XB_ON_ ## index; \ 199 XBQ_REMOVE(sc, index); \ 200 } \ 201 return (cm); \ 202 } \ 203 static __inline void \ 204 xb_remove_ ## name (struct xb_command *cm) \ 205 { \ 206 if ((cm->cm_flags & XB_ON_ ## index) == 0) { \ 207 printf("command %p not in queue, flags = %#x, " \ 208 "bit = %#x\n", cm, cm->cm_flags, \ 209 XB_ON_ ## index); \ 210 panic("command not in queue"); \ 211 } \ 212 TAILQ_REMOVE(&cm->cm_sc->cm_ ## name, cm, cm_link); \ 213 cm->cm_flags &= ~XB_ON_ ## index; \ 214 XBQ_REMOVE(cm->cm_sc, index); \ 215 } \ 216 struct hack 217 218 XBQ_COMMAND_QUEUE(free, XBQ_FREE); 219 XBQ_COMMAND_QUEUE(ready, XBQ_READY); 220 XBQ_COMMAND_QUEUE(busy, XBQ_BUSY); 221 XBQ_COMMAND_QUEUE(complete, XBQ_COMPLETE); 222 223 static __inline void 224 xb_initq_bio(struct xb_softc *sc) 225 { 226 bioq_init(&sc->xb_bioq); 227 XBQ_INIT(sc, XBQ_BIO); 228 } 229 230 static __inline void 231 xb_enqueue_bio(struct xb_softc *sc, struct bio *bp) 232 { 233 bioq_insert_tail(&sc->xb_bioq, bp); 234 XBQ_ADD(sc, XBQ_BIO); 235 } 236 237 static __inline void 238 xb_requeue_bio(struct xb_softc *sc, struct bio *bp) 239 { 240 bioq_insert_head(&sc->xb_bioq, bp); 241 XBQ_ADD(sc, XBQ_BIO); 242 } 243 244 static __inline struct bio * 245 xb_dequeue_bio(struct xb_softc *sc) 246 { 247 struct bio *bp; 248 249 if ((bp = bioq_first(&sc->xb_bioq)) != NULL) { 250 bioq_remove(&sc->xb_bioq, bp); 251 XBQ_REMOVE(sc, XBQ_BIO); 252 } 253 return (bp); 254 } 255 256 #endif /* __XEN_DRIVERS_BLOCK_H__ */ 257 258