]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - sys/dev/mps/mpsvar.h
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / sys / dev / mps / mpsvar.h
1 /*-
2  * Copyright (c) 2009 Yahoo! Inc.
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  * $FreeBSD$
27  */
28
29 #ifndef _MPSVAR_H
30 #define _MPSVAR_H
31
32 #define MPS_DB_MAX_WAIT         2500
33
34 #define MPS_REQ_FRAMES          1024
35 #define MPS_EVT_REPLY_FRAMES    32
36 #define MPS_REPLY_FRAMES        MPS_REQ_FRAMES
37 #define MPS_CHAIN_FRAMES        2048
38 #define MPS_SENSE_LEN           SSD_FULL_SIZE
39 #define MPS_MSI_COUNT           1
40 #define MPS_SGE64_SIZE          12
41 #define MPS_SGE32_SIZE          8
42 #define MPS_SGC_SIZE            8
43
44 #define MPS_PERIODIC_DELAY      1       /* 1 second heartbeat/watchdog check */
45
46 struct mps_softc;
47 struct mps_command;
48 struct mpssas_softc;
49 struct mpssas_target;
50
51 MALLOC_DECLARE(M_MPT2);
52
53 typedef void mps_evt_callback_t(struct mps_softc *, uintptr_t,
54     MPI2_EVENT_NOTIFICATION_REPLY *reply);
55 typedef void mps_command_callback_t(struct mps_softc *, struct mps_command *cm);
56
57 struct mps_chain {
58         TAILQ_ENTRY(mps_chain)          chain_link;
59         MPI2_SGE_IO_UNION               *chain;
60         uint32_t                        chain_busaddr;
61 };
62
63 /*
64  * This needs to be at least 2 to support SMP passthrough.
65  */
66 #define MPS_IOVEC_COUNT 2
67
68 struct mps_command {
69         TAILQ_ENTRY(mps_command)        cm_link;
70         struct mps_softc                *cm_sc;
71         void                            *cm_data;
72         u_int                           cm_length;
73         struct uio                      cm_uio;
74         struct iovec                    cm_iovec[MPS_IOVEC_COUNT];
75         u_int                           cm_max_segs;
76         u_int                           cm_sglsize;
77         MPI2_SGE_IO_UNION               *cm_sge;
78         uint8_t                         *cm_req;
79         uint8_t                         *cm_reply;
80         uint32_t                        cm_reply_data;
81         mps_command_callback_t          *cm_complete;
82         void                            *cm_complete_data;
83         struct mpssas_target            *cm_targ;
84         MPI2_REQUEST_DESCRIPTOR_UNION   cm_desc;
85         u_int                           cm_flags;
86 #define MPS_CM_FLAGS_POLLED             (1 << 0)
87 #define MPS_CM_FLAGS_COMPLETE           (1 << 1)
88 #define MPS_CM_FLAGS_SGE_SIMPLE         (1 << 2)
89 #define MPS_CM_FLAGS_DATAOUT            (1 << 3)
90 #define MPS_CM_FLAGS_DATAIN             (1 << 4)
91 #define MPS_CM_FLAGS_WAKEUP             (1 << 5)
92 #define MPS_CM_FLAGS_ACTIVE             (1 << 6)
93 #define MPS_CM_FLAGS_USE_UIO            (1 << 7)
94 #define MPS_CM_FLAGS_SMP_PASS           (1 << 8)
95 #define MPS_CM_FLAGS_CHAIN_FAILED       (1 << 9)
96 #define MPS_CM_FLAGS_ERROR_MASK         MPS_CM_FLAGS_CHAIN_FAILED
97         u_int                           cm_state;
98 #define MPS_CM_STATE_FREE               0
99 #define MPS_CM_STATE_BUSY               1
100 #define MPS_CM_STATE_TIMEDOUT           2
101         bus_dmamap_t                    cm_dmamap;
102         struct scsi_sense_data          *cm_sense;
103         TAILQ_HEAD(, mps_chain)         cm_chain_list;
104         uint32_t                        cm_req_busaddr;
105         uint32_t                        cm_sense_busaddr;
106         struct callout                  cm_callout;
107 };
108
109 struct mps_event_handle {
110         TAILQ_ENTRY(mps_event_handle)   eh_list;
111         mps_evt_callback_t              *callback;
112         void                            *data;
113         uint8_t                         mask[16];
114 };
115
116 struct mps_softc {
117         device_t                        mps_dev;
118         struct cdev                     *mps_cdev;
119         u_int                           mps_flags;
120 #define MPS_FLAGS_INTX          (1 << 0)
121 #define MPS_FLAGS_MSI           (1 << 1)
122 #define MPS_FLAGS_BUSY          (1 << 2)
123 #define MPS_FLAGS_SHUTDOWN      (1 << 3)
124 #define MPS_FLAGS_ATTACH_DONE   (1 << 4)
125         u_int                           mps_debug;
126         u_int                           allow_multiple_tm_cmds;
127         int                             tm_cmds_active;
128         int                             io_cmds_active;
129         int                             io_cmds_highwater;
130         int                             chain_free;
131         int                             chain_free_lowwater;
132         uint64_t                        chain_alloc_fail;
133         struct sysctl_ctx_list          sysctl_ctx;
134         struct sysctl_oid               *sysctl_tree;
135         struct mps_command              *commands;
136         struct mps_chain                *chains;
137         struct callout                  periodic;
138
139         struct mpssas_softc             *sassc;
140
141         TAILQ_HEAD(, mps_command)       req_list;
142         TAILQ_HEAD(, mps_chain)         chain_list;
143         TAILQ_HEAD(, mps_command)       tm_list;
144         TAILQ_HEAD(, mps_command)       io_list;
145         int                             replypostindex;
146         int                             replyfreeindex;
147
148         struct resource                 *mps_regs_resource;
149         bus_space_handle_t              mps_bhandle;
150         bus_space_tag_t                 mps_btag;
151         int                             mps_regs_rid;
152
153         bus_dma_tag_t                   mps_parent_dmat;
154         bus_dma_tag_t                   buffer_dmat;
155
156         MPI2_IOC_FACTS_REPLY            *facts;
157         MPI2_PORT_FACTS_REPLY           *pfacts;
158         int                             num_reqs;
159         int                             num_replies;
160         int                             fqdepth;        /* Free queue */
161         int                             pqdepth;        /* Post queue */
162
163         uint8_t                         event_mask[16];
164         TAILQ_HEAD(, mps_event_handle)  event_list;
165         struct mps_event_handle         *mps_log_eh;
166
167         struct mtx                      mps_mtx;
168         struct intr_config_hook         mps_ich;
169         struct resource                 *mps_irq[MPS_MSI_COUNT];
170         void                            *mps_intrhand[MPS_MSI_COUNT];
171         int                             mps_irq_rid[MPS_MSI_COUNT];
172
173         uint8_t                         *req_frames;
174         bus_addr_t                      req_busaddr;
175         bus_dma_tag_t                   req_dmat;
176         bus_dmamap_t                    req_map;
177
178         uint8_t                         *reply_frames;
179         bus_addr_t                      reply_busaddr;
180         bus_dma_tag_t                   reply_dmat;
181         bus_dmamap_t                    reply_map;
182
183         struct scsi_sense_data          *sense_frames;
184         bus_addr_t                      sense_busaddr;
185         bus_dma_tag_t                   sense_dmat;
186         bus_dmamap_t                    sense_map;
187
188         uint8_t                         *chain_frames;
189         bus_addr_t                      chain_busaddr;
190         bus_dma_tag_t                   chain_dmat;
191         bus_dmamap_t                    chain_map;
192
193         MPI2_REPLY_DESCRIPTORS_UNION    *post_queue;
194         bus_addr_t                      post_busaddr;
195         uint32_t                        *free_queue;
196         bus_addr_t                      free_busaddr;
197         bus_dma_tag_t                   queues_dmat;
198         bus_dmamap_t                    queues_map;
199 };
200
201 struct mps_config_params {
202         MPI2_CONFIG_EXT_PAGE_HEADER_UNION       hdr;
203         u_int           action;
204         u_int           page_address;   /* Attributes, not a phys address */
205         u_int           status;
206         void            *buffer;
207         u_int           length;
208         int             timeout;
209         void            (*callback)(struct mps_softc *, struct mps_config_params *);
210         void            *cbdata;
211 };
212
213 static __inline uint32_t
214 mps_regread(struct mps_softc *sc, uint32_t offset)
215 {
216         return (bus_space_read_4(sc->mps_btag, sc->mps_bhandle, offset));
217 }
218
219 static __inline void
220 mps_regwrite(struct mps_softc *sc, uint32_t offset, uint32_t val)
221 {
222         bus_space_write_4(sc->mps_btag, sc->mps_bhandle, offset, val);
223 }
224
225 static __inline void
226 mps_free_reply(struct mps_softc *sc, uint32_t busaddr)
227 {
228
229         if (++sc->replyfreeindex >= sc->fqdepth)
230                 sc->replyfreeindex = 0;
231         sc->free_queue[sc->replyfreeindex] = busaddr;
232         mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
233 }
234
235 static __inline struct mps_chain *
236 mps_alloc_chain(struct mps_softc *sc)
237 {
238         struct mps_chain *chain;
239
240         if ((chain = TAILQ_FIRST(&sc->chain_list)) != NULL) {
241                 TAILQ_REMOVE(&sc->chain_list, chain, chain_link);
242                 sc->chain_free--;
243                 if (sc->chain_free < sc->chain_free_lowwater)
244                         sc->chain_free_lowwater = sc->chain_free;
245         } else
246                 sc->chain_alloc_fail++;
247         return (chain);
248 }
249
250 static __inline void
251 mps_free_chain(struct mps_softc *sc, struct mps_chain *chain)
252 {
253 #if 0
254         bzero(chain->chain, 128);
255 #endif
256         sc->chain_free++;
257         TAILQ_INSERT_TAIL(&sc->chain_list, chain, chain_link);
258 }
259
260 static __inline void
261 mps_free_command(struct mps_softc *sc, struct mps_command *cm)
262 {
263         struct mps_chain *chain, *chain_temp;
264
265         if (cm->cm_reply != NULL) {
266                 mps_free_reply(sc, cm->cm_reply_data);
267                 cm->cm_reply = NULL;
268         }
269         cm->cm_flags = 0;
270         cm->cm_complete = NULL;
271         cm->cm_complete_data = NULL;
272         cm->cm_targ = 0;
273         cm->cm_max_segs = 0;
274         cm->cm_state = MPS_CM_STATE_FREE;
275         TAILQ_FOREACH_SAFE(chain, &cm->cm_chain_list, chain_link, chain_temp) {
276                 TAILQ_REMOVE(&cm->cm_chain_list, chain, chain_link);
277                 mps_free_chain(sc, chain);
278         }
279         TAILQ_INSERT_TAIL(&sc->req_list, cm, cm_link);
280 }
281
282 static __inline struct mps_command *
283 mps_alloc_command(struct mps_softc *sc)
284 {
285         struct mps_command *cm;
286
287         cm = TAILQ_FIRST(&sc->req_list);
288         if (cm == NULL)
289                 return (NULL);
290
291         TAILQ_REMOVE(&sc->req_list, cm, cm_link);
292         KASSERT(cm->cm_state == MPS_CM_STATE_FREE, ("mps: Allocating busy command\n"));
293         cm->cm_state = MPS_CM_STATE_BUSY;
294         return (cm);
295 }
296
297 static __inline void
298 mps_lock(struct mps_softc *sc)
299 {
300         mtx_lock(&sc->mps_mtx);
301 }
302
303 static __inline void
304 mps_unlock(struct mps_softc *sc)
305 {
306         mtx_unlock(&sc->mps_mtx);
307 }
308
309 #define MPS_INFO        (1 << 0)
310 #define MPS_TRACE       (1 << 1)
311 #define MPS_FAULT       (1 << 2)
312 #define MPS_EVENT       (1 << 3)
313 #define MPS_LOG         (1 << 4)
314
315 #define mps_printf(sc, args...)                         \
316         device_printf((sc)->mps_dev, ##args)
317
318 #define mps_dprint(sc, level, msg, args...)             \
319 do {                                                    \
320         if (sc->mps_debug & level)                      \
321                 device_printf(sc->mps_dev, msg, ##args);        \
322 } while (0)
323
324 #define mps_dprint_field(sc, level, msg, args...)               \
325 do {                                                            \
326         if (sc->mps_debug & level)                              \
327                 printf("\t" msg, ##args);                       \
328 } while (0)
329
330 #define MPS_PRINTFIELD_START(sc, tag...)        \
331         mps_dprint((sc), MPS_INFO, ##tag);      \
332         mps_dprint_field((sc), MPS_INFO, ":\n")
333 #define MPS_PRINTFIELD_END(sc, tag)             \
334         mps_dprint((sc), MPS_INFO, tag "\n")
335 #define MPS_PRINTFIELD(sc, facts, attr, fmt)    \
336         mps_dprint_field((sc), MPS_INFO, #attr ": " #fmt "\n", (facts)->attr)
337
338 #define MPS_EVENTFIELD_START(sc, tag...)        \
339         mps_dprint((sc), MPS_EVENT, ##tag);     \
340         mps_dprint_field((sc), MPS_EVENT, ":\n")
341 #define MPS_EVENTFIELD(sc, facts, attr, fmt)    \
342         mps_dprint_field((sc), MPS_EVENT, #attr ": " #fmt "\n", (facts)->attr)
343
344 static __inline void
345 mps_from_u64(uint64_t data, U64 *mps)
346 {
347         (mps)->High = (uint32_t)((data) >> 32);
348         (mps)->Low = (uint32_t)((data) & 0xffffffff);
349 }
350
351 static __inline uint64_t
352 mps_to_u64(U64 *data)
353 {
354
355         return (((uint64_t)data->High << 32) | data->Low);
356 }
357
358 static __inline void
359 mps_mask_intr(struct mps_softc *sc)
360 {
361         uint32_t mask;
362
363         mask = mps_regread(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET);
364         mask |= MPI2_HIM_REPLY_INT_MASK;
365         mps_regwrite(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET, mask);
366 }
367
368 static __inline void
369 mps_unmask_intr(struct mps_softc *sc)
370 {
371         uint32_t mask;
372
373         mask = mps_regread(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET);
374         mask &= ~MPI2_HIM_REPLY_INT_MASK;
375         mps_regwrite(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET, mask);
376 }
377
378 int mps_pci_setup_interrupts(struct mps_softc *);
379 int mps_attach(struct mps_softc *sc);
380 int mps_free(struct mps_softc *sc);
381 void mps_intr(void *);
382 void mps_intr_msi(void *);
383 void mps_intr_locked(void *);
384 int mps_register_events(struct mps_softc *, uint8_t *, mps_evt_callback_t *,
385     void *, struct mps_event_handle **);
386 int mps_update_events(struct mps_softc *, struct mps_event_handle *, uint8_t *);
387 int mps_deregister_events(struct mps_softc *, struct mps_event_handle *);
388 int mps_request_polled(struct mps_softc *sc, struct mps_command *cm);
389 void mps_enqueue_request(struct mps_softc *, struct mps_command *);
390 int mps_push_sge(struct mps_command *, void *, size_t, int);
391 int mps_add_dmaseg(struct mps_command *, vm_paddr_t, size_t, u_int, int);
392 int mps_attach_sas(struct mps_softc *sc);
393 int mps_detach_sas(struct mps_softc *sc);
394 int mps_map_command(struct mps_softc *sc, struct mps_command *cm);
395 int mps_read_config_page(struct mps_softc *, struct mps_config_params *);
396 int mps_write_config_page(struct mps_softc *, struct mps_config_params *);
397 void mps_memaddr_cb(void *, bus_dma_segment_t *, int , int );
398 void mpi_init_sge(struct mps_command *cm, void *req, void *sge);
399 int mps_attach_user(struct mps_softc *);
400 void mps_detach_user(struct mps_softc *);
401
402 SYSCTL_DECL(_hw_mps);
403
404 #endif
405