xref: /freebsd/sys/dev/xen/blkfront/block.h (revision e4808c4b2dbab579f0c22efa2e05d7c463b1260e)
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