]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - sys/dev/mfi/mfivar.h
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.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_stp_len;
91         int                     cm_total_frame_size;
92         int                     cm_extra_frames;
93         int                     cm_flags;
94 #define MFI_CMD_MAPPED          (1<<0)
95 #define MFI_CMD_DATAIN          (1<<1)
96 #define MFI_CMD_DATAOUT         (1<<2)
97 #define MFI_CMD_COMPLETED       (1<<3)
98 #define MFI_CMD_POLLED          (1<<4)
99 #define MFI_ON_MFIQ_FREE        (1<<5)
100 #define MFI_ON_MFIQ_READY       (1<<6)
101 #define MFI_ON_MFIQ_BUSY        (1<<7)
102 #define MFI_ON_MFIQ_MASK        ((1<<5)|(1<<6)|(1<<7))
103         int                     cm_aen_abort;
104         void                    (* cm_complete)(struct mfi_command *cm);
105         void                    *cm_private;
106         int                     cm_index;
107         int                     cm_error;
108 };
109
110 struct mfi_disk {
111         TAILQ_ENTRY(mfi_disk)   ld_link;
112         device_t        ld_dev;
113         int             ld_id;
114         int             ld_unit;
115         struct mfi_softc *ld_controller;
116         struct mfi_ld_info      *ld_info;
117         struct disk     *ld_disk;
118         int             ld_flags;
119 #define MFI_DISK_FLAGS_OPEN     0x01
120 #define MFI_DISK_FLAGS_DISABLED 0x02
121 };
122
123 struct mfi_aen {
124         TAILQ_ENTRY(mfi_aen) aen_link;
125         struct proc                     *p;
126 };
127
128 struct mfi_softc {
129         device_t                        mfi_dev;
130         int                             mfi_flags;
131 #define MFI_FLAGS_SG64          (1<<0)
132 #define MFI_FLAGS_QFRZN         (1<<1)
133 #define MFI_FLAGS_OPEN          (1<<2)
134 #define MFI_FLAGS_STOP          (1<<3)
135 #define MFI_FLAGS_1064R         (1<<4)
136 #define MFI_FLAGS_1078          (1<<5)
137 #define MFI_FLAGS_GEN2          (1<<6)
138
139         struct mfi_hwcomms              *mfi_comms;
140         TAILQ_HEAD(,mfi_command)        mfi_free;
141         TAILQ_HEAD(,mfi_command)        mfi_ready;
142         TAILQ_HEAD(,mfi_command)        mfi_busy;
143         struct bio_queue_head           mfi_bioq;
144         struct mfi_qstat                mfi_qstat[MFIQ_COUNT];
145
146         struct resource                 *mfi_regs_resource;
147         bus_space_handle_t              mfi_bhandle;
148         bus_space_tag_t                 mfi_btag;
149         int                             mfi_regs_rid;
150
151         bus_dma_tag_t                   mfi_parent_dmat;
152         bus_dma_tag_t                   mfi_buffer_dmat;
153
154         bus_dma_tag_t                   mfi_comms_dmat;
155         bus_dmamap_t                    mfi_comms_dmamap;
156         uint32_t                        mfi_comms_busaddr;
157
158         bus_dma_tag_t                   mfi_frames_dmat;
159         bus_dmamap_t                    mfi_frames_dmamap;
160         uint32_t                        mfi_frames_busaddr;
161         union mfi_frame                 *mfi_frames;
162
163         TAILQ_HEAD(,mfi_aen)            mfi_aen_pids;
164         struct mfi_command              *mfi_aen_cm;
165         uint32_t                        mfi_aen_triggered;
166         uint32_t                        mfi_poll_waiting;
167         struct selinfo                  mfi_select;
168         int                             mfi_delete_busy_volumes;
169         int                             mfi_keep_deleted_volumes;
170         int                             mfi_detaching;
171
172         bus_dma_tag_t                   mfi_sense_dmat;
173         bus_dmamap_t                    mfi_sense_dmamap;
174         uint32_t                        mfi_sense_busaddr;
175         struct mfi_sense                *mfi_sense;
176
177         struct resource                 *mfi_irq;
178         void                            *mfi_intr;
179         int                             mfi_irq_rid;
180
181         struct intr_config_hook         mfi_ich;
182         eventhandler_tag                eh;
183
184         /*
185          * Allocation for the command array.  Used as an indexable array to
186          * recover completed commands.
187          */
188         struct mfi_command              *mfi_commands;
189         /*
190          * How many commands were actually allocated
191          */
192         int                             mfi_total_cmds;
193         /*
194          * How many commands the firmware can handle.  Also how big the reply
195          * queue is, minus 1.
196          */
197         int                             mfi_max_fw_cmds;
198         /*
199          * How many S/G elements we'll ever actually use 
200          */
201         int                             mfi_max_sge;
202         /*
203          * How many bytes a compound frame is, including all of the extra frames
204          * that are used for S/G elements.
205          */
206         int                             mfi_cmd_size;
207         /*
208          * How large an S/G element is.  Used to calculate the number of single
209          * frames in a command.
210          */
211         int                             mfi_sge_size;
212         /*
213          * Max number of sectors that the firmware allows
214          */
215         uint32_t                        mfi_max_io;
216
217         TAILQ_HEAD(,mfi_disk)           mfi_ld_tqh;
218         eventhandler_tag                mfi_eh;
219         struct cdev                     *mfi_cdev;
220
221         TAILQ_HEAD(, ccb_hdr)           mfi_cam_ccbq;
222         struct mfi_command *            (* mfi_cam_start)(void *);
223         struct callout                  mfi_watchdog_callout;
224         struct mtx                      mfi_io_lock;
225         struct sx                       mfi_config_lock;
226
227         /* Controller type specific interfaces */
228         void    (*mfi_enable_intr)(struct mfi_softc *sc);
229         int32_t (*mfi_read_fw_status)(struct mfi_softc *sc);
230         int     (*mfi_check_clear_intr)(struct mfi_softc *sc);
231         void    (*mfi_issue_cmd)(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt);
232 };
233
234 extern int mfi_attach(struct mfi_softc *);
235 extern void mfi_free(struct mfi_softc *);
236 extern int mfi_shutdown(struct mfi_softc *);
237 extern void mfi_startio(struct mfi_softc *);
238 extern void mfi_disk_complete(struct bio *);
239 extern int mfi_disk_disable(struct mfi_disk *);
240 extern void mfi_disk_enable(struct mfi_disk *);
241 extern int mfi_dump_blocks(struct mfi_softc *, int id, uint64_t, void *, int);
242
243 #define MFIQ_ADD(sc, qname)                                     \
244         do {                                                    \
245                 struct mfi_qstat *qs;                           \
246                                                                 \
247                 qs = &(sc)->mfi_qstat[qname];                   \
248                 qs->q_length++;                                 \
249                 if (qs->q_length > qs->q_max)                   \
250                         qs->q_max = qs->q_length;               \
251         } while (0)
252
253 #define MFIQ_REMOVE(sc, qname)  (sc)->mfi_qstat[qname].q_length--
254
255 #define MFIQ_INIT(sc, qname)                                    \
256         do {                                                    \
257                 sc->mfi_qstat[qname].q_length = 0;              \
258                 sc->mfi_qstat[qname].q_max = 0;                 \
259         } while (0)
260
261 #define MFIQ_COMMAND_QUEUE(name, index)                                 \
262         static __inline void                                            \
263         mfi_initq_ ## name (struct mfi_softc *sc)                       \
264         {                                                               \
265                 TAILQ_INIT(&sc->mfi_ ## name);                          \
266                 MFIQ_INIT(sc, index);                                   \
267         }                                                               \
268         static __inline void                                            \
269         mfi_enqueue_ ## name (struct mfi_command *cm)                   \
270         {                                                               \
271                 if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {           \
272                         printf("command %p is on another queue, "       \
273                             "flags = %#x\n", cm, cm->cm_flags);         \
274                         panic("command is on another queue");           \
275                 }                                                       \
276                 TAILQ_INSERT_TAIL(&cm->cm_sc->mfi_ ## name, cm, cm_link); \
277                 cm->cm_flags |= MFI_ON_ ## index;                       \
278                 MFIQ_ADD(cm->cm_sc, index);                             \
279         }                                                               \
280         static __inline void                                            \
281         mfi_requeue_ ## name (struct mfi_command *cm)                   \
282         {                                                               \
283                 if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {           \
284                         printf("command %p is on another queue, "       \
285                             "flags = %#x\n", cm, cm->cm_flags);         \
286                         panic("command is on another queue");           \
287                 }                                                       \
288                 TAILQ_INSERT_HEAD(&cm->cm_sc->mfi_ ## name, cm, cm_link); \
289                 cm->cm_flags |= MFI_ON_ ## index;                       \
290                 MFIQ_ADD(cm->cm_sc, index);                             \
291         }                                                               \
292         static __inline struct mfi_command *                            \
293         mfi_dequeue_ ## name (struct mfi_softc *sc)                     \
294         {                                                               \
295                 struct mfi_command *cm;                                 \
296                                                                         \
297                 if ((cm = TAILQ_FIRST(&sc->mfi_ ## name)) != NULL) {    \
298                         if ((cm->cm_flags & MFI_ON_ ## index) == 0) {   \
299                                 printf("command %p not in queue, "      \
300                                     "flags = %#x, bit = %#x\n", cm,     \
301                                     cm->cm_flags, MFI_ON_ ## index);    \
302                                 panic("command not in queue");          \
303                         }                                               \
304                         TAILQ_REMOVE(&sc->mfi_ ## name, cm, cm_link);   \
305                         cm->cm_flags &= ~MFI_ON_ ## index;              \
306                         MFIQ_REMOVE(sc, index);                         \
307                 }                                                       \
308                 return (cm);                                            \
309         }                                                               \
310         static __inline void                                            \
311         mfi_remove_ ## name (struct mfi_command *cm)                    \
312         {                                                               \
313                 if ((cm->cm_flags & MFI_ON_ ## index) == 0) {           \
314                         printf("command %p not in queue, flags = %#x, " \
315                             "bit = %#x\n", cm, cm->cm_flags,            \
316                             MFI_ON_ ## index);                          \
317                         panic("command not in queue");                  \
318                 }                                                       \
319                 TAILQ_REMOVE(&cm->cm_sc->mfi_ ## name, cm, cm_link);    \
320                 cm->cm_flags &= ~MFI_ON_ ## index;                      \
321                 MFIQ_REMOVE(cm->cm_sc, index);                          \
322         }                                                               \
323 struct hack
324
325 MFIQ_COMMAND_QUEUE(free, MFIQ_FREE);
326 MFIQ_COMMAND_QUEUE(ready, MFIQ_READY);
327 MFIQ_COMMAND_QUEUE(busy, MFIQ_BUSY);
328
329 static __inline void
330 mfi_initq_bio(struct mfi_softc *sc)
331 {
332         bioq_init(&sc->mfi_bioq);
333         MFIQ_INIT(sc, MFIQ_BIO);
334 }
335
336 static __inline void
337 mfi_enqueue_bio(struct mfi_softc *sc, struct bio *bp)
338 {
339         bioq_insert_tail(&sc->mfi_bioq, bp);
340         MFIQ_ADD(sc, MFIQ_BIO);
341 }
342
343 static __inline struct bio *
344 mfi_dequeue_bio(struct mfi_softc *sc)
345 {
346         struct bio *bp;
347
348         if ((bp = bioq_first(&sc->mfi_bioq)) != NULL) {
349                 bioq_remove(&sc->mfi_bioq, bp);
350                 MFIQ_REMOVE(sc, MFIQ_BIO);
351         }
352         return (bp);
353 }
354
355 /*
356  * This is from the original scsi_extract_sense() in CAM.  It's copied
357  * here because CAM now uses a non-inline version that follows more complex
358  * additions to the SPC spec, and we don't want to force a dependency on
359  * the CAM module for such a trivial action.
360  */
361 static __inline void
362 mfi_extract_sense(struct scsi_sense_data_fixed *sense,
363     int *error_code, int *sense_key, int *asc, int *ascq)
364 {
365
366         *error_code = sense->error_code & SSD_ERRCODE;
367         *sense_key = sense->flags & SSD_KEY;
368         *asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
369         *ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
370 }
371
372 static __inline void
373 mfi_print_sense(struct mfi_softc *sc, void *sense)
374 {
375         int error, key, asc, ascq;
376
377         mfi_extract_sense((struct scsi_sense_data_fixed *)sense,
378             &error, &key, &asc, &ascq);
379         device_printf(sc->mfi_dev, "sense error %d, sense_key %d, "
380             "asc %d, ascq %d\n", error, key, asc, ascq);
381 }
382
383
384 #define MFI_WRITE4(sc, reg, val)        bus_space_write_4((sc)->mfi_btag, \
385         sc->mfi_bhandle, (reg), (val))
386 #define MFI_READ4(sc, reg)              bus_space_read_4((sc)->mfi_btag, \
387         (sc)->mfi_bhandle, (reg))
388 #define MFI_WRITE2(sc, reg, val)        bus_space_write_2((sc)->mfi_btag, \
389         sc->mfi_bhandle, (reg), (val))
390 #define MFI_READ2(sc, reg)              bus_space_read_2((sc)->mfi_btag, \
391         (sc)->mfi_bhandle, (reg))
392 #define MFI_WRITE1(sc, reg, val)        bus_space_write_1((sc)->mfi_btag, \
393         sc->mfi_bhandle, (reg), (val))
394 #define MFI_READ1(sc, reg)              bus_space_read_1((sc)->mfi_btag, \
395         (sc)->mfi_bhandle, (reg))
396
397 MALLOC_DECLARE(M_MFIBUF);
398
399 #define MFI_CMD_TIMEOUT 30
400 #define MFI_MAXPHYS (128 * 1024)
401
402 #ifdef MFI_DEBUG
403 extern void mfi_print_cmd(struct mfi_command *cm);
404 extern void mfi_dump_cmds(struct mfi_softc *sc);
405 extern void mfi_validate_sg(struct mfi_softc *, struct mfi_command *, const char *, int );
406 #define MFI_PRINT_CMD(cm)       mfi_print_cmd(cm)
407 #define MFI_DUMP_CMDS(sc)       mfi_dump_cmds(sc)
408 #define MFI_VALIDATE_CMD(sc, cm) mfi_validate_sg(sc, cm, __FUNCTION__, __LINE__)
409 #else
410 #define MFI_PRINT_CMD(cm)
411 #define MFI_DUMP_CMDS(sc)
412 #define MFI_VALIDATE_CMD(sc, cm)
413 #endif
414
415 extern void mfi_release_command(struct mfi_command *cm);
416
417 #endif /* _MFIVAR_H */