xref: /freebsd/sys/dev/ciss/cissvar.h (revision 3ff369fed2a08f32dda232c10470b949bef9489f)
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$
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
79 typedef 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 
91 struct 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  */
110 struct 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  */
150 struct 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 
162     char			cl_name[16];		/* device name */
163 };
164 
165 /*
166  * Per-adapter data
167  */
168 struct ciss_softc
169 {
170     /* bus connections */
171     device_t			ciss_dev;		/* bus attachment */
172     dev_t			ciss_dev_t;		/* control device */
173 
174     struct resource		*ciss_regs_resource;	/* register interface window */
175     int				ciss_regs_rid;		/* resource ID */
176     bus_space_handle_t		ciss_regs_bhandle;	/* bus space handle */
177     bus_space_tag_t		ciss_regs_btag;		/* bus space tag */
178 
179     struct resource		*ciss_cfg_resource;	/* config struct interface window */
180     int				ciss_cfg_rid;		/* resource ID */
181     struct ciss_config_table	*ciss_cfg;		/* config table in adapter memory */
182     struct ciss_bmic_id_table	*ciss_id;		/* ID table in host memory */
183     u_int32_t			ciss_heartbeat;		/* last heartbeat value */
184     int				ciss_heart_attack;	/* number of times we have seen this value */
185 
186     struct resource		*ciss_irq_resource;	/* interrupt */
187     int				ciss_irq_rid;		/* resource ID */
188     void			*ciss_intr;		/* interrupt handle */
189 
190     bus_dma_tag_t		ciss_parent_dmat;	/* parent DMA tag */
191     bus_dma_tag_t		ciss_buffer_dmat;	/* data buffer/command DMA tag */
192 
193     u_int32_t			ciss_interrupt_mask;	/* controller interrupt mask bits */
194 
195     int				ciss_max_requests;
196     struct ciss_request		ciss_request[CISS_MAX_REQUESTS];	/* requests */
197     void			*ciss_command;		/* command structures */
198     bus_dma_tag_t		ciss_command_dmat;	/* command DMA tag */
199     bus_dmamap_t		ciss_command_map;	/* command DMA map */
200     u_int32_t			ciss_command_phys;	/* command array base address */
201     TAILQ_HEAD(,ciss_request)	ciss_free;		/* requests available for reuse */
202     TAILQ_HEAD(,ciss_request)	ciss_busy;		/* requests in the adapter */
203     TAILQ_HEAD(,ciss_request)	ciss_complete;		/* requests which have been returned by the adapter */
204 
205     struct callout_handle	ciss_periodic;		/* periodic event handling */
206     struct ciss_request		*ciss_periodic_notify;	/* notify callback request */
207 
208     struct ciss_notify		ciss_notify[CISS_MAX_EVENTS];
209     int				ciss_notify_head;	/* saved-event ringbuffer */
210     int				ciss_notify_tail;
211 
212     struct ciss_ldrive		ciss_logical[CISS_MAX_LOGICAL];
213 
214     struct cam_devq		*ciss_cam_devq;
215     struct cam_sim		*ciss_cam_sim;
216     struct cam_path		*ciss_cam_path;
217 
218     int				ciss_flags;
219 #define CISS_FLAG_NOTIFY_OK	(1<<0)		/* notify command running OK */
220 #define CISS_FLAG_CONTROL_OPEN	(1<<1)		/* control device is open */
221 #define CISS_FLAG_ABORTING	(1<<2)		/* driver is going away */
222 #define CISS_FLAG_RUNNING	(1<<3)		/* driver is running (interrupts usable) */
223 
224 #define CISS_FLAG_FAKE_SYNCH	(1<<16)		/* needs SYNCHRONISE_CACHE faked */
225 #define CISS_FLAG_BMIC_ABORT	(1<<17)		/* use BMIC command to abort Notify on Event */
226 
227     struct ciss_qstat		ciss_qstat[CISSQ_COUNT];	/* queue statistics */
228 };
229 
230 /*
231  * Given a request tag, find the corresponding command in virtual or
232  * physical space.
233  *
234  * The arithmetic here is due to the allocation of ciss_command structures
235  * inside CISS_COMMAND_ALLOC_SIZE blocks.  See the comment at the definition
236  * of CISS_COMMAND_ALLOC_SIZE above.
237  */
238 #define CISS_FIND_COMMAND(cr)							\
239 	(struct ciss_command *)((u_int8_t *)(cr)->cr_sc->ciss_command +		\
240 				((cr)->cr_tag * CISS_COMMAND_ALLOC_SIZE))
241 #define CISS_FIND_COMMANDPHYS(cr)	((cr)->cr_sc->ciss_command_phys + \
242 					 ((cr)->cr_tag * CISS_COMMAND_ALLOC_SIZE))
243 
244 /************************************************************************
245  * Debugging/diagnostic output.
246  */
247 
248 /*
249  * Debugging levels:
250  *  0 - quiet, only emit warnings
251  *  1 - talkative, log major events, but nothing on the I/O path
252  *  2 - noisy, log events on the I/O path
253  *  3 - extremely noisy, log items in loops
254  */
255 #ifdef CISS_DEBUG
256 # define debug(level, fmt, args...)							\
257 	do {										\
258 	    if (level <= CISS_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);	\
259 	} while(0)
260 # define debug_called(level)						\
261 	do {								\
262 	    if (level <= CISS_DEBUG) printf("%s: called\n", __func__);	\
263 	} while(0)
264 # define debug_struct(s)		printf("  SIZE %s: %d\n", #s, sizeof(struct s))
265 # define debug_union(s)			printf("  SIZE %s: %d\n", #s, sizeof(union s))
266 # define debug_type(s)			printf("  SIZE %s: %d\n", #s, sizeof(s))
267 # define debug_field(s, f)		printf("  OFFSET %s.%s: %d\n", #s, #f, ((int)&(((struct s *)0)->f)))
268 # define debug_const(c)			printf("  CONST %s %d/0x%x\n", #c, c, c);
269 #else
270 # define debug(level, fmt, args...)
271 # define debug_called(level)
272 # define debug_struct(s)
273 # define debug_union(s)
274 # define debug_type(s)
275 # define debug_field(s, f)
276 # define debug_const(c)
277 #endif
278 
279 #define ciss_printf(sc, fmt, args...)	device_printf(sc->ciss_dev, fmt , ##args)
280 
281 /************************************************************************
282  * Queue primitives
283  */
284 
285 #define CISSQ_ADD(sc, qname)					\
286 	do {							\
287 	    struct ciss_qstat *qs = &(sc)->ciss_qstat[qname];	\
288 								\
289 	    qs->q_length++;					\
290 	    if (qs->q_length > qs->q_max)			\
291 		qs->q_max = qs->q_length;			\
292 	} while(0)
293 
294 #define CISSQ_REMOVE(sc, qname)    (sc)->ciss_qstat[qname].q_length--
295 #define CISSQ_INIT(sc, qname)			\
296 	do {					\
297 	    sc->ciss_qstat[qname].q_length = 0;	\
298 	    sc->ciss_qstat[qname].q_max = 0;	\
299 	} while(0)
300 
301 
302 #define CISSQ_REQUEST_QUEUE(name, index)				\
303 static __inline void							\
304 ciss_initq_ ## name (struct ciss_softc *sc)				\
305 {									\
306     TAILQ_INIT(&sc->ciss_ ## name);					\
307     CISSQ_INIT(sc, index);						\
308 }									\
309 static __inline void							\
310 ciss_enqueue_ ## name (struct ciss_request *cr)				\
311 {									\
312     int		s;							\
313 									\
314     s = splcam();							\
315     TAILQ_INSERT_TAIL(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
316     CISSQ_ADD(cr->cr_sc, index);					\
317     cr->cr_onq = index;							\
318     splx(s);								\
319 }									\
320 static __inline void							\
321 ciss_requeue_ ## name (struct ciss_request *cr)				\
322 {									\
323     int		s;							\
324 									\
325     s = splcam();							\
326     TAILQ_INSERT_HEAD(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
327     CISSQ_ADD(cr->cr_sc, index);					\
328     cr->cr_onq = index;							\
329     splx(s);								\
330 }									\
331 static __inline struct ciss_request *					\
332 ciss_dequeue_ ## name (struct ciss_softc *sc)				\
333 {									\
334     struct ciss_request	*cr;						\
335     int			s;						\
336 									\
337     s = splcam();							\
338     if ((cr = TAILQ_FIRST(&sc->ciss_ ## name)) != NULL) {		\
339 	TAILQ_REMOVE(&sc->ciss_ ## name, cr, cr_link);			\
340 	CISSQ_REMOVE(sc, index);					\
341 	cr->cr_onq = -1;						\
342     }									\
343     splx(s);								\
344     return(cr);								\
345 }									\
346 static __inline int							\
347 ciss_remove_ ## name (struct ciss_request *cr)				\
348 {									\
349     int			s, error;					\
350 									\
351     s = splcam();							\
352     if (cr->cr_onq != index) {						\
353 	printf("request on queue %d (expected %d)\n", cr->cr_onq, index);\
354 	error = 1;							\
355     } else {								\
356 	TAILQ_REMOVE(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
357 	CISSQ_REMOVE(cr->cr_sc, index);					\
358 	cr->cr_onq = -1;						\
359 	error = 0;							\
360     }									\
361     splx(s);								\
362     return(error);							\
363 }									\
364 struct hack
365 
366 CISSQ_REQUEST_QUEUE(free, CISSQ_FREE);
367 CISSQ_REQUEST_QUEUE(busy, CISSQ_BUSY);
368 CISSQ_REQUEST_QUEUE(complete, CISSQ_COMPLETE);
369 
370 /********************************************************************************
371  * space-fill a character string
372  */
373 static __inline void
374 padstr(char *targ, const char *src, int len)
375 {
376     while (len-- > 0) {
377 	if (*src != 0) {
378 	    *targ++ = *src++;
379 	} else {
380 	    *targ++ = ' ';
381 	}
382     }
383 }
384