]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/sfxge/common/efsys.h
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / sfxge / common / efsys.h
1 /*-
2  * Copyright (c) 2010-2015 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * This software was developed in part by Philip Paeps under contract for
6  * Solarflare Communications, Inc.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * The views and conclusions contained in the software and documentation are
30  * those of the authors and should not be interpreted as representing official
31  * policies, either expressed or implied, of the FreeBSD Project.
32  *
33  * $FreeBSD$
34  */
35
36 #ifndef _SYS_EFSYS_H
37 #define _SYS_EFSYS_H
38
39 #ifdef  __cplusplus
40 extern "C" {
41 #endif
42
43 #include <sys/param.h>
44 #include <sys/bus.h>
45 #include <sys/endian.h>
46 #include <sys/lock.h>
47 #include <sys/malloc.h>
48 #include <sys/mbuf.h>
49 #include <sys/mutex.h>
50 #include <sys/rwlock.h>
51 #include <sys/sdt.h>
52 #include <sys/systm.h>
53
54 #include <machine/bus.h>
55 #include <machine/endian.h>
56
57 #define EFSYS_HAS_UINT64 1
58 #if defined(__x86_64__)
59 #define EFSYS_USE_UINT64 1
60 #else
61 #define EFSYS_USE_UINT64 0
62 #endif
63 #define EFSYS_HAS_SSE2_M128 0
64 #if _BYTE_ORDER == _BIG_ENDIAN
65 #define EFSYS_IS_BIG_ENDIAN 1
66 #define EFSYS_IS_LITTLE_ENDIAN 0
67 #elif _BYTE_ORDER == _LITTLE_ENDIAN
68 #define EFSYS_IS_BIG_ENDIAN 0
69 #define EFSYS_IS_LITTLE_ENDIAN 1
70 #endif
71 #include "efx_types.h"
72
73 /* Common code requires this */
74 #if __FreeBSD_version < 800068
75 #define memmove(d, s, l) bcopy(s, d, l)
76 #endif
77
78 /* FreeBSD equivalents of Solaris things */
79 #ifndef _NOTE
80 #define _NOTE(s)
81 #endif
82
83 #ifndef B_FALSE
84 #define B_FALSE FALSE
85 #endif
86 #ifndef B_TRUE
87 #define B_TRUE  TRUE
88 #endif
89
90 #ifndef IS_P2ALIGNED
91 #define IS_P2ALIGNED(v, a)      ((((uintptr_t)(v)) & ((uintptr_t)(a) - 1)) == 0)
92 #endif
93
94 #ifndef P2ROUNDUP
95 #define P2ROUNDUP(x, align)     (-(-(x) & -(align)))
96 #endif
97
98 #ifndef P2ALIGN
99 #define P2ALIGN(_x, _a)         ((_x) & -(_a))
100 #endif
101
102 #ifndef IS2P
103 #define ISP2(x)                 (((x) & ((x) - 1)) == 0)
104 #endif
105
106 #if defined(__x86_64__) && __FreeBSD_version >= 1000000
107
108 #define SFXGE_USE_BUS_SPACE_8           1
109
110 #if !defined(bus_space_read_stream_8)
111
112 #define bus_space_read_stream_8(t, h, o)                                \
113         bus_space_read_8((t), (h), (o))
114
115 #define bus_space_write_stream_8(t, h, o, v)                            \
116         bus_space_write_8((t), (h), (o), (v))
117
118 #endif
119
120 #endif
121
122 #define ENOTACTIVE EINVAL
123
124 /* Memory type to use on FreeBSD */
125 MALLOC_DECLARE(M_SFXGE);
126
127 /* Machine dependend prefetch wrappers */
128 #if defined(__i386__) || defined(__amd64__)
129 static __inline void
130 prefetch_read_many(void *addr)
131 {
132
133         __asm__(
134             "prefetcht0 (%0)"
135             :
136             : "r" (addr));
137 }
138
139 static __inline void
140 prefetch_read_once(void *addr)
141 {
142
143         __asm__(
144             "prefetchnta (%0)"
145             :
146             : "r" (addr));
147 }
148 #elif defined(__sparc64__)
149 static __inline void
150 prefetch_read_many(void *addr)
151 {
152
153         __asm__(
154             "prefetch [%0], 0"
155             :
156             : "r" (addr));
157 }
158
159 static __inline void
160 prefetch_read_once(void *addr)
161 {
162
163         __asm__(
164             "prefetch [%0], 1"
165             :
166             : "r" (addr));
167 }
168 #else
169 static __inline void
170 prefetch_read_many(void *addr)
171 {
172
173 }
174
175 static __inline void
176 prefetch_read_once(void *addr)
177 {
178
179 }
180 #endif
181
182 #if defined(__i386__) || defined(__amd64__)
183 #include <vm/vm.h>
184 #include <vm/pmap.h>
185 #endif
186 static __inline void
187 sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map,
188                     struct mbuf *m, bus_dma_segment_t *seg)
189 {
190 #if defined(__i386__) || defined(__amd64__)
191         seg->ds_addr = pmap_kextract(mtod(m, vm_offset_t));
192         seg->ds_len = m->m_len;
193 #else
194         int nsegstmp;
195
196         bus_dmamap_load_mbuf_sg(tag, map, m, seg, &nsegstmp, 0);
197 #endif
198 }
199
200 /* Modifiers used for Windows builds */
201 #define __in
202 #define __in_opt
203 #define __in_ecount(_n)
204 #define __in_ecount_opt(_n)
205 #define __in_bcount(_n)
206 #define __in_bcount_opt(_n)
207
208 #define __out
209 #define __out_opt
210 #define __out_ecount(_n)
211 #define __out_ecount_opt(_n)
212 #define __out_bcount(_n)
213 #define __out_bcount_opt(_n)
214
215 #define __deref_out
216
217 #define __inout
218 #define __inout_opt
219 #define __inout_ecount(_n)
220 #define __inout_ecount_opt(_n)
221 #define __inout_bcount(_n)
222 #define __inout_bcount_opt(_n)
223 #define __inout_bcount_full_opt(_n)
224
225 #define __deref_out_bcount_opt(n)
226
227 #define __checkReturn
228
229 #define __drv_when(_p, _c)
230
231 /* Code inclusion options */
232
233
234 #define EFSYS_OPT_NAMES 1
235
236 #define EFSYS_OPT_FALCON 0
237 #define EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE 0
238 #define EFSYS_OPT_SIENA 1
239 #define EFSYS_OPT_HUNTINGTON 1
240 #ifdef DEBUG
241 #define EFSYS_OPT_CHECK_REG 1
242 #else
243 #define EFSYS_OPT_CHECK_REG 0
244 #endif
245
246 #define EFSYS_OPT_MCDI 1
247
248 #define EFSYS_OPT_MAC_FALCON_GMAC 0
249 #define EFSYS_OPT_MAC_FALCON_XMAC 0
250 #define EFSYS_OPT_MAC_STATS 1
251
252 #define EFSYS_OPT_LOOPBACK 0
253
254 #define EFSYS_OPT_MON_NULL 0
255 #define EFSYS_OPT_MON_LM87 0
256 #define EFSYS_OPT_MON_MAX6647 0
257 #define EFSYS_OPT_MON_MCDI 0
258 #define EFSYS_OPT_MON_STATS 0
259
260 #define EFSYS_OPT_PHY_NULL 0
261 #define EFSYS_OPT_PHY_QT2022C2 0
262 #define EFSYS_OPT_PHY_SFX7101 0
263 #define EFSYS_OPT_PHY_TXC43128 0
264 #define EFSYS_OPT_PHY_SFT9001 0
265 #define EFSYS_OPT_PHY_QT2025C 0
266 #define EFSYS_OPT_PHY_STATS 1
267 #define EFSYS_OPT_PHY_PROPS 0
268 #define EFSYS_OPT_PHY_BIST 0
269 #define EFSYS_OPT_BIST 1
270 #define EFSYS_OPT_PHY_LED_CONTROL 1
271 #define EFSYS_OPT_PHY_FLAGS 0
272
273 #define EFSYS_OPT_VPD 1
274 #define EFSYS_OPT_NVRAM 1
275 #define EFSYS_OPT_NVRAM_FALCON_BOOTROM 0
276 #define EFSYS_OPT_NVRAM_SFT9001 0
277 #define EFSYS_OPT_NVRAM_SFX7101 0
278 #define EFSYS_OPT_BOOTCFG 0
279
280 #define EFSYS_OPT_PCIE_TUNE 0
281 #define EFSYS_OPT_DIAG 0
282 #define EFSYS_OPT_WOL 1
283 #define EFSYS_OPT_RX_SCALE 1
284 #define EFSYS_OPT_QSTATS 1
285 #define EFSYS_OPT_FILTER 1
286 #define EFSYS_OPT_MCAST_FILTER_LIST 1
287 #define EFSYS_OPT_RX_SCATTER 0
288 #define EFSYS_OPT_RX_HDR_SPLIT 0
289
290 #define EFSYS_OPT_EV_PREFETCH 0
291
292 #define EFSYS_OPT_DECODE_INTR_FATAL 1
293
294 /* ID */
295
296 typedef struct __efsys_identifier_s     efsys_identifier_t;
297
298 /* PROBE */
299
300 #ifndef KDTRACE_HOOKS
301
302 #define EFSYS_PROBE(_name)
303
304 #define EFSYS_PROBE1(_name, _type1, _arg1)
305
306 #define EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)
307
308 #define EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2,               \
309             _type3, _arg3)
310
311 #define EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2,               \
312             _type3, _arg3, _type4, _arg4)
313
314 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,               \
315             _type3, _arg3, _type4, _arg4, _type5, _arg5)
316
317 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,               \
318             _type3, _arg3, _type4, _arg4, _type5, _arg5,                \
319             _type6, _arg6)
320
321 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,               \
322             _type3, _arg3, _type4, _arg4, _type5, _arg5,                \
323             _type6, _arg6, _type7, _arg7)
324
325 #else /* KDTRACE_HOOKS */
326
327 #define EFSYS_PROBE(_name)                                              \
328         DTRACE_PROBE(_name)
329
330 #define EFSYS_PROBE1(_name, _type1, _arg1)                              \
331         DTRACE_PROBE1(_name, _type1, _arg1)
332
333 #define EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)               \
334         DTRACE_PROBE2(_name, _type1, _arg1, _type2, _arg2)
335
336 #define EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2,               \
337             _type3, _arg3)                                              \
338         DTRACE_PROBE3(_name, _type1, _arg1, _type2, _arg2,              \
339             _type3, _arg3)
340
341 #define EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2,               \
342             _type3, _arg3, _type4, _arg4)                               \
343         DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2,              \
344             _type3, _arg3, _type4, _arg4)
345
346 #ifdef DTRACE_PROBE5
347 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,               \
348             _type3, _arg3, _type4, _arg4, _type5, _arg5)                \
349         DTRACE_PROBE5(_name, _type1, _arg1, _type2, _arg2,              \
350             _type3, _arg3, _type4, _arg4, _type5, _arg5)
351 #else
352 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,               \
353             _type3, _arg3, _type4, _arg4, _type5, _arg5)                \
354         DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2,              \
355             _type3, _arg3, _type4, _arg4)
356 #endif
357
358 #ifdef DTRACE_PROBE6
359 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,               \
360             _type3, _arg3, _type4, _arg4, _type5, _arg5,                \
361             _type6, _arg6)                                              \
362         DTRACE_PROBE6(_name, _type1, _arg1, _type2, _arg2,              \
363             _type3, _arg3, _type4, _arg4, _type5, _arg5,                \
364             _type6, _arg6)
365 #else
366 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,               \
367             _type3, _arg3, _type4, _arg4, _type5, _arg5,                \
368             _type6, _arg6)                                              \
369         EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,               \
370             _type3, _arg3, _type4, _arg4, _type5, _arg5)
371 #endif
372
373 #ifdef DTRACE_PROBE7
374 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,               \
375             _type3, _arg3, _type4, _arg4, _type5, _arg5,                \
376             _type6, _arg6, _type7, _arg7)                               \
377         DTRACE_PROBE7(_name, _type1, _arg1, _type2, _arg2,              \
378             _type3, _arg3, _type4, _arg4, _type5, _arg5,                \
379             _type6, _arg6, _type7, _arg7)
380 #else
381 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,               \
382             _type3, _arg3, _type4, _arg4, _type5, _arg5,                \
383             _type6, _arg6, _type7, _arg7)                               \
384         EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,               \
385             _type3, _arg3, _type4, _arg4, _type5, _arg5,                \
386             _type6, _arg6)
387 #endif
388
389 #endif /* KDTRACE_HOOKS */
390
391 /* DMA */
392
393 typedef uint64_t                efsys_dma_addr_t;
394
395 typedef struct efsys_mem_s {
396         bus_dma_tag_t           esm_tag;
397         bus_dmamap_t            esm_map;
398         caddr_t                 esm_base;
399         efsys_dma_addr_t        esm_addr;
400 } efsys_mem_t;
401
402
403 #define EFSYS_MEM_ZERO(_esmp, _size)                                    \
404         do {                                                            \
405                 (void) memset((_esmp)->esm_base, 0, (_size));           \
406                                                                         \
407         _NOTE(CONSTANTCONDITION)                                        \
408         } while (B_FALSE)
409
410 #define EFSYS_MEM_READD(_esmp, _offset, _edp)                           \
411         do {                                                            \
412                 uint32_t *addr;                                         \
413                                                                         \
414                 _NOTE(CONSTANTCONDITION)                                \
415                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),    \
416                     ("not power of 2 aligned"));                        \
417                                                                         \
418                 addr = (void *)((_esmp)->esm_base + (_offset));         \
419                                                                         \
420                 (_edp)->ed_u32[0] = *addr;                              \
421                                                                         \
422                 EFSYS_PROBE2(mem_readd, unsigned int, (_offset),        \
423                     uint32_t, (_edp)->ed_u32[0]);                       \
424                                                                         \
425         _NOTE(CONSTANTCONDITION)                                        \
426         } while (B_FALSE)
427
428 #if defined(__x86_64__)
429 #define EFSYS_MEM_READQ(_esmp, _offset, _eqp)                           \
430         do {                                                            \
431                 uint64_t *addr;                                         \
432                                                                         \
433                 _NOTE(CONSTANTCONDITION)                                \
434                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),    \
435                     ("not power of 2 aligned"));                        \
436                                                                         \
437                 addr = (void *)((_esmp)->esm_base + (_offset));         \
438                                                                         \
439                 (_eqp)->eq_u64[0] = *addr;                              \
440                                                                         \
441                 EFSYS_PROBE3(mem_readq, unsigned int, (_offset),        \
442                     uint32_t, (_eqp)->eq_u32[1],                        \
443                     uint32_t, (_eqp)->eq_u32[0]);                       \
444                                                                         \
445         _NOTE(CONSTANTCONDITION)                                        \
446         } while (B_FALSE)
447 #else
448 #define EFSYS_MEM_READQ(_esmp, _offset, _eqp)                           \
449         do {                                                            \
450                 uint32_t *addr;                                         \
451                                                                         \
452                 _NOTE(CONSTANTCONDITION)                                \
453                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),    \
454                     ("not power of 2 aligned"));                        \
455                                                                         \
456                 addr = (void *)((_esmp)->esm_base + (_offset));         \
457                                                                         \
458                 (_eqp)->eq_u32[0] = *addr++;                            \
459                 (_eqp)->eq_u32[1] = *addr;                              \
460                                                                         \
461                 EFSYS_PROBE3(mem_readq, unsigned int, (_offset),        \
462                     uint32_t, (_eqp)->eq_u32[1],                        \
463                     uint32_t, (_eqp)->eq_u32[0]);                       \
464                                                                         \
465         _NOTE(CONSTANTCONDITION)                                        \
466         } while (B_FALSE)
467 #endif
468
469 #if defined(__x86_64__)
470 #define EFSYS_MEM_READO(_esmp, _offset, _eop)                           \
471         do {                                                            \
472                 uint64_t *addr;                                         \
473                                                                         \
474                 _NOTE(CONSTANTCONDITION)                                \
475                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),    \
476                     ("not power of 2 aligned"));                        \
477                                                                         \
478                 addr = (void *)((_esmp)->esm_base + (_offset));         \
479                                                                         \
480                 (_eop)->eo_u64[0] = *addr++;                            \
481                 (_eop)->eo_u64[1] = *addr;                              \
482                                                                         \
483                 EFSYS_PROBE5(mem_reado, unsigned int, (_offset),        \
484                     uint32_t, (_eop)->eo_u32[3],                        \
485                     uint32_t, (_eop)->eo_u32[2],                        \
486                     uint32_t, (_eop)->eo_u32[1],                        \
487                     uint32_t, (_eop)->eo_u32[0]);                       \
488                                                                         \
489         _NOTE(CONSTANTCONDITION)                                        \
490         } while (B_FALSE)
491 #else
492 #define EFSYS_MEM_READO(_esmp, _offset, _eop)                           \
493         do {                                                            \
494                 uint32_t *addr;                                         \
495                                                                         \
496                 _NOTE(CONSTANTCONDITION)                                \
497                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),    \
498                     ("not power of 2 aligned"));                        \
499                                                                         \
500                 addr = (void *)((_esmp)->esm_base + (_offset));         \
501                                                                         \
502                 (_eop)->eo_u32[0] = *addr++;                            \
503                 (_eop)->eo_u32[1] = *addr++;                            \
504                 (_eop)->eo_u32[2] = *addr++;                            \
505                 (_eop)->eo_u32[3] = *addr;                              \
506                                                                         \
507                 EFSYS_PROBE5(mem_reado, unsigned int, (_offset),        \
508                     uint32_t, (_eop)->eo_u32[3],                        \
509                     uint32_t, (_eop)->eo_u32[2],                        \
510                     uint32_t, (_eop)->eo_u32[1],                        \
511                     uint32_t, (_eop)->eo_u32[0]);                       \
512                                                                         \
513         _NOTE(CONSTANTCONDITION)                                        \
514         } while (B_FALSE)
515 #endif
516
517 #define EFSYS_MEM_WRITED(_esmp, _offset, _edp)                          \
518         do {                                                            \
519                 uint32_t *addr;                                         \
520                                                                         \
521                 _NOTE(CONSTANTCONDITION)                                \
522                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),    \
523                     ("not power of 2 aligned"));                        \
524                                                                         \
525                 EFSYS_PROBE2(mem_writed, unsigned int, (_offset),       \
526                     uint32_t, (_edp)->ed_u32[0]);                       \
527                                                                         \
528                 addr = (void *)((_esmp)->esm_base + (_offset));         \
529                                                                         \
530                 *addr = (_edp)->ed_u32[0];                              \
531                                                                         \
532         _NOTE(CONSTANTCONDITION)                                        \
533         } while (B_FALSE)
534
535 #if defined(__x86_64__)
536 #define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp)                          \
537         do {                                                            \
538                 uint64_t *addr;                                         \
539                                                                         \
540                 _NOTE(CONSTANTCONDITION)                                \
541                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),    \
542                     ("not power of 2 aligned"));                        \
543                                                                         \
544                 EFSYS_PROBE3(mem_writeq, unsigned int, (_offset),       \
545                     uint32_t, (_eqp)->eq_u32[1],                        \
546                     uint32_t, (_eqp)->eq_u32[0]);                       \
547                                                                         \
548                 addr = (void *)((_esmp)->esm_base + (_offset));         \
549                                                                         \
550                 *addr   = (_eqp)->eq_u64[0];                            \
551                                                                         \
552         _NOTE(CONSTANTCONDITION)                                        \
553         } while (B_FALSE)
554
555 #else
556 #define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp)                          \
557         do {                                                            \
558                 uint32_t *addr;                                         \
559                                                                         \
560                 _NOTE(CONSTANTCONDITION)                                \
561                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),    \
562                     ("not power of 2 aligned"));                        \
563                                                                         \
564                 EFSYS_PROBE3(mem_writeq, unsigned int, (_offset),       \
565                     uint32_t, (_eqp)->eq_u32[1],                        \
566                     uint32_t, (_eqp)->eq_u32[0]);                       \
567                                                                         \
568                 addr = (void *)((_esmp)->esm_base + (_offset));         \
569                                                                         \
570                 *addr++ = (_eqp)->eq_u32[0];                            \
571                 *addr   = (_eqp)->eq_u32[1];                            \
572                                                                         \
573         _NOTE(CONSTANTCONDITION)                                        \
574         } while (B_FALSE)
575 #endif
576
577 #if defined(__x86_64__)
578 #define EFSYS_MEM_WRITEO(_esmp, _offset, _eop)                          \
579         do {                                                            \
580                 uint64_t *addr;                                         \
581                                                                         \
582                 _NOTE(CONSTANTCONDITION)                                \
583                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),    \
584                     ("not power of 2 aligned"));                        \
585                                                                         \
586                 EFSYS_PROBE5(mem_writeo, unsigned int, (_offset),       \
587                     uint32_t, (_eop)->eo_u32[3],                        \
588                     uint32_t, (_eop)->eo_u32[2],                        \
589                     uint32_t, (_eop)->eo_u32[1],                        \
590                     uint32_t, (_eop)->eo_u32[0]);                       \
591                                                                         \
592                 addr = (void *)((_esmp)->esm_base + (_offset));         \
593                                                                         \
594                 *addr++ = (_eop)->eo_u64[0];                            \
595                 *addr   = (_eop)->eo_u64[1];                            \
596                                                                         \
597         _NOTE(CONSTANTCONDITION)                                        \
598         } while (B_FALSE)
599 #else
600 #define EFSYS_MEM_WRITEO(_esmp, _offset, _eop)                          \
601         do {                                                            \
602                 uint32_t *addr;                                         \
603                                                                         \
604                 _NOTE(CONSTANTCONDITION)                                \
605                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),    \
606                     ("not power of 2 aligned"));                        \
607                                                                         \
608                 EFSYS_PROBE5(mem_writeo, unsigned int, (_offset),       \
609                     uint32_t, (_eop)->eo_u32[3],                        \
610                     uint32_t, (_eop)->eo_u32[2],                        \
611                     uint32_t, (_eop)->eo_u32[1],                        \
612                     uint32_t, (_eop)->eo_u32[0]);                       \
613                                                                         \
614                 addr = (void *)((_esmp)->esm_base + (_offset));         \
615                                                                         \
616                 *addr++ = (_eop)->eo_u32[0];                            \
617                 *addr++ = (_eop)->eo_u32[1];                            \
618                 *addr++ = (_eop)->eo_u32[2];                            \
619                 *addr   = (_eop)->eo_u32[3];                            \
620                                                                         \
621         _NOTE(CONSTANTCONDITION)                                        \
622         } while (B_FALSE)
623 #endif
624
625 #define EFSYS_MEM_ADDR(_esmp)                                           \
626         ((_esmp)->esm_addr)
627
628 #define EFSYS_MEM_IS_NULL(_esmp)                                        \
629         ((_esmp)->esm_base == NULL)
630
631 /* BAR */
632
633 #define SFXGE_LOCK_NAME_MAX     16
634
635 typedef struct efsys_bar_s {
636         struct mtx              esb_lock;
637         char                    esb_lock_name[SFXGE_LOCK_NAME_MAX];
638         bus_space_tag_t         esb_tag;
639         bus_space_handle_t      esb_handle;
640         int                     esb_rid;
641         struct resource         *esb_res;
642 } efsys_bar_t;
643
644 #define SFXGE_BAR_LOCK_INIT(_esbp, _ifname)                             \
645         do {                                                            \
646                 snprintf((_esbp)->esb_lock_name,                        \
647                          sizeof((_esbp)->esb_lock_name),                \
648                          "%s:bar", (_ifname));                          \
649                 mtx_init(&(_esbp)->esb_lock, (_esbp)->esb_lock_name,    \
650                          NULL, MTX_DEF);                                \
651         _NOTE(CONSTANTCONDITION)                                        \
652         } while (B_FALSE)
653 #define SFXGE_BAR_LOCK_DESTROY(_esbp)                                   \
654         mtx_destroy(&(_esbp)->esb_lock)
655 #define SFXGE_BAR_LOCK(_esbp)                                           \
656         mtx_lock(&(_esbp)->esb_lock)
657 #define SFXGE_BAR_UNLOCK(_esbp)                                         \
658         mtx_unlock(&(_esbp)->esb_lock)
659
660 #define EFSYS_BAR_READD(_esbp, _offset, _edp, _lock)                    \
661         do {                                                            \
662                 _NOTE(CONSTANTCONDITION)                                \
663                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),    \
664                     ("not power of 2 aligned"));                        \
665                                                                         \
666                 _NOTE(CONSTANTCONDITION)                                \
667                 if (_lock)                                              \
668                         SFXGE_BAR_LOCK(_esbp);                          \
669                                                                         \
670                 (_edp)->ed_u32[0] = bus_space_read_stream_4(            \
671                     (_esbp)->esb_tag, (_esbp)->esb_handle,              \
672                     (_offset));                                         \
673                                                                         \
674                 EFSYS_PROBE2(bar_readd, unsigned int, (_offset),        \
675                     uint32_t, (_edp)->ed_u32[0]);                       \
676                                                                         \
677                 _NOTE(CONSTANTCONDITION)                                \
678                 if (_lock)                                              \
679                         SFXGE_BAR_UNLOCK(_esbp);                        \
680         _NOTE(CONSTANTCONDITION)                                        \
681         } while (B_FALSE)
682
683 #if defined(SFXGE_USE_BUS_SPACE_8)
684 #define EFSYS_BAR_READQ(_esbp, _offset, _eqp)                           \
685         do {                                                            \
686                 _NOTE(CONSTANTCONDITION)                                \
687                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),    \
688                     ("not power of 2 aligned"));                        \
689                                                                         \
690                 SFXGE_BAR_LOCK(_esbp);                                  \
691                                                                         \
692                 (_eqp)->eq_u64[0] = bus_space_read_stream_8(            \
693                     (_esbp)->esb_tag, (_esbp)->esb_handle,              \
694                     (_offset));                                         \
695                                                                         \
696                 EFSYS_PROBE3(bar_readq, unsigned int, (_offset),        \
697                     uint32_t, (_eqp)->eq_u32[1],                        \
698                     uint32_t, (_eqp)->eq_u32[0]);                       \
699                                                                         \
700                 SFXGE_BAR_UNLOCK(_esbp);                                \
701         _NOTE(CONSTANTCONDITION)                                        \
702         } while (B_FALSE)
703
704 #define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock)                    \
705         do {                                                            \
706                 _NOTE(CONSTANTCONDITION)                                \
707                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),    \
708                     ("not power of 2 aligned"));                        \
709                                                                         \
710                 _NOTE(CONSTANTCONDITION)                                \
711                 if (_lock)                                              \
712                         SFXGE_BAR_LOCK(_esbp);                          \
713                                                                         \
714                 (_eop)->eo_u64[0] = bus_space_read_stream_8(            \
715                     (_esbp)->esb_tag, (_esbp)->esb_handle,              \
716                     (_offset));                                         \
717                 (_eop)->eo_u64[1] = bus_space_read_stream_8(            \
718                     (_esbp)->esb_tag, (_esbp)->esb_handle,              \
719                     (_offset) + 8);                                     \
720                                                                         \
721                 EFSYS_PROBE5(bar_reado, unsigned int, (_offset),        \
722                     uint32_t, (_eop)->eo_u32[3],                        \
723                     uint32_t, (_eop)->eo_u32[2],                        \
724                     uint32_t, (_eop)->eo_u32[1],                        \
725                     uint32_t, (_eop)->eo_u32[0]);                       \
726                                                                         \
727                 _NOTE(CONSTANTCONDITION)                                \
728                 if (_lock)                                              \
729                         SFXGE_BAR_UNLOCK(_esbp);                        \
730         _NOTE(CONSTANTCONDITION)                                        \
731         } while (B_FALSE)
732
733 #else
734 #define EFSYS_BAR_READQ(_esbp, _offset, _eqp)                           \
735         do {                                                            \
736                 _NOTE(CONSTANTCONDITION)                                \
737                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),    \
738                     ("not power of 2 aligned"));                        \
739                                                                         \
740                 SFXGE_BAR_LOCK(_esbp);                                  \
741                                                                         \
742                 (_eqp)->eq_u32[0] = bus_space_read_stream_4(            \
743                     (_esbp)->esb_tag, (_esbp)->esb_handle,              \
744                     (_offset));                                         \
745                 (_eqp)->eq_u32[1] = bus_space_read_stream_4(            \
746                     (_esbp)->esb_tag, (_esbp)->esb_handle,              \
747                     (_offset) + 4);                                     \
748                                                                         \
749                 EFSYS_PROBE3(bar_readq, unsigned int, (_offset),        \
750                     uint32_t, (_eqp)->eq_u32[1],                        \
751                     uint32_t, (_eqp)->eq_u32[0]);                       \
752                                                                         \
753                 SFXGE_BAR_UNLOCK(_esbp);                                \
754         _NOTE(CONSTANTCONDITION)                                        \
755         } while (B_FALSE)
756
757 #define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock)                    \
758         do {                                                            \
759                 _NOTE(CONSTANTCONDITION)                                \
760                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),    \
761                     ("not power of 2 aligned"));                        \
762                                                                         \
763                 _NOTE(CONSTANTCONDITION)                                \
764                 if (_lock)                                              \
765                         SFXGE_BAR_LOCK(_esbp);                          \
766                                                                         \
767                 (_eop)->eo_u32[0] = bus_space_read_stream_4(            \
768                     (_esbp)->esb_tag, (_esbp)->esb_handle,              \
769                     (_offset));                                         \
770                 (_eop)->eo_u32[1] = bus_space_read_stream_4(            \
771                     (_esbp)->esb_tag, (_esbp)->esb_handle,              \
772                     (_offset) + 4);                                     \
773                 (_eop)->eo_u32[2] = bus_space_read_stream_4(            \
774                     (_esbp)->esb_tag, (_esbp)->esb_handle,              \
775                     (_offset) + 8);                                     \
776                 (_eop)->eo_u32[3] = bus_space_read_stream_4(            \
777                     (_esbp)->esb_tag, (_esbp)->esb_handle,              \
778                     (_offset) + 12);                                    \
779                                                                         \
780                 EFSYS_PROBE5(bar_reado, unsigned int, (_offset),        \
781                     uint32_t, (_eop)->eo_u32[3],                        \
782                     uint32_t, (_eop)->eo_u32[2],                        \
783                     uint32_t, (_eop)->eo_u32[1],                        \
784                     uint32_t, (_eop)->eo_u32[0]);                       \
785                                                                         \
786                 _NOTE(CONSTANTCONDITION)                                \
787                 if (_lock)                                              \
788                         SFXGE_BAR_UNLOCK(_esbp);                        \
789         _NOTE(CONSTANTCONDITION)                                        \
790         } while (B_FALSE)
791 #endif
792
793 #define EFSYS_BAR_WRITED(_esbp, _offset, _edp, _lock)                   \
794         do {                                                            \
795                 _NOTE(CONSTANTCONDITION)                                \
796                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),    \
797                     ("not power of 2 aligned"));                        \
798                                                                         \
799                 _NOTE(CONSTANTCONDITION)                                \
800                 if (_lock)                                              \
801                         SFXGE_BAR_LOCK(_esbp);                          \
802                                                                         \
803                 EFSYS_PROBE2(bar_writed, unsigned int, (_offset),       \
804                     uint32_t, (_edp)->ed_u32[0]);                       \
805                                                                         \
806                 /*                                                      \
807                  * Make sure that previous writes to the dword have     \
808                  * been done. It should be cheaper than barrier just    \
809                  * after the write below.                               \
810                  */                                                     \
811                 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
812                     (_offset), sizeof (efx_dword_t),                    \
813                     BUS_SPACE_BARRIER_WRITE);                           \
814                 bus_space_write_stream_4((_esbp)->esb_tag,              \
815                     (_esbp)->esb_handle,                                \
816                     (_offset), (_edp)->ed_u32[0]);                      \
817                                                                         \
818                 _NOTE(CONSTANTCONDITION)                                \
819                 if (_lock)                                              \
820                         SFXGE_BAR_UNLOCK(_esbp);                        \
821         _NOTE(CONSTANTCONDITION)                                        \
822         } while (B_FALSE)
823
824 #if defined(SFXGE_USE_BUS_SPACE_8)
825 #define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp)                          \
826         do {                                                            \
827                 _NOTE(CONSTANTCONDITION)                                \
828                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),    \
829                     ("not power of 2 aligned"));                        \
830                                                                         \
831                 SFXGE_BAR_LOCK(_esbp);                                  \
832                                                                         \
833                 EFSYS_PROBE3(bar_writeq, unsigned int, (_offset),       \
834                     uint32_t, (_eqp)->eq_u32[1],                        \
835                     uint32_t, (_eqp)->eq_u32[0]);                       \
836                                                                         \
837                 /*                                                      \
838                  * Make sure that previous writes to the qword have     \
839                  * been done. It should be cheaper than barrier just    \
840                  * after the write below.                               \
841                  */                                                     \
842                 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
843                     (_offset), sizeof (efx_qword_t),                    \
844                     BUS_SPACE_BARRIER_WRITE);                           \
845                 bus_space_write_stream_8((_esbp)->esb_tag,              \
846                     (_esbp)->esb_handle,                                \
847                     (_offset), (_eqp)->eq_u64[0]);                      \
848                                                                         \
849                 SFXGE_BAR_UNLOCK(_esbp);                                \
850         _NOTE(CONSTANTCONDITION)                                        \
851         } while (B_FALSE)
852 #else
853 #define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp)                          \
854         do {                                                            \
855                 _NOTE(CONSTANTCONDITION)                                \
856                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),    \
857                     ("not power of 2 aligned"));                        \
858                                                                         \
859                 SFXGE_BAR_LOCK(_esbp);                                  \
860                                                                         \
861                 EFSYS_PROBE3(bar_writeq, unsigned int, (_offset),       \
862                     uint32_t, (_eqp)->eq_u32[1],                        \
863                     uint32_t, (_eqp)->eq_u32[0]);                       \
864                                                                         \
865                 /*                                                      \
866                  * Make sure that previous writes to the qword have     \
867                  * been done. It should be cheaper than barrier just    \
868                  * after the last write below.                          \
869                  */                                                     \
870                 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
871                     (_offset), sizeof (efx_qword_t),                    \
872                     BUS_SPACE_BARRIER_WRITE);                           \
873                 bus_space_write_stream_4((_esbp)->esb_tag,              \
874                     (_esbp)->esb_handle,                                \
875                     (_offset), (_eqp)->eq_u32[0]);                      \
876                 /*                                                      \
877                  * It should be guaranteed that the last dword comes    \
878                  * the last, so barrier entire qword to be sure that    \
879                  * neither above nor below writes are reordered.        \
880                  */                                                     \
881                 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
882                     (_offset), sizeof (efx_qword_t),                    \
883                     BUS_SPACE_BARRIER_WRITE);                           \
884                 bus_space_write_stream_4((_esbp)->esb_tag,              \
885                     (_esbp)->esb_handle,                                \
886                     (_offset) + 4, (_eqp)->eq_u32[1]);                  \
887                                                                         \
888                 SFXGE_BAR_UNLOCK(_esbp);                                \
889         _NOTE(CONSTANTCONDITION)                                        \
890         } while (B_FALSE)
891 #endif
892
893 /*
894  * Guarantees 64bit aligned 64bit writes to write combined BAR mapping
895  * (required by PIO hardware)
896  */
897 #define EFSYS_BAR_WC_WRITEQ(_esbp, _offset, _eqp)                       \
898         do {                                                            \
899                 _NOTE(CONSTANTCONDITION)                                \
900                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),    \
901                     ("not power of 2 aligned"));                        \
902                                                                         \
903                 (void) (_esbp);                                         \
904                                                                         \
905                 /* FIXME: Perform a 64-bit write */                     \
906                 KASSERT(0, ("not implemented"));                        \
907                                                                         \
908         _NOTE(CONSTANTCONDITION)                                        \
909         } while (B_FALSE)
910
911 #if defined(SFXGE_USE_BUS_SPACE_8)
912 #define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock)                   \
913         do {                                                            \
914                 _NOTE(CONSTANTCONDITION)                                \
915                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),    \
916                     ("not power of 2 aligned"));                        \
917                                                                         \
918                 _NOTE(CONSTANTCONDITION)                                \
919                 if (_lock)                                              \
920                         SFXGE_BAR_LOCK(_esbp);                          \
921                                                                         \
922                 EFSYS_PROBE5(bar_writeo, unsigned int, (_offset),       \
923                     uint32_t, (_eop)->eo_u32[3],                        \
924                     uint32_t, (_eop)->eo_u32[2],                        \
925                     uint32_t, (_eop)->eo_u32[1],                        \
926                     uint32_t, (_eop)->eo_u32[0]);                       \
927                                                                         \
928                 /*                                                      \
929                  * Make sure that previous writes to the oword have     \
930                  * been done. It should be cheaper than barrier just    \
931                  * after the last write below.                          \
932                  */                                                     \
933                 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
934                     (_offset), sizeof (efx_oword_t),                    \
935                     BUS_SPACE_BARRIER_WRITE);                           \
936                 bus_space_write_stream_8((_esbp)->esb_tag,              \
937                     (_esbp)->esb_handle,                                \
938                     (_offset), (_eop)->eo_u64[0]);                      \
939                 /*                                                      \
940                  * It should be guaranteed that the last qword comes    \
941                  * the last, so barrier entire oword to be sure that    \
942                  * neither above nor below writes are reordered.        \
943                  */                                                     \
944                 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
945                     (_offset), sizeof (efx_oword_t),                    \
946                     BUS_SPACE_BARRIER_WRITE);                           \
947                 bus_space_write_stream_8((_esbp)->esb_tag,              \
948                     (_esbp)->esb_handle,                                \
949                     (_offset) + 8, (_eop)->eo_u64[1]);                  \
950                                                                         \
951                 _NOTE(CONSTANTCONDITION)                                \
952                 if (_lock)                                              \
953                         SFXGE_BAR_UNLOCK(_esbp);                        \
954         _NOTE(CONSTANTCONDITION)                                        \
955         } while (B_FALSE)
956
957 #else
958 #define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock)                   \
959         do {                                                            \
960                 _NOTE(CONSTANTCONDITION)                                \
961                 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),    \
962                     ("not power of 2 aligned"));                        \
963                                                                         \
964                 _NOTE(CONSTANTCONDITION)                                \
965                 if (_lock)                                              \
966                         SFXGE_BAR_LOCK(_esbp);                          \
967                                                                         \
968                 EFSYS_PROBE5(bar_writeo, unsigned int, (_offset),       \
969                     uint32_t, (_eop)->eo_u32[3],                        \
970                     uint32_t, (_eop)->eo_u32[2],                        \
971                     uint32_t, (_eop)->eo_u32[1],                        \
972                     uint32_t, (_eop)->eo_u32[0]);                       \
973                                                                         \
974                 /*                                                      \
975                  * Make sure that previous writes to the oword have     \
976                  * been done. It should be cheaper than barrier just    \
977                  * after the last write below.                          \
978                  */                                                     \
979                 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
980                     (_offset), sizeof (efx_oword_t),                    \
981                     BUS_SPACE_BARRIER_WRITE);                           \
982                 bus_space_write_stream_4((_esbp)->esb_tag,              \
983                     (_esbp)->esb_handle,                                \
984                     (_offset), (_eop)->eo_u32[0]);                      \
985                 bus_space_write_stream_4((_esbp)->esb_tag,              \
986                     (_esbp)->esb_handle,                                \
987                     (_offset) + 4, (_eop)->eo_u32[1]);                  \
988                 bus_space_write_stream_4((_esbp)->esb_tag,              \
989                     (_esbp)->esb_handle,                                \
990                     (_offset) + 8, (_eop)->eo_u32[2]);                  \
991                 /*                                                      \
992                  * It should be guaranteed that the last dword comes    \
993                  * the last, so barrier entire oword to be sure that    \
994                  * neither above nor below writes are reordered.        \
995                  */                                                     \
996                 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
997                     (_offset), sizeof (efx_oword_t),                    \
998                     BUS_SPACE_BARRIER_WRITE);                           \
999                 bus_space_write_stream_4((_esbp)->esb_tag,              \
1000                     (_esbp)->esb_handle,                                \
1001                     (_offset) + 12, (_eop)->eo_u32[3]);                 \
1002                                                                         \
1003                 _NOTE(CONSTANTCONDITION)                                \
1004                 if (_lock)                                              \
1005                         SFXGE_BAR_UNLOCK(_esbp);                        \
1006         _NOTE(CONSTANTCONDITION)                                        \
1007         } while (B_FALSE)
1008 #endif
1009
1010 /* Use the standard octo-word write for doorbell writes */
1011 #define EFSYS_BAR_DOORBELL_WRITEO(_esbp, _offset, _eop)                 \
1012         do {                                                            \
1013                 EFSYS_BAR_WRITEO((_esbp), (_offset), (_eop), B_FALSE);  \
1014         _NOTE(CONSTANTCONDITION)                                        \
1015         } while (B_FALSE)
1016
1017 /* SPIN */
1018
1019 #define EFSYS_SPIN(_us)                                                 \
1020         do {                                                            \
1021                 DELAY(_us);                                             \
1022         _NOTE(CONSTANTCONDITION)                                        \
1023         } while (B_FALSE)
1024
1025 #define EFSYS_SLEEP     EFSYS_SPIN
1026
1027 /* BARRIERS */
1028
1029 #define EFSYS_MEM_READ_BARRIER()        rmb()
1030 #define EFSYS_PIO_WRITE_BARRIER()
1031
1032 /* DMA SYNC */
1033 #define EFSYS_DMA_SYNC_FOR_KERNEL(_esmp, _offset, _size)                \
1034         do {                                                            \
1035                 bus_dmamap_sync((_esmp)->esm_tag,                       \
1036                     (_esmp)->esm_map,                                   \
1037                     BUS_DMASYNC_POSTREAD);                              \
1038         _NOTE(CONSTANTCONDITION)                                        \
1039         } while (B_FALSE)
1040
1041 #define EFSYS_DMA_SYNC_FOR_DEVICE(_esmp, _offset, _size)                \
1042         do {                                                            \
1043                 bus_dmamap_sync((_esmp)->esm_tag,                       \
1044                     (_esmp)->esm_map,                                   \
1045                     BUS_DMASYNC_PREWRITE);                              \
1046         _NOTE(CONSTANTCONDITION)                                        \
1047         } while (B_FALSE)
1048
1049 /* TIMESTAMP */
1050
1051 typedef clock_t efsys_timestamp_t;
1052
1053 #define EFSYS_TIMESTAMP(_usp)                                           \
1054         do {                                                            \
1055                 clock_t now;                                            \
1056                                                                         \
1057                 now = ticks;                                            \
1058                 *(_usp) = now * hz / 1000000;                           \
1059         _NOTE(CONSTANTCONDITION)                                        \
1060         } while (B_FALSE)
1061
1062 /* KMEM */
1063
1064 #define EFSYS_KMEM_ALLOC(_esip, _size, _p)                              \
1065         do {                                                            \
1066                 (_esip) = (_esip);                                      \
1067                 /*                                                      \
1068                  * The macro is used in non-sleepable contexts, for     \
1069                  * example, holding a mutex.                            \
1070                  */                                                     \
1071                 (_p) = malloc((_size), M_SFXGE, M_NOWAIT|M_ZERO);       \
1072         _NOTE(CONSTANTCONDITION)                                        \
1073         } while (B_FALSE)
1074
1075 #define EFSYS_KMEM_FREE(_esip, _size, _p)                               \
1076         do {                                                            \
1077                 (void) (_esip);                                         \
1078                 (void) (_size);                                         \
1079                 free((_p), M_SFXGE);                                    \
1080         _NOTE(CONSTANTCONDITION)                                        \
1081         } while (B_FALSE)
1082
1083 /* LOCK */
1084
1085 typedef struct efsys_lock_s {
1086         struct mtx      lock;
1087         char            lock_name[SFXGE_LOCK_NAME_MAX];
1088 } efsys_lock_t;
1089
1090 #define SFXGE_EFSYS_LOCK_INIT(_eslp, _ifname, _label)                   \
1091         do {                                                            \
1092                 efsys_lock_t *__eslp = (_eslp);                         \
1093                                                                         \
1094                 snprintf((__eslp)->lock_name,                           \
1095                          sizeof((__eslp)->lock_name),                   \
1096                          "%s:%s", (_ifname), (_label));                 \
1097                 mtx_init(&(__eslp)->lock, (__eslp)->lock_name,          \
1098                          NULL, MTX_DEF);                                \
1099         } while (B_FALSE)
1100 #define SFXGE_EFSYS_LOCK_DESTROY(_eslp)                                 \
1101         mtx_destroy(&(_eslp)->lock)
1102 #define SFXGE_EFSYS_LOCK(_eslp)                                         \
1103         mtx_lock(&(_eslp)->lock)
1104 #define SFXGE_EFSYS_UNLOCK(_eslp)                                       \
1105         mtx_unlock(&(_eslp)->lock)
1106 #define SFXGE_EFSYS_LOCK_ASSERT_OWNED(_eslp)                            \
1107         mtx_assert(&(_eslp)->lock, MA_OWNED)
1108
1109 #define EFSYS_LOCK_MAGIC        0x000010c4
1110
1111 #define EFSYS_LOCK(_lockp, _state)                                      \
1112         do {                                                            \
1113                 SFXGE_EFSYS_LOCK(_lockp);                               \
1114                 (_state) = EFSYS_LOCK_MAGIC;                            \
1115         _NOTE(CONSTANTCONDITION)                                        \
1116         } while (B_FALSE)
1117
1118 #define EFSYS_UNLOCK(_lockp, _state)                                    \
1119         do {                                                            \
1120                 if ((_state) != EFSYS_LOCK_MAGIC)                       \
1121                         KASSERT(B_FALSE, ("not locked"));               \
1122                 SFXGE_EFSYS_UNLOCK(_lockp);                             \
1123         _NOTE(CONSTANTCONDITION)                                        \
1124         } while (B_FALSE)
1125
1126 /* PREEMPT */
1127
1128 #define EFSYS_PREEMPT_DISABLE(_state)                                   \
1129         do {                                                            \
1130                 (_state) = (_state);                                    \
1131                 critical_enter();                                       \
1132         _NOTE(CONSTANTCONDITION)                                        \
1133         } while (B_FALSE)
1134
1135 #define EFSYS_PREEMPT_ENABLE(_state)                                    \
1136         do {                                                            \
1137                 (_state) = (_state);                                    \
1138                 critical_exit(_state);                                  \
1139         _NOTE(CONSTANTCONDITION)                                        \
1140         } while (B_FALSE)
1141
1142 /* STAT */
1143
1144 typedef uint64_t                efsys_stat_t;
1145
1146 #define EFSYS_STAT_INCR(_knp, _delta)                                   \
1147         do {                                                            \
1148                 *(_knp) += (_delta);                                    \
1149         _NOTE(CONSTANTCONDITION)                                        \
1150         } while (B_FALSE)
1151
1152 #define EFSYS_STAT_DECR(_knp, _delta)                                   \
1153         do {                                                            \
1154                 *(_knp) -= (_delta);                                    \
1155         _NOTE(CONSTANTCONDITION)                                        \
1156         } while (B_FALSE)
1157
1158 #define EFSYS_STAT_SET(_knp, _val)                                      \
1159         do {                                                            \
1160                 *(_knp) = (_val);                                       \
1161         _NOTE(CONSTANTCONDITION)                                        \
1162         } while (B_FALSE)
1163
1164 #define EFSYS_STAT_SET_QWORD(_knp, _valp)                               \
1165         do {                                                            \
1166                 *(_knp) = le64toh((_valp)->eq_u64[0]);                  \
1167         _NOTE(CONSTANTCONDITION)                                        \
1168         } while (B_FALSE)
1169
1170 #define EFSYS_STAT_SET_DWORD(_knp, _valp)                               \
1171         do {                                                            \
1172                 *(_knp) = le32toh((_valp)->ed_u32[0]);                  \
1173         _NOTE(CONSTANTCONDITION)                                        \
1174         } while (B_FALSE)
1175
1176 #define EFSYS_STAT_INCR_QWORD(_knp, _valp)                              \
1177         do {                                                            \
1178                 *(_knp) += le64toh((_valp)->eq_u64[0]);                 \
1179         _NOTE(CONSTANTCONDITION)                                        \
1180         } while (B_FALSE)
1181
1182 #define EFSYS_STAT_SUBR_QWORD(_knp, _valp)                              \
1183         do {                                                            \
1184                 *(_knp) -= le64toh((_valp)->eq_u64[0]);                 \
1185         _NOTE(CONSTANTCONDITION)                                        \
1186         } while (B_FALSE)
1187
1188 /* ERR */
1189
1190 extern void     sfxge_err(efsys_identifier_t *, unsigned int,
1191                     uint32_t, uint32_t);
1192
1193 #if EFSYS_OPT_DECODE_INTR_FATAL
1194 #define EFSYS_ERR(_esip, _code, _dword0, _dword1)                       \
1195         do {                                                            \
1196                 sfxge_err((_esip), (_code), (_dword0), (_dword1));      \
1197         _NOTE(CONSTANTCONDITION)                                        \
1198         } while (B_FALSE)
1199 #endif
1200
1201 /* ASSERT */
1202
1203 #define EFSYS_ASSERT(_exp) do {                                         \
1204         if (!(_exp))                                                    \
1205                 panic("%s", #_exp);                                     \
1206         } while (0)
1207
1208 #define EFSYS_ASSERT3(_x, _op, _y, _t) do {                             \
1209         const _t __x = (_t)(_x);                                        \
1210         const _t __y = (_t)(_y);                                        \
1211         if (!(__x _op __y))                                             \
1212                 panic("assertion failed at %s:%u", __FILE__, __LINE__); \
1213         } while(0)
1214
1215 #define EFSYS_ASSERT3U(_x, _op, _y)     EFSYS_ASSERT3(_x, _op, _y, uint64_t)
1216 #define EFSYS_ASSERT3S(_x, _op, _y)     EFSYS_ASSERT3(_x, _op, _y, int64_t)
1217 #define EFSYS_ASSERT3P(_x, _op, _y)     EFSYS_ASSERT3(_x, _op, _y, uintptr_t)
1218
1219 /* ROTATE */
1220
1221 #define EFSYS_HAS_ROTL_DWORD 0
1222
1223 #ifdef  __cplusplus
1224 }
1225 #endif
1226
1227 #endif  /* _SYS_EFSYS_H */