amrvar.h revision 89055
1/*-
2 * Copyright (c) 1999,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: head/sys/dev/amr/amrvar.h 89055 2002-01-08 06:47:02Z msmith $
28 */
29
30#if __FreeBSD_version >= 500005
31# include <sys/taskqueue.h>
32#endif
33
34#ifdef AMR_DEBUG
35# define debug(level, fmt, args...)	do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);} while(0)
36# define debug_called(level)		do {if (level <= AMR_DEBUG) printf("%s: called\n", __func__);} while(0)
37#else
38# define debug(level, fmt, args...)
39# define debug_called(level)
40#endif
41#define xdebug(fmt, args...)	printf("%s: " fmt "\n", __func__ , ##args)
42
43/*
44 * Per-logical-drive datastructure
45 */
46struct amr_logdrive
47{
48    u_int32_t	al_size;
49    int		al_state;
50    int		al_properties;
51
52    /* synthetic geometry */
53    int		al_cylinders;
54    int		al_heads;
55    int		al_sectors;
56
57    /* driver */
58    device_t	al_disk;
59};
60
61/*
62 * Due to the difficulty of using the zone allocator to create a new
63 * zone from within a module, we use our own clustering to reduce
64 * memory wastage due to allocating lots of these small structures.
65 *
66 * 16k gives us a little under 200 command structures, which should
67 * normally be plenty.  We will grab more if we need them.
68 */
69
70#define AMR_CMD_CLUSTERSIZE	(16 * 1024)
71
72/*
73 * Per-command control structure.
74 */
75struct amr_command
76{
77    TAILQ_ENTRY(amr_command)	ac_link;
78
79    struct amr_softc		*ac_sc;
80    u_int8_t			ac_slot;
81    int				ac_status;	/* command completion status */
82    struct amr_mailbox		ac_mailbox;
83    int				ac_flags;
84#define AMR_CMD_DATAIN		(1<<0)
85#define AMR_CMD_DATAOUT		(1<<1)
86#define AMR_CMD_CCB_DATAIN	(1<<2)
87#define AMR_CMD_CCB_DATAOUT	(1<<3)
88#define AMR_CMD_PRIORITY	(1<<4)
89#define AMR_CMD_MAPPED		(1<<5)
90#define AMR_CMD_SLEEP		(1<<6)
91#define AMR_CMD_BUSY		(1<<7)
92
93    struct bio			*ac_bio;
94
95    void			*ac_data;
96    size_t			ac_length;
97    bus_dmamap_t		ac_dmamap;
98    u_int32_t			ac_dataphys;
99
100    void			*ac_ccb_data;
101    size_t			ac_ccb_length;
102    bus_dmamap_t		ac_ccb_dmamap;
103    u_int32_t			ac_ccb_dataphys;
104
105    void			(* ac_complete)(struct amr_command *ac);
106};
107
108struct amr_command_cluster
109{
110    TAILQ_ENTRY(amr_command_cluster)	acc_link;
111    struct amr_command		acc_command[0];
112};
113
114#define AMR_CMD_CLUSTERCOUNT	((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) /	\
115				 sizeof(struct amr_command))
116
117/*
118 * Per-controller-instance data
119 */
120struct amr_softc
121{
122    /* bus attachments */
123    device_t			amr_dev;
124    struct resource		*amr_reg;		/* control registers */
125    bus_space_handle_t		amr_bhandle;
126    bus_space_tag_t		amr_btag;
127    bus_dma_tag_t		amr_parent_dmat;	/* parent DMA tag */
128    bus_dma_tag_t		amr_buffer_dmat;	/* data buffer DMA tag */
129    struct resource		*amr_irq;		/* interrupt */
130    void			*amr_intr;
131
132    /* mailbox */
133    volatile struct amr_mailbox		*amr_mailbox;
134    volatile struct amr_mailbox64	*amr_mailbox64;
135    u_int32_t			amr_mailboxphys;
136    bus_dma_tag_t		amr_mailbox_dmat;
137    bus_dmamap_t		amr_mailbox_dmamap;
138
139    /* scatter/gather lists and their controller-visible mappings */
140    struct amr_sgentry		*amr_sgtable;		/* s/g lists */
141    u_int32_t			amr_sgbusaddr;		/* s/g table base address in bus space */
142    bus_dma_tag_t		amr_sg_dmat;		/* s/g buffer DMA tag */
143    bus_dmamap_t		amr_sg_dmamap;		/* map for s/g buffers */
144
145    /* controller limits and features */
146    int				amr_maxio;		/* maximum number of I/O transactions */
147    int				amr_maxdrives;		/* max number of logical drives */
148    int				amr_maxchan;		/* count of SCSI channels */
149
150    /* connected logical drives */
151    struct amr_logdrive		amr_drive[AMR_MAXLD];
152
153    /* controller state */
154    int				amr_state;
155#define AMR_STATE_OPEN		(1<<0)
156#define AMR_STATE_SUSPEND	(1<<1)
157#define AMR_STATE_INTEN		(1<<2)
158#define AMR_STATE_SHUTDOWN	(1<<3)
159
160    /* per-controller queues */
161    struct bio_queue_head 	amr_bioq;		/* pending I/O with no commands */
162    TAILQ_HEAD(,amr_command)	amr_ready;		/* commands ready to be submitted */
163    struct amr_command		*amr_busycmd[AMR_MAXCMD];
164    int				amr_busyslots;
165    TAILQ_HEAD(,amr_command)	amr_completed;
166    TAILQ_HEAD(,amr_command)	amr_freecmds;
167    TAILQ_HEAD(,amr_command_cluster)	amr_cmd_clusters;
168
169    /* CAM attachments for passthrough */
170    struct cam_sim		*amr_cam_sim[AMR_MAX_CHANNELS];
171    TAILQ_HEAD(, ccb_hdr)	amr_cam_ccbq;
172
173    /* control device */
174    dev_t			amr_dev_t;
175
176    /* controller type-specific support */
177    int				amr_type;
178#define AMR_TYPE_QUARTZ		(1<<0)
179#define AMR_IS_QUARTZ(sc)	((sc)->amr_type & AMR_TYPE_QUARTZ)
180#define AMR_TYPE_40LD		(1<<1)
181#define AMR_IS_40LD(sc)		((sc)->amr_type & AMR_TYPE_40LD)
182    int				(* amr_submit_command)(struct amr_softc *sc);
183    int				(* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
184
185    /* misc glue */
186    struct intr_config_hook	amr_ich;		/* wait-for-interrupts probe hook */
187    struct callout_handle	amr_timeout;		/* periodic status check */
188#if __FreeBSD_version >= 500005
189    struct task			amr_task_complete;	/* deferred-completion task */
190#endif
191};
192
193/*
194 * Interface between bus connections and driver core.
195 */
196extern int              amr_attach(struct amr_softc *sc);
197extern void		amr_free(struct amr_softc *sc);
198extern int		amr_flush(struct amr_softc *sc);
199extern int		amr_done(struct amr_softc *sc);
200extern void		amr_startio(struct amr_softc *sc);
201
202/*
203 * Command buffer allocation.
204 */
205extern struct amr_command	*amr_alloccmd(struct amr_softc *sc);
206extern void			amr_releasecmd(struct amr_command *ac);
207
208/*
209 * CAM interface
210 */
211extern int		amr_cam_attach(struct amr_softc *sc);
212extern void		amr_cam_detach(struct amr_softc *sc);
213extern int		amr_cam_command(struct amr_softc *sc, struct amr_command **acp);
214
215/*
216 * MegaRAID logical disk driver
217 */
218struct amrd_softc
219{
220    device_t		amrd_dev;
221    dev_t		amrd_dev_t;
222    struct amr_softc	*amrd_controller;
223    struct amr_logdrive	*amrd_drive;
224    struct disk		amrd_disk;
225    struct devstat	amrd_stats;
226    struct disklabel	amrd_label;
227    int			amrd_unit;
228    int			amrd_flags;
229#define AMRD_OPEN	(1<<0)		/* drive is open (can't detach) */
230};
231
232/*
233 * Interface between driver core and disk driver (should be using a bus?)
234 */
235extern int	amr_submit_bio(struct amr_softc *sc, struct bio *bio);
236extern void	amrd_intr(void *data);
237
238/********************************************************************************
239 * Enqueue/dequeue functions
240 */
241static __inline void
242amr_enqueue_bio(struct amr_softc *sc, struct bio *bio)
243{
244    int		s;
245
246    s = splbio();
247    bioq_insert_tail(&sc->amr_bioq, bio);
248    splx(s);
249}
250
251static __inline struct bio *
252amr_dequeue_bio(struct amr_softc *sc)
253{
254    struct bio	*bio;
255    int		s;
256
257    s = splbio();
258    if ((bio = bioq_first(&sc->amr_bioq)) != NULL)
259	bioq_remove(&sc->amr_bioq, bio);
260    splx(s);
261    return(bio);
262}
263
264static __inline void
265amr_enqueue_ready(struct amr_command *ac)
266{
267    int		s;
268
269    s = splbio();
270    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link);
271    splx(s);
272}
273
274static __inline void
275amr_requeue_ready(struct amr_command *ac)
276{
277    int		s;
278
279    s = splbio();
280    TAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link);
281    splx(s);
282}
283
284static __inline struct amr_command *
285amr_dequeue_ready(struct amr_softc *sc)
286{
287    struct amr_command	*ac;
288    int			s;
289
290    s = splbio();
291    if ((ac = TAILQ_FIRST(&sc->amr_ready)) != NULL)
292	TAILQ_REMOVE(&sc->amr_ready, ac, ac_link);
293    splx(s);
294    return(ac);
295}
296
297static __inline void
298amr_enqueue_completed(struct amr_command *ac)
299{
300    int		s;
301
302    s = splbio();
303    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_completed, ac, ac_link);
304    splx(s);
305}
306
307static __inline struct amr_command *
308amr_dequeue_completed(struct amr_softc *sc)
309{
310    struct amr_command	*ac;
311    int			s;
312
313    s = splbio();
314    if ((ac = TAILQ_FIRST(&sc->amr_completed)) != NULL)
315	TAILQ_REMOVE(&sc->amr_completed, ac, ac_link);
316    splx(s);
317    return(ac);
318}
319
320static __inline void
321amr_enqueue_free(struct amr_command *ac)
322{
323    int		s;
324
325    s = splbio();
326    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_freecmds, ac, ac_link);
327    splx(s);
328}
329
330static __inline struct amr_command *
331amr_dequeue_free(struct amr_softc *sc)
332{
333    struct amr_command	*ac;
334    int			s;
335
336    s = splbio();
337    if ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL)
338	TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link);
339    splx(s);
340    return(ac);
341}
342