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