cissvar.h revision 110366
1/*-
2 * Copyright (c) 2001 Michael Smith
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 *	$FreeBSD: head/sys/dev/ciss/cissvar.h 110366 2003-02-05 08:43:46Z ps $
27 */
28
29/*
30 * CISS adapter driver datastructures
31 */
32
33/************************************************************************
34 * Tunable parameters
35 */
36
37/*
38 * There is no guaranteed upper bound on the number of concurrent
39 * commands an adapter may claim to support.  Cap it at a reasonable
40 * value.
41 */
42#define CISS_MAX_REQUESTS	256
43
44/*
45 * Maximum number of logical drives we support.
46 */
47#define CISS_MAX_LOGICAL	15
48
49/*
50 * Interrupt reduction can be controlled by tuning the interrupt
51 * coalesce delay and count paramters.  The delay (in microseconds)
52 * defers delivery of interrupts to increase the chance of there being
53 * more than one completed command ready when the interrupt is
54 * delivered.  The count expedites the delivery of the interrupt when
55 * the given number of commands are ready.
56 *
57 * If the delay is set to 0, interrupts are delivered immediately.
58 */
59#define CISS_INTERRUPT_COALESCE_DELAY	1000
60#define CISS_INTERRUPT_COALESCE_COUNT	16
61
62/*
63 * Heartbeat routine timeout in seconds.  Note that since event
64 * handling is performed on a callback basis, we don't need this to
65 * run very often.
66 */
67#define CISS_HEARTBEAT_RATE		10
68
69/*
70 * Maximum number of events we will queue for a monitoring utility.
71 */
72#define CISS_MAX_EVENTS		32
73
74/************************************************************************
75 * Compatibility with older versions of FreeBSD
76 */
77#if __FreeBSD_version < 440001
78#warning testing old-FreeBSD compat
79typedef struct proc	d_thread_t;
80#endif
81
82/************************************************************************
83 * Command queue statistics
84 */
85
86#define CISSQ_FREE	0
87#define CISSQ_BUSY	1
88#define CISSQ_COMPLETE	2
89#define CISSQ_COUNT	3
90
91struct ciss_qstat
92{
93    u_int32_t	q_length;
94    u_int32_t	q_max;
95};
96
97/************************************************************************
98 * Driver version.  Only really significant to the ACU interface.
99 */
100#define CISS_DRIVER_VERSION	20011201
101
102/************************************************************************
103 * Driver data structures
104 */
105
106/*
107 * Each command issued to the adapter is managed by a request
108 * structure.
109 */
110struct ciss_request
111{
112    TAILQ_ENTRY(ciss_request)	cr_link;
113    int				cr_onq;		/* which queue we are on */
114
115    struct ciss_softc		*cr_sc;		/* controller softc */
116    void			*cr_data;	/* data buffer */
117    u_int32_t			cr_length;	/* data length */
118    bus_dmamap_t		cr_datamap;	/* DMA map for data */
119    int				cr_tag;
120    int				cr_flags;
121#define CISS_REQ_MAPPED		(1<<0)		/* data mapped */
122#define CISS_REQ_SLEEP		(1<<1)		/* submitter sleeping */
123#define CISS_REQ_POLL		(1<<2)		/* submitter polling */
124#define CISS_REQ_DATAOUT	(1<<3)		/* data host->adapter */
125#define CISS_REQ_DATAIN		(1<<4)		/* data adapter->host */
126
127    void			(* cr_complete)(struct ciss_request *);
128    void			*cr_private;
129};
130
131/*
132 * The adapter command structure is defined with a zero-length
133 * scatter/gather list size.  In practise, we want space for a
134 * scatter-gather list, and we also want to avoid having commands
135 * cross page boundaries.
136 *
137 * Note that 512 bytes yields 28 scatter/gather entries, or the
138 * ability to map (26 * PAGE_SIZE) + 2 bytes of data.  On x86, this is
139 * 104kB.  256 bytes would only yield 12 entries, giving a mere 40kB,
140 * too small.
141 */
142
143#define CISS_COMMAND_ALLOC_SIZE		512	/* XXX tune to get sensible s/g list length */
144#define CISS_COMMAND_SG_LENGTH	((CISS_COMMAND_ALLOC_SIZE - sizeof(struct ciss_command)) \
145				 / sizeof(struct ciss_sg_entry))
146
147/*
148 * Per-logical-drive data.
149 */
150struct ciss_ldrive
151{
152    union ciss_device_address	cl_address;
153
154    int				cl_status;
155#define CISS_LD_NONEXISTENT	0
156#define CISS_LD_ONLINE		1
157#define CISS_LD_OFFLINE		2
158
159    struct ciss_bmic_id_ldrive	*cl_ldrive;
160    struct ciss_bmic_id_lstatus	*cl_lstatus;
161    struct ciss_ldrive_geometry	cl_geometry;
162
163    char			cl_name[16];		/* device name */
164};
165
166/*
167 * Per-adapter data
168 */
169struct ciss_softc
170{
171    /* bus connections */
172    device_t			ciss_dev;		/* bus attachment */
173    dev_t			ciss_dev_t;		/* control device */
174
175    struct resource		*ciss_regs_resource;	/* register interface window */
176    int				ciss_regs_rid;		/* resource ID */
177    bus_space_handle_t		ciss_regs_bhandle;	/* bus space handle */
178    bus_space_tag_t		ciss_regs_btag;		/* bus space tag */
179
180    struct resource		*ciss_cfg_resource;	/* config struct interface window */
181    int				ciss_cfg_rid;		/* resource ID */
182    struct ciss_config_table	*ciss_cfg;		/* config table in adapter memory */
183    struct ciss_bmic_id_table	*ciss_id;		/* ID table in host memory */
184    u_int32_t			ciss_heartbeat;		/* last heartbeat value */
185    int				ciss_heart_attack;	/* number of times we have seen this value */
186
187    struct resource		*ciss_irq_resource;	/* interrupt */
188    int				ciss_irq_rid;		/* resource ID */
189    void			*ciss_intr;		/* interrupt handle */
190
191    bus_dma_tag_t		ciss_parent_dmat;	/* parent DMA tag */
192    bus_dma_tag_t		ciss_buffer_dmat;	/* data buffer/command DMA tag */
193
194    u_int32_t			ciss_interrupt_mask;	/* controller interrupt mask bits */
195
196    int				ciss_max_requests;
197    struct ciss_request		ciss_request[CISS_MAX_REQUESTS];	/* requests */
198    void			*ciss_command;		/* command structures */
199    bus_dma_tag_t		ciss_command_dmat;	/* command DMA tag */
200    bus_dmamap_t		ciss_command_map;	/* command DMA map */
201    u_int32_t			ciss_command_phys;	/* command array base address */
202    TAILQ_HEAD(,ciss_request)	ciss_free;		/* requests available for reuse */
203    TAILQ_HEAD(,ciss_request)	ciss_busy;		/* requests in the adapter */
204    TAILQ_HEAD(,ciss_request)	ciss_complete;		/* requests which have been returned by the adapter */
205
206    struct callout_handle	ciss_periodic;		/* periodic event handling */
207    struct ciss_request		*ciss_periodic_notify;	/* notify callback request */
208
209    struct ciss_notify		ciss_notify[CISS_MAX_EVENTS];
210    int				ciss_notify_head;	/* saved-event ringbuffer */
211    int				ciss_notify_tail;
212
213    struct ciss_ldrive		ciss_logical[CISS_MAX_LOGICAL];
214
215    struct cam_devq		*ciss_cam_devq;
216    struct cam_sim		*ciss_cam_sim;
217    struct cam_path		*ciss_cam_path;
218
219    int				ciss_flags;
220#define CISS_FLAG_NOTIFY_OK	(1<<0)		/* notify command running OK */
221#define CISS_FLAG_CONTROL_OPEN	(1<<1)		/* control device is open */
222#define CISS_FLAG_ABORTING	(1<<2)		/* driver is going away */
223#define CISS_FLAG_RUNNING	(1<<3)		/* driver is running (interrupts usable) */
224
225#define CISS_FLAG_FAKE_SYNCH	(1<<16)		/* needs SYNCHRONISE_CACHE faked */
226#define CISS_FLAG_BMIC_ABORT	(1<<17)		/* use BMIC command to abort Notify on Event */
227
228    struct ciss_qstat		ciss_qstat[CISSQ_COUNT];	/* queue statistics */
229};
230
231/*
232 * Given a request tag, find the corresponding command in virtual or
233 * physical space.
234 *
235 * The arithmetic here is due to the allocation of ciss_command structures
236 * inside CISS_COMMAND_ALLOC_SIZE blocks.  See the comment at the definition
237 * of CISS_COMMAND_ALLOC_SIZE above.
238 */
239#define CISS_FIND_COMMAND(cr)							\
240	(struct ciss_command *)((u_int8_t *)(cr)->cr_sc->ciss_command +		\
241				((cr)->cr_tag * CISS_COMMAND_ALLOC_SIZE))
242#define CISS_FIND_COMMANDPHYS(cr)	((cr)->cr_sc->ciss_command_phys + \
243					 ((cr)->cr_tag * CISS_COMMAND_ALLOC_SIZE))
244
245/************************************************************************
246 * Debugging/diagnostic output.
247 */
248
249/*
250 * Debugging levels:
251 *  0 - quiet, only emit warnings
252 *  1 - talkative, log major events, but nothing on the I/O path
253 *  2 - noisy, log events on the I/O path
254 *  3 - extremely noisy, log items in loops
255 */
256#ifdef CISS_DEBUG
257# define debug(level, fmt, args...)							\
258	do {										\
259	    if (level <= CISS_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);	\
260	} while(0)
261# define debug_called(level)						\
262	do {								\
263	    if (level <= CISS_DEBUG) printf("%s: called\n", __func__);	\
264	} while(0)
265# define debug_struct(s)		printf("  SIZE %s: %zu\n", #s, sizeof(struct s))
266# define debug_union(s)			printf("  SIZE %s: %zu\n", #s, sizeof(union s))
267# define debug_type(s)			printf("  SIZE %s: %zu\n", #s, sizeof(s))
268# define debug_field(s, f)		printf("  OFFSET %s.%s: %d\n", #s, #f, ((int)&(((struct s *)0)->f)))
269# define debug_const(c)			printf("  CONST %s %jd/0x%jx\n", #c, (intmax_t)c, (intmax_t)c);
270#else
271# define debug(level, fmt, args...)
272# define debug_called(level)
273# define debug_struct(s)
274# define debug_union(s)
275# define debug_type(s)
276# define debug_field(s, f)
277# define debug_const(c)
278#endif
279
280#define ciss_printf(sc, fmt, args...)	device_printf(sc->ciss_dev, fmt , ##args)
281
282/************************************************************************
283 * Queue primitives
284 */
285
286#define CISSQ_ADD(sc, qname)					\
287	do {							\
288	    struct ciss_qstat *qs = &(sc)->ciss_qstat[qname];	\
289								\
290	    qs->q_length++;					\
291	    if (qs->q_length > qs->q_max)			\
292		qs->q_max = qs->q_length;			\
293	} while(0)
294
295#define CISSQ_REMOVE(sc, qname)    (sc)->ciss_qstat[qname].q_length--
296#define CISSQ_INIT(sc, qname)			\
297	do {					\
298	    sc->ciss_qstat[qname].q_length = 0;	\
299	    sc->ciss_qstat[qname].q_max = 0;	\
300	} while(0)
301
302
303#define CISSQ_REQUEST_QUEUE(name, index)				\
304static __inline void							\
305ciss_initq_ ## name (struct ciss_softc *sc)				\
306{									\
307    TAILQ_INIT(&sc->ciss_ ## name);					\
308    CISSQ_INIT(sc, index);						\
309}									\
310static __inline void							\
311ciss_enqueue_ ## name (struct ciss_request *cr)				\
312{									\
313    int		s;							\
314									\
315    s = splcam();							\
316    TAILQ_INSERT_TAIL(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
317    CISSQ_ADD(cr->cr_sc, index);					\
318    cr->cr_onq = index;							\
319    splx(s);								\
320}									\
321static __inline void							\
322ciss_requeue_ ## name (struct ciss_request *cr)				\
323{									\
324    int		s;							\
325									\
326    s = splcam();							\
327    TAILQ_INSERT_HEAD(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
328    CISSQ_ADD(cr->cr_sc, index);					\
329    cr->cr_onq = index;							\
330    splx(s);								\
331}									\
332static __inline struct ciss_request *					\
333ciss_dequeue_ ## name (struct ciss_softc *sc)				\
334{									\
335    struct ciss_request	*cr;						\
336    int			s;						\
337									\
338    s = splcam();							\
339    if ((cr = TAILQ_FIRST(&sc->ciss_ ## name)) != NULL) {		\
340	TAILQ_REMOVE(&sc->ciss_ ## name, cr, cr_link);			\
341	CISSQ_REMOVE(sc, index);					\
342	cr->cr_onq = -1;						\
343    }									\
344    splx(s);								\
345    return(cr);								\
346}									\
347static __inline int							\
348ciss_remove_ ## name (struct ciss_request *cr)				\
349{									\
350    int			s, error;					\
351									\
352    s = splcam();							\
353    if (cr->cr_onq != index) {						\
354	printf("request on queue %d (expected %d)\n", cr->cr_onq, index);\
355	error = 1;							\
356    } else {								\
357	TAILQ_REMOVE(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
358	CISSQ_REMOVE(cr->cr_sc, index);					\
359	cr->cr_onq = -1;						\
360	error = 0;							\
361    }									\
362    splx(s);								\
363    return(error);							\
364}									\
365struct hack
366
367CISSQ_REQUEST_QUEUE(free, CISSQ_FREE);
368CISSQ_REQUEST_QUEUE(busy, CISSQ_BUSY);
369CISSQ_REQUEST_QUEUE(complete, CISSQ_COMPLETE);
370
371/********************************************************************************
372 * space-fill a character string
373 */
374static __inline void
375padstr(char *targ, const char *src, int len)
376{
377    while (len-- > 0) {
378	if (*src != 0) {
379	    *targ++ = *src++;
380	} else {
381	    *targ++ = ' ';
382	}
383    }
384}
385