efsys.h revision 284555
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: stable/10/sys/dev/sfxge/common/efsys.h 284555 2015-06-18 15:46:39Z arybchik $
34 */
35
36#ifndef	_SYS_EFSYS_H
37#define	_SYS_EFSYS_H
38
39#ifdef	__cplusplus
40extern "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 */
125MALLOC_DECLARE(M_SFXGE);
126
127/* Machine dependend prefetch wrappers */
128#if defined(__i386__) || defined(__amd64__)
129static __inline void
130prefetch_read_many(void *addr)
131{
132
133	__asm__(
134	    "prefetcht0 (%0)"
135	    :
136	    : "r" (addr));
137}
138
139static __inline void
140prefetch_read_once(void *addr)
141{
142
143	__asm__(
144	    "prefetchnta (%0)"
145	    :
146	    : "r" (addr));
147}
148#elif defined(__sparc64__)
149static __inline void
150prefetch_read_many(void *addr)
151{
152
153	__asm__(
154	    "prefetch [%0], 0"
155	    :
156	    : "r" (addr));
157}
158
159static __inline void
160prefetch_read_once(void *addr)
161{
162
163	__asm__(
164	    "prefetch [%0], 1"
165	    :
166	    : "r" (addr));
167}
168#else
169static __inline void
170prefetch_read_many(void *addr)
171{
172
173}
174
175static __inline void
176prefetch_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
186static __inline void
187sfxge_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
296typedef 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
393typedef uint64_t		efsys_dma_addr_t;
394
395typedef 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
635typedef 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
1051typedef	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
1085typedef 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
1144typedef 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
1190extern 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 */
1228