]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/dev/mfi/mfivar.h
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / dev / mfi / mfivar.h
1 /*-
2  * Copyright (c) 2006 IronPort Systems
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 /*-
27  * Copyright (c) 2007 LSI Corp.
28  * Copyright (c) 2007 Rajesh Prabhakaran.
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  *
40  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  */
52
53 #ifndef _MFIVAR_H
54 #define _MFIVAR_H
55
56 #include <sys/cdefs.h>
57 __FBSDID("$FreeBSD$");
58
59 #include <sys/lock.h>
60 #include <sys/sx.h>
61
62 /*
63  * SCSI structures and definitions are used from here, but no linking
64  * requirements are made to CAM.
65  */
66 #include <cam/scsi/scsi_all.h>
67
68 struct mfi_hwcomms {
69         uint32_t                hw_pi;
70         uint32_t                hw_ci;
71         uint32_t                hw_reply_q[1];
72 };
73
74 struct mfi_softc;
75 struct disk;
76 struct ccb_hdr;
77
78 struct mfi_command {
79         TAILQ_ENTRY(mfi_command) cm_link;
80         time_t                  cm_timestamp;
81         struct mfi_softc        *cm_sc;
82         union mfi_frame         *cm_frame;
83         uint32_t                cm_frame_busaddr;
84         struct mfi_sense        *cm_sense;
85         uint32_t                cm_sense_busaddr;
86         bus_dmamap_t            cm_dmamap;
87         union mfi_sgl           *cm_sg;
88         void                    *cm_data;
89         int                     cm_len;
90         int                     cm_total_frame_size;
91         int                     cm_extra_frames;
92         int                     cm_flags;
93 #define MFI_CMD_MAPPED          (1<<0)
94 #define MFI_CMD_DATAIN          (1<<1)
95 #define MFI_CMD_DATAOUT         (1<<2)
96 #define MFI_CMD_COMPLETED       (1<<3)
97 #define MFI_CMD_POLLED          (1<<4)
98 #define MFI_ON_MFIQ_FREE        (1<<5)
99 #define MFI_ON_MFIQ_READY       (1<<6)
100 #define MFI_ON_MFIQ_BUSY        (1<<7)
101 #define MFI_ON_MFIQ_MASK        ((1<<5)|(1<<6)|(1<<7))
102         int                     cm_aen_abort;
103         void                    (* cm_complete)(struct mfi_command *cm);
104         void                    *cm_private;
105         int                     cm_index;
106         int                     cm_error;
107 };
108
109 struct mfi_disk {
110         TAILQ_ENTRY(mfi_disk)   ld_link;
111         device_t        ld_dev;
112         int             ld_id;
113         int             ld_unit;
114         struct mfi_softc *ld_controller;
115         struct mfi_ld_info      *ld_info;
116         struct disk     *ld_disk;
117         int             ld_flags;
118 #define MFI_DISK_FLAGS_OPEN     0x01
119 #define MFI_DISK_FLAGS_DISABLED 0x02
120 };
121
122 struct mfi_aen {
123         TAILQ_ENTRY(mfi_aen) aen_link;
124         struct proc                     *p;
125 };
126
127 struct mfi_softc {
128         device_t                        mfi_dev;
129         int                             mfi_flags;
130 #define MFI_FLAGS_SG64          (1<<0)
131 #define MFI_FLAGS_QFRZN         (1<<1)
132 #define MFI_FLAGS_OPEN          (1<<2)
133 #define MFI_FLAGS_STOP          (1<<3)
134 #define MFI_FLAGS_1064R         (1<<4)
135 #define MFI_FLAGS_1078          (1<<5)
136 #define MFI_FLAGS_GEN2          (1<<6)
137
138         struct mfi_hwcomms              *mfi_comms;
139         TAILQ_HEAD(,mfi_command)        mfi_free;
140         TAILQ_HEAD(,mfi_command)        mfi_ready;
141         TAILQ_HEAD(,mfi_command)        mfi_busy;
142         struct bio_queue_head           mfi_bioq;
143         struct mfi_qstat                mfi_qstat[MFIQ_COUNT];
144
145         struct resource                 *mfi_regs_resource;
146         bus_space_handle_t              mfi_bhandle;
147         bus_space_tag_t                 mfi_btag;
148         int                             mfi_regs_rid;
149
150         bus_dma_tag_t                   mfi_parent_dmat;
151         bus_dma_tag_t                   mfi_buffer_dmat;
152
153         bus_dma_tag_t                   mfi_comms_dmat;
154         bus_dmamap_t                    mfi_comms_dmamap;
155         uint32_t                        mfi_comms_busaddr;
156
157         bus_dma_tag_t                   mfi_frames_dmat;
158         bus_dmamap_t                    mfi_frames_dmamap;
159         uint32_t                        mfi_frames_busaddr;
160         union mfi_frame                 *mfi_frames;
161
162         TAILQ_HEAD(,mfi_aen)            mfi_aen_pids;
163         struct mfi_command              *mfi_aen_cm;
164         uint32_t                        mfi_aen_triggered;
165         uint32_t                        mfi_poll_waiting;
166         struct selinfo                  mfi_select;
167         int                             mfi_delete_busy_volumes;
168         int                             mfi_keep_deleted_volumes;
169         int                             mfi_detaching;
170
171         bus_dma_tag_t                   mfi_sense_dmat;
172         bus_dmamap_t                    mfi_sense_dmamap;
173         uint32_t                        mfi_sense_busaddr;
174         struct mfi_sense                *mfi_sense;
175
176         struct resource                 *mfi_irq;
177         void                            *mfi_intr;
178         int                             mfi_irq_rid;
179
180         struct intr_config_hook         mfi_ich;
181         eventhandler_tag                eh;
182
183         /*
184          * Allocation for the command array.  Used as an indexable array to
185          * recover completed commands.
186          */
187         struct mfi_command              *mfi_commands;
188         /*
189          * How many commands were actually allocated
190          */
191         int                             mfi_total_cmds;
192         /*
193          * How many commands the firmware can handle.  Also how big the reply
194          * queue is, minus 1.
195          */
196         int                             mfi_max_fw_cmds;
197         /*
198          * How many S/G elements we'll ever actually use 
199          */
200         int                             mfi_max_sge;
201         /*
202          * How many bytes a compound frame is, including all of the extra frames
203          * that are used for S/G elements.
204          */
205         int                             mfi_cmd_size;
206         /*
207          * How large an S/G element is.  Used to calculate the number of single
208          * frames in a command.
209          */
210         int                             mfi_sge_size;
211         /*
212          * Max number of sectors that the firmware allows
213          */
214         uint32_t                        mfi_max_io;
215
216         TAILQ_HEAD(,mfi_disk)           mfi_ld_tqh;
217         eventhandler_tag                mfi_eh;
218         struct cdev                     *mfi_cdev;
219
220         TAILQ_HEAD(, ccb_hdr)           mfi_cam_ccbq;
221         struct mfi_command *            (* mfi_cam_start)(void *);
222         struct callout                  mfi_watchdog_callout;
223         struct mtx                      mfi_io_lock;
224         struct sx                       mfi_config_lock;
225
226         /* Controller type specific interfaces */
227         void    (*mfi_enable_intr)(struct mfi_softc *sc);
228         int32_t (*mfi_read_fw_status)(struct mfi_softc *sc);
229         int     (*mfi_check_clear_intr)(struct mfi_softc *sc);
230         void    (*mfi_issue_cmd)(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt);
231 };
232
233 extern int mfi_attach(struct mfi_softc *);
234 extern void mfi_free(struct mfi_softc *);
235 extern int mfi_shutdown(struct mfi_softc *);
236 extern void mfi_startio(struct mfi_softc *);
237 extern void mfi_disk_complete(struct bio *);
238 extern int mfi_disk_disable(struct mfi_disk *);
239 extern void mfi_disk_enable(struct mfi_disk *);
240 extern int mfi_dump_blocks(struct mfi_softc *, int id, uint64_t, void *, int);
241
242 #define MFIQ_ADD(sc, qname)                                     \
243         do {                                                    \
244                 struct mfi_qstat *qs;                           \
245                                                                 \
246                 qs = &(sc)->mfi_qstat[qname];                   \
247                 qs->q_length++;                                 \
248                 if (qs->q_length > qs->q_max)                   \
249                         qs->q_max = qs->q_length;               \
250         } while (0)
251
252 #define MFIQ_REMOVE(sc, qname)  (sc)->mfi_qstat[qname].q_length--
253
254 #define MFIQ_INIT(sc, qname)                                    \
255         do {                                                    \
256                 sc->mfi_qstat[qname].q_length = 0;              \
257                 sc->mfi_qstat[qname].q_max = 0;                 \
258         } while (0)
259
260 #define MFIQ_COMMAND_QUEUE(name, index)                                 \
261         static __inline void                                            \
262         mfi_initq_ ## name (struct mfi_softc *sc)                       \
263         {                                                               \
264                 TAILQ_INIT(&sc->mfi_ ## name);                          \
265                 MFIQ_INIT(sc, index);                                   \
266         }                                                               \
267         static __inline void                                            \
268         mfi_enqueue_ ## name (struct mfi_command *cm)                   \
269         {                                                               \
270                 if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {           \
271                         printf("command %p is on another queue, "       \
272                             "flags = %#x\n", cm, cm->cm_flags);         \
273                         panic("command is on another queue");           \
274                 }                                                       \
275                 TAILQ_INSERT_TAIL(&cm->cm_sc->mfi_ ## name, cm, cm_link); \
276                 cm->cm_flags |= MFI_ON_ ## index;                       \
277                 MFIQ_ADD(cm->cm_sc, index);                             \
278         }                                                               \
279         static __inline void                                            \
280         mfi_requeue_ ## name (struct mfi_command *cm)                   \
281         {                                                               \
282                 if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {           \
283                         printf("command %p is on another queue, "       \
284                             "flags = %#x\n", cm, cm->cm_flags);         \
285                         panic("command is on another queue");           \
286                 }                                                       \
287                 TAILQ_INSERT_HEAD(&cm->cm_sc->mfi_ ## name, cm, cm_link); \
288                 cm->cm_flags |= MFI_ON_ ## index;                       \
289                 MFIQ_ADD(cm->cm_sc, index);                             \
290         }                                                               \
291         static __inline struct mfi_command *                            \
292         mfi_dequeue_ ## name (struct mfi_softc *sc)                     \
293         {                                                               \
294                 struct mfi_command *cm;                                 \
295                                                                         \
296                 if ((cm = TAILQ_FIRST(&sc->mfi_ ## name)) != NULL) {    \
297                         if ((cm->cm_flags & MFI_ON_ ## index) == 0) {   \
298                                 printf("command %p not in queue, "      \
299                                     "flags = %#x, bit = %#x\n", cm,     \
300                                     cm->cm_flags, MFI_ON_ ## index);    \
301                                 panic("command not in queue");          \
302                         }                                               \
303                         TAILQ_REMOVE(&sc->mfi_ ## name, cm, cm_link);   \
304                         cm->cm_flags &= ~MFI_ON_ ## index;              \
305                         MFIQ_REMOVE(sc, index);                         \
306                 }                                                       \
307                 return (cm);                                            \
308         }                                                               \
309         static __inline void                                            \
310         mfi_remove_ ## name (struct mfi_command *cm)                    \
311         {                                                               \
312                 if ((cm->cm_flags & MFI_ON_ ## index) == 0) {           \
313                         printf("command %p not in queue, flags = %#x, " \
314                             "bit = %#x\n", cm, cm->cm_flags,            \
315                             MFI_ON_ ## index);                          \
316                         panic("command not in queue");                  \
317                 }                                                       \
318                 TAILQ_REMOVE(&cm->cm_sc->mfi_ ## name, cm, cm_link);    \
319                 cm->cm_flags &= ~MFI_ON_ ## index;                      \
320                 MFIQ_REMOVE(cm->cm_sc, index);                          \
321         }                                                               \
322 struct hack
323
324 MFIQ_COMMAND_QUEUE(free, MFIQ_FREE);
325 MFIQ_COMMAND_QUEUE(ready, MFIQ_READY);
326 MFIQ_COMMAND_QUEUE(busy, MFIQ_BUSY);
327
328 static __inline void
329 mfi_initq_bio(struct mfi_softc *sc)
330 {
331         bioq_init(&sc->mfi_bioq);
332         MFIQ_INIT(sc, MFIQ_BIO);
333 }
334
335 static __inline void
336 mfi_enqueue_bio(struct mfi_softc *sc, struct bio *bp)
337 {
338         bioq_insert_tail(&sc->mfi_bioq, bp);
339         MFIQ_ADD(sc, MFIQ_BIO);
340 }
341
342 static __inline struct bio *
343 mfi_dequeue_bio(struct mfi_softc *sc)
344 {
345         struct bio *bp;
346
347         if ((bp = bioq_first(&sc->mfi_bioq)) != NULL) {
348                 bioq_remove(&sc->mfi_bioq, bp);
349                 MFIQ_REMOVE(sc, MFIQ_BIO);
350         }
351         return (bp);
352 }
353
354 static __inline void
355 mfi_print_sense(struct mfi_softc *sc, void *sense)
356 {
357         int error, key, asc, ascq;
358
359         scsi_extract_sense((struct scsi_sense_data *)sense,
360             &error, &key, &asc, &ascq);
361         device_printf(sc->mfi_dev, "sense error %d, sense_key %d, "
362             "asc %d, ascq %d\n", error, key, asc, ascq);
363 }
364
365
366 #define MFI_WRITE4(sc, reg, val)        bus_space_write_4((sc)->mfi_btag, \
367         sc->mfi_bhandle, (reg), (val))
368 #define MFI_READ4(sc, reg)              bus_space_read_4((sc)->mfi_btag, \
369         (sc)->mfi_bhandle, (reg))
370 #define MFI_WRITE2(sc, reg, val)        bus_space_write_2((sc)->mfi_btag, \
371         sc->mfi_bhandle, (reg), (val))
372 #define MFI_READ2(sc, reg)              bus_space_read_2((sc)->mfi_btag, \
373         (sc)->mfi_bhandle, (reg))
374 #define MFI_WRITE1(sc, reg, val)        bus_space_write_1((sc)->mfi_btag, \
375         sc->mfi_bhandle, (reg), (val))
376 #define MFI_READ1(sc, reg)              bus_space_read_1((sc)->mfi_btag, \
377         (sc)->mfi_bhandle, (reg))
378
379 MALLOC_DECLARE(M_MFIBUF);
380
381 #define MFI_CMD_TIMEOUT 30
382 #define MFI_MAXPHYS (128 * 1024)
383
384 #ifdef MFI_DEBUG
385 extern void mfi_print_cmd(struct mfi_command *cm);
386 extern void mfi_dump_cmds(struct mfi_softc *sc);
387 extern void mfi_validate_sg(struct mfi_softc *, struct mfi_command *, const char *, int );
388 #define MFI_PRINT_CMD(cm)       mfi_print_cmd(cm)
389 #define MFI_DUMP_CMDS(sc)       mfi_dump_cmds(sc)
390 #define MFI_VALIDATE_CMD(sc, cm) mfi_validate_sg(sc, cm, __FUNCTION__, __LINE__)
391 #else
392 #define MFI_PRINT_CMD(cm)
393 #define MFI_DUMP_CMDS(sc)
394 #define MFI_VALIDATE_CMD(sc, cm)
395 #endif
396
397 extern void mfi_release_command(struct mfi_command *cm);
398
399 #endif /* _MFIVAR_H */