amrvar.h revision 65245
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 65245 2000-08-30 07:52:50Z 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", __FUNCTION__ , ##args);} while(0)
36# define debug_called(level)		do {if (level <= AMR_DEBUG) printf("%s: called\n", __FUNCTION__);} 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", __FUNCTION__ , ##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
202extern devclass_t	amr_devclass;
203
204/*
205 * Command buffer allocation.
206 */
207extern struct amr_command	*amr_alloccmd(struct amr_softc *sc);
208extern void			amr_releasecmd(struct amr_command *ac);
209
210/*
211 * CAM interface
212 */
213extern int		amr_cam_attach(struct amr_softc *sc);
214extern void		amr_cam_detach(struct amr_softc *sc);
215extern int		amr_cam_command(struct amr_softc *sc, struct amr_command **acp);
216
217/*
218 * MegaRAID logical disk driver
219 */
220struct amrd_softc
221{
222    device_t		amrd_dev;
223    dev_t		amrd_dev_t;
224    struct amr_softc	*amrd_controller;
225    struct amr_logdrive	*amrd_drive;
226    struct disk		amrd_disk;
227    struct devstat	amrd_stats;
228    struct disklabel	amrd_label;
229    int			amrd_unit;
230    int			amrd_flags;
231#define AMRD_OPEN	(1<<0)		/* drive is open (can't detach) */
232};
233
234/*
235 * Interface between driver core and disk driver (should be using a bus?)
236 */
237extern int	amr_submit_bio(struct amr_softc *sc, struct bio *bio);
238extern void	amrd_intr(void *data);
239
240/********************************************************************************
241 * Enqueue/dequeue functions
242 */
243static __inline void
244amr_enqueue_bio(struct amr_softc *sc, struct bio *bio)
245{
246    int		s;
247
248    s = splbio();
249    bioq_insert_tail(&sc->amr_bioq, bio);
250    splx(s);
251}
252
253static __inline struct bio *
254amr_dequeue_bio(struct amr_softc *sc)
255{
256    struct bio	*bio;
257    int		s;
258
259    s = splbio();
260    if ((bio = bioq_first(&sc->amr_bioq)) != NULL)
261	bioq_remove(&sc->amr_bioq, bio);
262    splx(s);
263    return(bio);
264}
265
266static __inline void
267amr_enqueue_ready(struct amr_command *ac)
268{
269    int		s;
270
271    s = splbio();
272    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link);
273    splx(s);
274}
275
276static __inline void
277amr_requeue_ready(struct amr_command *ac)
278{
279    int		s;
280
281    s = splbio();
282    TAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link);
283    splx(s);
284}
285
286static __inline struct amr_command *
287amr_dequeue_ready(struct amr_softc *sc)
288{
289    struct amr_command	*ac;
290    int			s;
291
292    s = splbio();
293    if ((ac = TAILQ_FIRST(&sc->amr_ready)) != NULL)
294	TAILQ_REMOVE(&sc->amr_ready, ac, ac_link);
295    splx(s);
296    return(ac);
297}
298
299static __inline void
300amr_enqueue_completed(struct amr_command *ac)
301{
302    int		s;
303
304    s = splbio();
305    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_completed, ac, ac_link);
306    splx(s);
307}
308
309static __inline struct amr_command *
310amr_dequeue_completed(struct amr_softc *sc)
311{
312    struct amr_command	*ac;
313    int			s;
314
315    s = splbio();
316    if ((ac = TAILQ_FIRST(&sc->amr_completed)) != NULL)
317	TAILQ_REMOVE(&sc->amr_completed, ac, ac_link);
318    splx(s);
319    return(ac);
320}
321
322static __inline void
323amr_enqueue_free(struct amr_command *ac)
324{
325    int		s;
326
327    s = splbio();
328    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_freecmds, ac, ac_link);
329    splx(s);
330}
331
332static __inline struct amr_command *
333amr_dequeue_free(struct amr_softc *sc)
334{
335    struct amr_command	*ac;
336    int			s;
337
338    s = splbio();
339    if ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL)
340	TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link);
341    splx(s);
342    return(ac);
343}
344