xref: /freebsd/sys/dev/aac/aacvar.h (revision 1d66272a85cde1c8a69c58f4b5dd649babd6eca6)
1 /*-
2  * Copyright (c) 2000 Michael Smith
3  * Copyright (c) 2000 BSDi
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *	$FreeBSD$
28  */
29 
30 /********************************************************************************
31  ********************************************************************************
32                                                      Driver Parameter Definitions
33  ********************************************************************************
34  ********************************************************************************/
35 
36 /*
37  * The firmware interface allows for a 16-bit s/g list length.  We limit
38  * ourselves to a reasonable maximum and ensure alignment.
39  */
40 #define AAC_MAXSGENTRIES	64	/* max S/G entries, limit 65535 */
41 
42 /*
43  * We allocate a small set of FIBs for the adapter to use to send us messages.
44  */
45 #define AAC_ADAPTER_FIBS	8
46 
47 /*
48  * FIBs are allocated up-front, and the pool isn't grown.  We should allocate
49  * enough here to let us keep the adapter busy without wasting large amounts
50  * of kernel memory.  The current interface implementation limits us to 512
51  * FIBs queued for the adapter at any one time.
52  */
53 #define AAC_FIB_COUNT		128
54 
55 /*
56  * The controller reports status events in AIFs.  We hang on to a number of these
57  * in order to pass them out to user-space management tools.
58  */
59 #define AAC_AIFQ_LENGTH		64
60 
61 /*
62  * Firmware messages are passed in the printf buffer.
63  */
64 #define AAC_PRINTF_BUFSIZE	256
65 
66 /*
67  * We wait this many seconds for the adapter to come ready if it is still booting
68  */
69 #define AAC_BOOT_TIMEOUT	(3 * 60)
70 
71 /*
72  * Timeout for immediate commands.
73  */
74 #define AAC_IMMEDIATE_TIMEOUT	30		/* seconds */
75 
76 /*
77  * Timeout for normal commands
78  */
79 #define AAC_CMD_TIMEOUT		30		/* seconds */
80 
81 /*
82  * Rate at which we periodically check for timed out commands and kick the
83  * controller.
84  */
85 #define AAC_PERIODIC_INTERVAL	10		/* seconds */
86 
87 /*
88  * Character device major numbers.
89  */
90 #define AAC_DISK_MAJOR	200
91 
92 /********************************************************************************
93  ********************************************************************************
94                                                       Driver Variable Definitions
95  ********************************************************************************
96  ********************************************************************************/
97 
98 #if __FreeBSD_version >= 500005
99 # include <sys/taskqueue.h>
100 #endif
101 
102 /*
103  * Per-container data structure
104  */
105 struct aac_container
106 {
107     struct aac_mntobj	co_mntobj;
108     device_t		co_disk;
109 };
110 
111 /*
112  * Per-disk structure
113  */
114 struct aac_disk
115 {
116     device_t			ad_dev;
117     dev_t			ad_dev_t;
118     struct aac_softc		*ad_controller;
119     struct aac_container	*ad_container;
120     struct disk			ad_disk;
121     struct devstat		ad_stats;
122     struct disklabel		ad_label;
123     int				ad_flags;
124 #define AAC_DISK_OPEN	(1<<0)
125     int				ad_cylinders;
126     int				ad_heads;
127     int				ad_sectors;
128     u_int32_t			ad_size;
129 };
130 
131 /*
132  * Per-command control structure.
133  */
134 struct aac_command
135 {
136     TAILQ_ENTRY(aac_command)	cm_link;	/* list linkage */
137 
138     struct aac_softc		*cm_sc;		/* controller that owns us */
139 
140     struct aac_fib		*cm_fib;	/* FIB associated with this command */
141     u_int32_t			cm_fibphys;	/* bus address of the FIB */
142     struct bio			*cm_data;	/* pointer to data in kernel space */
143     u_int32_t			cm_datalen;	/* data length */
144     bus_dmamap_t		cm_datamap;	/* DMA map for bio data */
145     struct aac_sg_table		*cm_sgtable;	/* pointer to s/g table in command */
146 
147     int				cm_flags;
148 #define AAC_CMD_MAPPED		(1<<0)		/* command has had its data mapped */
149 #define AAC_CMD_DATAIN		(1<<1)		/* command involves data moving from controller to host */
150 #define AAC_CMD_DATAOUT		(1<<2)		/* command involves data moving from host to controller */
151 #define AAC_CMD_COMPLETED	(1<<3)		/* command has been completed */
152 #define AAC_CMD_TIMEDOUT	(1<<4)		/* command taken too long */
153 
154     void			(* cm_complete)(struct aac_command *cm);
155     void			*cm_private;
156     time_t			cm_timestamp;	/* command creation time */
157 };
158 
159 /*
160  * We gather a number of adapter-visible items into a single structure.
161  *
162  * The ordering of this strucure may be important; we copy the Linux driver:
163  *
164  * Adapter FIBs
165  * Init struct
166  * Queue headers (Comm Area)
167  * Printf buffer
168  *
169  * In addition, we add:
170  * Sync Fib
171  */
172 struct aac_common {
173     /* fibs for the controller to send us messages */
174     struct aac_fib		ac_fibs[AAC_ADAPTER_FIBS];
175 
176     /* the init structure */
177     struct aac_adapter_init	ac_init;
178 
179     /* arena within which the queue structures are kept */
180     u_int8_t			ac_qbuf[sizeof(struct aac_queue_table) + AAC_QUEUE_ALIGN];
181 
182     /* buffer for text messages from the controller */
183     char		       	ac_printf[AAC_PRINTF_BUFSIZE];
184 
185     /* fib for synchronous commands */
186     struct aac_fib		ac_sync_fib;
187 };
188 
189 /*
190  * Interface operations
191  */
192 struct aac_interface
193 {
194     int		(* aif_get_fwstatus)(struct aac_softc *sc);
195     void	(* aif_qnotify)(struct aac_softc *sc, int qbit);
196     int		(* aif_get_istatus)(struct aac_softc *sc);
197     void	(* aif_set_istatus)(struct aac_softc *sc, int mask);
198     void	(* aif_set_mailbox)(struct aac_softc *sc, u_int32_t command,
199 				    u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3);
200     int		(* aif_get_mailboxstatus)(struct aac_softc *sc);
201     void	(* aif_set_interrupts)(struct aac_softc *sc, int enable);
202 };
203 extern struct aac_interface	aac_rx_interface;
204 extern struct aac_interface	aac_sa_interface;
205 
206 #define AAC_GET_FWSTATUS(sc)		((sc)->aac_if.aif_get_fwstatus((sc)))
207 #define AAC_QNOTIFY(sc, qbit)		((sc)->aac_if.aif_qnotify((sc), (qbit)))
208 #define AAC_GET_ISTATUS(sc)		((sc)->aac_if.aif_get_istatus((sc)))
209 #define AAC_CLEAR_ISTATUS(sc, mask)	((sc)->aac_if.aif_set_istatus((sc), (mask)))
210 #define AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3) \
211 	((sc)->aac_if.aif_set_mailbox((sc), (command), (arg0), (arg1), (arg2), (arg3)))
212 #define AAC_GET_MAILBOXSTATUS(sc)	((sc)->aac_if.aif_get_mailboxstatus((sc)))
213 #define	AAC_MASK_INTERRUPTS(sc)		((sc)->aac_if.aif_set_interrupts((sc), 0))
214 #define AAC_UNMASK_INTERRUPTS(sc)	((sc)->aac_if.aif_set_interrupts((sc), 1))
215 
216 #define AAC_SETREG4(sc, reg, val)	bus_space_write_4(sc->aac_btag, sc->aac_bhandle, reg, val)
217 #define AAC_GETREG4(sc, reg)		bus_space_read_4 (sc->aac_btag, sc->aac_bhandle, reg)
218 #define AAC_SETREG2(sc, reg, val)	bus_space_write_2(sc->aac_btag, sc->aac_bhandle, reg, val)
219 #define AAC_GETREG2(sc, reg)		bus_space_read_2 (sc->aac_btag, sc->aac_bhandle, reg)
220 #define AAC_SETREG1(sc, reg, val)	bus_space_write_1(sc->aac_btag, sc->aac_bhandle, reg, val)
221 #define AAC_GETREG1(sc, reg)		bus_space_read_1 (sc->aac_btag, sc->aac_bhandle, reg)
222 
223 /*
224  * Per-controller structure.
225  */
226 struct aac_softc
227 {
228     /* bus connections */
229     device_t			aac_dev;
230     struct resource		*aac_regs_resource;	/* register interface window */
231     int				aac_regs_rid;		/* resource ID */
232     bus_space_handle_t		aac_bhandle;		/* bus space handle */
233     bus_space_tag_t		aac_btag;		/* bus space tag */
234     bus_dma_tag_t		aac_parent_dmat;	/* parent DMA tag */
235     bus_dma_tag_t		aac_buffer_dmat;	/* data buffer/command DMA tag */
236     struct resource		*aac_irq;		/* interrupt */
237     int				aac_irq_rid;
238     void			*aac_intr;		/* interrupt handle */
239 
240     /* controller features, limits and status */
241     int				aac_state;
242 #define AAC_STATE_SUSPEND	(1<<0)
243 #define	AAC_STATE_OPEN		(1<<1)
244 #define AAC_STATE_INTERRUPTS_ON	(1<<2)
245 #define AAC_STATE_AIF_SLEEPER	(1<<3)
246     struct FsaRevision		aac_revision;
247 
248     /* controller hardware interface */
249     int				aac_hwif;
250 #define AAC_HWIF_I960RX		0
251 #define AAC_HWIF_STRONGARM	1
252 #define AAC_HWIF_UNKNOWN	-1
253     bus_dma_tag_t		aac_common_dmat;	/* common structure DMA tag */
254     bus_dmamap_t		aac_common_dmamap;	/* common structure DMA map */
255     struct aac_common		*aac_common;
256     u_int32_t			aac_common_busaddr;
257     struct aac_interface	aac_if;
258 
259     /* command/fib resources */
260     bus_dma_tag_t		aac_fib_dmat;	/* DMA tag for allocating FIBs */
261     struct aac_fib		*aac_fibs;
262     bus_dmamap_t		aac_fibmap;
263     u_int32_t			aac_fibphys;
264     struct aac_command		aac_command[AAC_FIB_COUNT];
265 
266     /* command management */
267     TAILQ_HEAD(,aac_command)	aac_free;	/* command structures available for reuse */
268     TAILQ_HEAD(,aac_command)	aac_ready;	/* commands on hold for controller resources */
269     TAILQ_HEAD(,aac_command)	aac_busy;
270     TAILQ_HEAD(,aac_command)	aac_complete;	/* commands which have been returned by the controller */
271     struct bio_queue_head	aac_bioq;
272     struct aac_queue_table	*aac_queues;
273     struct aac_queue_entry	*aac_qentries[AAC_QUEUE_COUNT];
274 
275     struct aac_qstat		aac_qstat[AACQ_COUNT];	/* queue statistics */
276 
277     /* connected containters */
278     struct aac_container	aac_container[AAC_MAX_CONTAINERS];
279 
280     /* delayed activity infrastructure */
281 #if __FreeBSD_version >= 500005
282     struct task			aac_task_complete;	/* deferred-completion task */
283 #endif
284     struct intr_config_hook	aac_ich;
285 
286     /* management interface */
287     dev_t			aac_dev_t;
288     struct aac_aif_command	aac_aifq[AAC_AIFQ_LENGTH];
289     int				aac_aifq_head;
290     int				aac_aifq_tail;
291 };
292 
293 
294 /*
295  * Public functions
296  */
297 extern void		aac_free(struct aac_softc *sc);
298 extern int		aac_attach(struct aac_softc *sc);
299 extern int		aac_detach(device_t dev);
300 extern int		aac_shutdown(device_t dev);
301 extern int		aac_suspend(device_t dev);
302 extern int		aac_resume(device_t dev);
303 extern void		aac_intr(void *arg);
304 extern devclass_t	aac_devclass;
305 extern void		aac_submit_bio(struct bio *bp);
306 extern void		aac_biodone(struct bio *bp);
307 
308 /*
309  * Debugging levels:
310  *  0 - quiet, only emit warnings
311  *  1 - noisy, emit major function points and things done
312  *  2 - extremely noisy, emit trace items in loops, etc.
313  */
314 #ifdef AAC_DEBUG
315 # define debug(level, fmt, args...)						\
316     do {									\
317 	if (level <= AAC_DEBUG) printf("%s: " fmt "\n", __FUNCTION__ , ##args);	\
318     } while(0)
319 # define debug_called(level)						\
320     do {								\
321 	if (level <= AAC_DEBUG) printf(__FUNCTION__ ": called\n");	\
322     } while(0)
323 
324 extern void	aac_print_queues(struct aac_softc *sc);
325 extern void	aac_panic(struct aac_softc *sc, char *reason);
326 extern void	aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, char *caller);
327 extern void	aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif);
328 
329 # define AAC_PRINT_FIB(sc, fib)	aac_print_fib(sc, fib, __FUNCTION__)
330 
331 #else
332 # define debug(level, fmt, args...)
333 # define debug_called(level)
334 
335 # define aac_print_queues(sc)
336 # define aac_panic(sc, reason)
337 # define aac_print_aif(sc, aif)
338 
339 # define AAC_PRINT_FIB(sc, fib)
340 #endif
341 
342 struct aac_code_lookup {
343     char	*string;
344     u_int32_t	code;
345 };
346 
347 /********************************************************************************
348  * Queue primitives for driver queues.
349  */
350 #define AACQ_ADD(sc, qname)					\
351 	do {							\
352 	    struct aac_qstat *qs = &(sc)->aac_qstat[qname];	\
353 								\
354 	    qs->q_length++;					\
355 	    if (qs->q_length > qs->q_max)			\
356 		qs->q_max = qs->q_length;			\
357 	} while(0)
358 
359 #define AACQ_REMOVE(sc, qname)    (sc)->aac_qstat[qname].q_length--
360 #define AACQ_INIT(sc, qname)			\
361 	do {					\
362 	    sc->aac_qstat[qname].q_length = 0;	\
363 	    sc->aac_qstat[qname].q_max = 0;	\
364 	} while(0)
365 
366 
367 #define AACQ_COMMAND_QUEUE(name, index)					\
368 static __inline void							\
369 aac_initq_ ## name (struct aac_softc *sc)				\
370 {									\
371     TAILQ_INIT(&sc->aac_ ## name);					\
372     AACQ_INIT(sc, index);						\
373 }									\
374 static __inline void							\
375 aac_enqueue_ ## name (struct aac_command *cm)				\
376 {									\
377     int		s;							\
378 									\
379     s = splbio();							\
380     TAILQ_INSERT_TAIL(&cm->cm_sc->aac_ ## name, cm, cm_link);		\
381     AACQ_ADD(cm->cm_sc, index);						\
382     splx(s);								\
383 }									\
384 static __inline void							\
385 aac_requeue_ ## name (struct aac_command *cm)				\
386 {									\
387     int		s;							\
388 									\
389     s = splbio();							\
390     TAILQ_INSERT_HEAD(&cm->cm_sc->aac_ ## name, cm, cm_link);		\
391     AACQ_ADD(cm->cm_sc, index);						\
392     splx(s);								\
393 }									\
394 static __inline struct aac_command *					\
395 aac_dequeue_ ## name (struct aac_softc *sc)				\
396 {									\
397     struct aac_command	*cm;						\
398     int			s;						\
399 									\
400     s = splbio();							\
401     if ((cm = TAILQ_FIRST(&sc->aac_ ## name)) != NULL) {		\
402 	TAILQ_REMOVE(&sc->aac_ ## name, cm, cm_link);			\
403 	AACQ_REMOVE(sc, index);						\
404     }									\
405     splx(s);								\
406     return(cm);								\
407 }									\
408 static __inline void							\
409 aac_remove_ ## name (struct aac_command *cm)				\
410 {									\
411     int			s;						\
412 									\
413     s = splbio();							\
414     TAILQ_REMOVE(&cm->cm_sc->aac_ ## name, cm, cm_link);		\
415     AACQ_REMOVE(cm->cm_sc, index);					\
416     splx(s);								\
417 }									\
418 struct hack
419 
420 AACQ_COMMAND_QUEUE(free, AACQ_FREE);
421 AACQ_COMMAND_QUEUE(ready, AACQ_READY);
422 AACQ_COMMAND_QUEUE(busy, AACQ_BUSY);
423 AACQ_COMMAND_QUEUE(complete, AACQ_COMPLETE);
424 
425 /*
426  * outstanding bio queue
427  */
428 static __inline void
429 aac_initq_bio(struct aac_softc *sc)
430 {
431     bioq_init(&sc->aac_bioq);
432     AACQ_INIT(sc, AACQ_BIO);
433 }
434 
435 static __inline void
436 aac_enqueue_bio(struct aac_softc *sc, struct bio *bp)
437 {
438     int		s;
439 
440     s = splbio();
441     bioq_insert_tail(&sc->aac_bioq, bp);
442     AACQ_ADD(sc, AACQ_BIO);
443     splx(s);
444 }
445 
446 static __inline struct bio *
447 aac_dequeue_bio(struct aac_softc *sc)
448 {
449     int		s;
450     struct bio	*bp;
451 
452     s = splbio();
453     if ((bp = bioq_first(&sc->aac_bioq)) != NULL) {
454 	bioq_remove(&sc->aac_bioq, bp);
455 	AACQ_REMOVE(sc, AACQ_BIO);
456     }
457     splx(s);
458     return(bp);
459 }
460