Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / dev / raid / amr / amrvar.h
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  * Copyright (c) 2002 Eric Moore
28  * Copyright (c) 2002 LSI Logic Corporation
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  * 1. Redistributions of source code must retain the above copyright
35  *    notice, this list of conditions and the following disclaimer.
36  * 2. Redistributions in binary form must reproduce the above copyright
37  *    notice, this list of conditions and the following disclaimer in the
38  *    documentation and/or other materials provided with the distribution.
39  * 3. The party using or redistributing the source code and binary forms
40  *    agrees to the disclaimer below and the terms and conditions set forth
41  *    herein.
42  *
43  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
44  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
47  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53  * SUCH DAMAGE.
54  *
55  *      $FreeBSD: src/sys/dev/amr/amrvar.h,v 1.2.2.5 2002/12/20 15:12:04 emoore Exp $
56  */
57
58 #if __FreeBSD_version >= 500005
59 # include <sys/taskqueue.h>
60 #endif
61
62 #ifdef AMR_DEBUG
63 # define debug(level, fmt, args...)     do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);} while(0)
64 # define debug_called(level)            do {if (level <= AMR_DEBUG) printf("%s: called\n", __func__);} while(0)
65 #else
66 # define debug(level, fmt, args...)
67 # define debug_called(level)
68 #endif
69 #define xdebug(fmt, args...)    printf("%s: " fmt "\n", __func__ , ##args)
70
71 /*
72  * Per-logical-drive datastructure
73  */
74 struct amr_logdrive
75 {
76     u_int32_t   al_size;
77     int         al_state;
78     int         al_properties;
79     
80     /* synthetic geometry */
81     int         al_cylinders;
82     int         al_heads;
83     int         al_sectors;
84     
85     /* driver */
86     device_t    al_disk;
87 };
88
89 /*
90  * Due to the difficulty of using the zone allocator to create a new
91  * zone from within a module, we use our own clustering to reduce 
92  * memory wastage due to allocating lots of these small structures.
93  *
94  * 16k gives us a little under 200 command structures, which should
95  * normally be plenty.  We will grab more if we need them.
96  */
97
98 #define AMR_CMD_CLUSTERSIZE     (16 * 1024)
99
100 /*
101  * Per-command control structure.
102  */
103 struct amr_command
104 {
105     TAILQ_ENTRY(amr_command)    ac_link;
106
107     struct amr_softc            *ac_sc;
108     u_int8_t                    ac_slot;
109     int                         ac_status;      /* command completion status */
110     struct amr_mailbox          ac_mailbox;
111     int                         ac_flags;
112 #define AMR_CMD_DATAIN          (1<<0)
113 #define AMR_CMD_DATAOUT         (1<<1)
114 #define AMR_CMD_CCB_DATAIN      (1<<2)
115 #define AMR_CMD_CCB_DATAOUT     (1<<3)
116 #define AMR_CMD_PRIORITY        (1<<4)
117 #define AMR_CMD_MAPPED          (1<<5)
118 #define AMR_CMD_SLEEP           (1<<6)
119 #define AMR_CMD_BUSY            (1<<7)
120
121     struct bio                  *ac_bio;
122
123     void                        *ac_data;
124     size_t                      ac_length;
125     bus_dmamap_t                ac_dmamap;
126     u_int32_t                   ac_dataphys;
127
128     void                        *ac_ccb_data;
129     size_t                      ac_ccb_length;
130     bus_dmamap_t                ac_ccb_dmamap;
131     u_int32_t                   ac_ccb_dataphys;
132
133     void                        (* ac_complete)(struct amr_command *ac);
134     void                        *ac_private;
135 };
136
137 struct amr_command_cluster
138 {
139     TAILQ_ENTRY(amr_command_cluster)    acc_link;
140     struct amr_command          acc_command[0];
141 };
142
143 #define AMR_CMD_CLUSTERCOUNT    ((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) /   \
144                                  sizeof(struct amr_command))
145
146 /*
147  * Per-controller-instance data
148  */
149 struct amr_softc 
150 {
151     /* bus attachments */
152     device_t                    amr_dev;
153     struct resource             *amr_reg;               /* control registers */
154     bus_space_handle_t          amr_bhandle;
155     bus_space_tag_t             amr_btag;
156     bus_dma_tag_t               amr_parent_dmat;        /* parent DMA tag */
157     bus_dma_tag_t               amr_buffer_dmat;        /* data buffer DMA tag */
158     struct resource             *amr_irq;               /* interrupt */
159     void                        *amr_intr;
160
161     /* mailbox */
162     volatile struct amr_mailbox         *amr_mailbox;
163     volatile struct amr_mailbox64       *amr_mailbox64;
164     u_int32_t                   amr_mailboxphys;
165     bus_dma_tag_t               amr_mailbox_dmat;
166     bus_dmamap_t                amr_mailbox_dmamap;
167
168     /* scatter/gather lists and their controller-visible mappings */
169     struct amr_sgentry          *amr_sgtable;           /* s/g lists */
170     u_int32_t                   amr_sgbusaddr;          /* s/g table base address in bus space */
171     bus_dma_tag_t               amr_sg_dmat;            /* s/g buffer DMA tag */
172     bus_dmamap_t                amr_sg_dmamap;          /* map for s/g buffers */
173
174     /* controller limits and features */
175     int                         amr_maxio;              /* maximum number of I/O transactions */
176     int                         amr_maxdrives;          /* max number of logical drives */
177     int                         amr_maxchan;            /* count of SCSI channels */
178     
179     /* connected logical drives */
180     struct amr_logdrive         amr_drive[AMR_MAXLD];
181
182     /* controller state */
183     int                         amr_state;
184 #define AMR_STATE_OPEN          (1<<0)
185 #define AMR_STATE_SUSPEND       (1<<1)
186 #define AMR_STATE_INTEN         (1<<2)
187 #define AMR_STATE_SHUTDOWN      (1<<3)
188
189     /* per-controller queues */
190     struct bio_queue_head       amr_bioq;               /* pending I/O with no commands */
191     TAILQ_HEAD(,amr_command)    amr_ready;              /* commands ready to be submitted */
192     struct amr_command          *amr_busycmd[AMR_MAXCMD];
193     int                         amr_busyslots;
194     TAILQ_HEAD(,amr_command)    amr_completed;
195     TAILQ_HEAD(,amr_command)    amr_freecmds;
196     TAILQ_HEAD(,amr_command_cluster)    amr_cmd_clusters;
197
198     /* CAM attachments for passthrough */
199     struct cam_sim              *amr_cam_sim[AMR_MAX_CHANNELS];
200     TAILQ_HEAD(, ccb_hdr)       amr_cam_ccbq;
201
202     /* control device */
203     dev_t                       amr_dev_t;
204
205     /* controller type-specific support */
206     int                         amr_type;
207 #define AMR_TYPE_QUARTZ         (1<<0)
208 #define AMR_IS_QUARTZ(sc)       ((sc)->amr_type & AMR_TYPE_QUARTZ)
209 #define AMR_TYPE_40LD           (1<<1)
210 #define AMR_IS_40LD(sc)         ((sc)->amr_type & AMR_TYPE_40LD)
211     int                         (* amr_submit_command)(struct amr_softc *sc);
212     int                         (* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
213     int                         (*amr_poll_command)(struct amr_command *ac);
214     int                         support_ext_cdb;        /* greater than 10 byte cdb support */
215
216     /* misc glue */
217     struct intr_config_hook     amr_ich;                /* wait-for-interrupts probe hook */
218     struct callout_handle       amr_timeout;            /* periodic status check */
219 #if __FreeBSD_version >= 500005
220     struct task                 amr_task_complete;      /* deferred-completion task */
221 #endif
222 };
223
224 /*
225  * Interface between bus connections and driver core.
226  */
227 extern int              amr_attach(struct amr_softc *sc);
228 extern void             amr_free(struct amr_softc *sc);
229 extern int              amr_flush(struct amr_softc *sc);
230 extern int              amr_done(struct amr_softc *sc);
231 extern void             amr_startio(struct amr_softc *sc);
232
233 /*
234  * Command buffer allocation.
235  */
236 extern struct amr_command       *amr_alloccmd(struct amr_softc *sc);
237 extern void                     amr_releasecmd(struct amr_command *ac);
238
239 /*
240  * CAM interface
241  */
242 extern int              amr_cam_attach(struct amr_softc *sc);
243 extern void             amr_cam_detach(struct amr_softc *sc);
244 extern int              amr_cam_command(struct amr_softc *sc, struct amr_command **acp);
245
246 /*
247  * MegaRAID logical disk driver
248  */
249 struct amrd_softc 
250 {
251     device_t            amrd_dev;
252     dev_t               amrd_dev_t;
253     struct amr_softc    *amrd_controller;
254     struct amr_logdrive *amrd_drive;
255     struct disk         amrd_disk;
256     struct devstat      amrd_stats;
257     int                 amrd_unit;
258     int                 amrd_flags;
259 #define AMRD_OPEN       (1<<0)          /* drive is open (can't detach) */
260 };
261
262 /*
263  * Interface between driver core and disk driver (should be using a bus?)
264  */
265 extern int      amr_submit_bio(struct amr_softc *sc, struct bio *bio);
266 extern void     amrd_intr(void *data);
267
268 /********************************************************************************
269  * Enqueue/dequeue functions
270  */
271 static __inline void
272 amr_enqueue_bio(struct amr_softc *sc, struct bio *bio)
273 {
274     int         s;
275
276     s = splbio();
277     bioq_insert_tail(&sc->amr_bioq, bio);
278     splx(s);
279 }
280
281 static __inline struct bio *
282 amr_dequeue_bio(struct amr_softc *sc)
283 {
284     struct bio  *bio;
285     int         s;
286
287     s = splbio();
288     if ((bio = bioq_first(&sc->amr_bioq)) != NULL)
289         bioq_remove(&sc->amr_bioq, bio);
290     splx(s);
291     return(bio);
292 }
293
294 static __inline void
295 amr_enqueue_ready(struct amr_command *ac)
296 {
297     int         s;
298
299     s = splbio();
300     TAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link);
301     splx(s);
302 }
303
304 static __inline void
305 amr_requeue_ready(struct amr_command *ac)
306 {
307     int         s;
308
309     s = splbio();
310     TAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link);
311     splx(s);
312 }
313
314 static __inline struct amr_command *
315 amr_dequeue_ready(struct amr_softc *sc)
316 {
317     struct amr_command  *ac;
318     int                 s;
319
320     s = splbio();
321     if ((ac = TAILQ_FIRST(&sc->amr_ready)) != NULL)
322         TAILQ_REMOVE(&sc->amr_ready, ac, ac_link);
323     splx(s);
324     return(ac);
325 }
326
327 static __inline void
328 amr_enqueue_completed(struct amr_command *ac)
329 {
330     int         s;
331
332     s = splbio();
333     TAILQ_INSERT_TAIL(&ac->ac_sc->amr_completed, ac, ac_link);
334     splx(s);
335 }
336
337 static __inline struct amr_command *
338 amr_dequeue_completed(struct amr_softc *sc)
339 {
340     struct amr_command  *ac;
341     int                 s;
342
343     s = splbio();
344     if ((ac = TAILQ_FIRST(&sc->amr_completed)) != NULL)
345         TAILQ_REMOVE(&sc->amr_completed, ac, ac_link);
346     splx(s);
347     return(ac);
348 }
349
350 static __inline void
351 amr_enqueue_free(struct amr_command *ac)
352 {
353     int         s;
354
355     s = splbio();
356     TAILQ_INSERT_TAIL(&ac->ac_sc->amr_freecmds, ac, ac_link);
357     splx(s);
358 }
359
360 static __inline struct amr_command *
361 amr_dequeue_free(struct amr_softc *sc)
362 {
363     struct amr_command  *ac;
364     int                 s;
365
366     s = splbio();
367     if ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL)
368         TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link);
369     splx(s);
370     return(ac);
371 }