efsys.h revision 294386
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 294386 2016-01-20 08:01:21Z 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#define	__out_bcount_part(_n, _l)
215#define	__out_bcount_part_opt(_n, _l)
216
217#define	__deref_out
218
219#define	__inout
220#define	__inout_opt
221#define	__inout_ecount(_n)
222#define	__inout_ecount_opt(_n)
223#define	__inout_bcount(_n)
224#define	__inout_bcount_opt(_n)
225#define	__inout_bcount_full_opt(_n)
226
227#define	__deref_out_bcount_opt(n)
228
229#define	__checkReturn
230#define	__success(_x)
231
232#define	__drv_when(_p, _c)
233
234/* Code inclusion options */
235
236
237#define	EFSYS_OPT_NAMES 1
238
239#define	EFSYS_OPT_FALCON 0
240#define	EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE 0
241#define	EFSYS_OPT_SIENA 1
242#define	EFSYS_OPT_HUNTINGTON 1
243#define	EFSYS_OPT_MEDFORD 0
244#ifdef DEBUG
245#define	EFSYS_OPT_CHECK_REG 1
246#else
247#define	EFSYS_OPT_CHECK_REG 0
248#endif
249
250#define	EFSYS_OPT_MCDI 1
251#define	EFSYS_OPT_MCDI_LOGGING 0
252#define	EFSYS_OPT_MCDI_PROXY_AUTH 0
253
254#define	EFSYS_OPT_MAC_FALCON_GMAC 0
255#define	EFSYS_OPT_MAC_FALCON_XMAC 0
256#define	EFSYS_OPT_MAC_STATS 1
257
258#define	EFSYS_OPT_LOOPBACK 0
259
260#define	EFSYS_OPT_MON_NULL 0
261#define	EFSYS_OPT_MON_LM87 0
262#define	EFSYS_OPT_MON_MAX6647 0
263#define	EFSYS_OPT_MON_MCDI 0
264#define	EFSYS_OPT_MON_STATS 0
265
266#define	EFSYS_OPT_PHY_NULL 0
267#define	EFSYS_OPT_PHY_QT2022C2 0
268#define	EFSYS_OPT_PHY_SFX7101 0
269#define	EFSYS_OPT_PHY_TXC43128 0
270#define	EFSYS_OPT_PHY_SFT9001 0
271#define	EFSYS_OPT_PHY_QT2025C 0
272#define	EFSYS_OPT_PHY_STATS 1
273#define	EFSYS_OPT_PHY_PROPS 0
274#define	EFSYS_OPT_PHY_BIST 0
275#define	EFSYS_OPT_BIST 1
276#define	EFSYS_OPT_PHY_LED_CONTROL 1
277#define	EFSYS_OPT_PHY_FLAGS 0
278
279#define	EFSYS_OPT_VPD 1
280#define	EFSYS_OPT_NVRAM 1
281#define	EFSYS_OPT_NVRAM_FALCON_BOOTROM 0
282#define	EFSYS_OPT_NVRAM_SFT9001	0
283#define	EFSYS_OPT_NVRAM_SFX7101	0
284#define	EFSYS_OPT_BOOTCFG 0
285
286#define	EFSYS_OPT_PCIE_TUNE 0
287#define	EFSYS_OPT_DIAG 0
288#define	EFSYS_OPT_WOL 1
289#define	EFSYS_OPT_RX_SCALE 1
290#define	EFSYS_OPT_QSTATS 1
291#define	EFSYS_OPT_FILTER 1
292#define	EFSYS_OPT_RX_SCATTER 0
293
294#define	EFSYS_OPT_EV_PREFETCH 0
295
296#define	EFSYS_OPT_DECODE_INTR_FATAL 1
297
298#define	EFSYS_OPT_LICENSING 0
299
300/* ID */
301
302typedef struct __efsys_identifier_s	efsys_identifier_t;
303
304/* PROBE */
305
306#ifndef KDTRACE_HOOKS
307
308#define	EFSYS_PROBE(_name)
309
310#define	EFSYS_PROBE1(_name, _type1, _arg1)
311
312#define	EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)
313
314#define	EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2,		\
315	    _type3, _arg3)
316
317#define	EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2,		\
318	    _type3, _arg3, _type4, _arg4)
319
320#define	EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
321	    _type3, _arg3, _type4, _arg4, _type5, _arg5)
322
323#define	EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
324	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
325	    _type6, _arg6)
326
327#define	EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,		\
328	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
329	    _type6, _arg6, _type7, _arg7)
330
331#else /* KDTRACE_HOOKS */
332
333#define	EFSYS_PROBE(_name)						\
334	DTRACE_PROBE(_name)
335
336#define	EFSYS_PROBE1(_name, _type1, _arg1)				\
337	DTRACE_PROBE1(_name, _type1, _arg1)
338
339#define	EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)		\
340	DTRACE_PROBE2(_name, _type1, _arg1, _type2, _arg2)
341
342#define	EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2,		\
343	    _type3, _arg3)						\
344	DTRACE_PROBE3(_name, _type1, _arg1, _type2, _arg2,		\
345	    _type3, _arg3)
346
347#define	EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2,		\
348	    _type3, _arg3, _type4, _arg4)				\
349	DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2,		\
350	    _type3, _arg3, _type4, _arg4)
351
352#ifdef DTRACE_PROBE5
353#define	EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
354	    _type3, _arg3, _type4, _arg4, _type5, _arg5)		\
355	DTRACE_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
356	    _type3, _arg3, _type4, _arg4, _type5, _arg5)
357#else
358#define	EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
359	    _type3, _arg3, _type4, _arg4, _type5, _arg5)		\
360	DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2,		\
361	    _type3, _arg3, _type4, _arg4)
362#endif
363
364#ifdef DTRACE_PROBE6
365#define	EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
366	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
367	    _type6, _arg6)						\
368	DTRACE_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
369	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
370	    _type6, _arg6)
371#else
372#define	EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
373	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
374	    _type6, _arg6)						\
375	EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
376	    _type3, _arg3, _type4, _arg4, _type5, _arg5)
377#endif
378
379#ifdef DTRACE_PROBE7
380#define	EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,		\
381	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
382	    _type6, _arg6, _type7, _arg7)				\
383	DTRACE_PROBE7(_name, _type1, _arg1, _type2, _arg2,		\
384	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
385	    _type6, _arg6, _type7, _arg7)
386#else
387#define	EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,		\
388	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
389	    _type6, _arg6, _type7, _arg7)				\
390	EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
391	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
392	    _type6, _arg6)
393#endif
394
395#endif /* KDTRACE_HOOKS */
396
397/* DMA */
398
399typedef uint64_t		efsys_dma_addr_t;
400
401typedef struct efsys_mem_s {
402	bus_dma_tag_t		esm_tag;
403	bus_dmamap_t		esm_map;
404	caddr_t			esm_base;
405	efsys_dma_addr_t	esm_addr;
406} efsys_mem_t;
407
408
409#define	EFSYS_MEM_ZERO(_esmp, _size)					\
410	do {								\
411		(void) memset((_esmp)->esm_base, 0, (_size));		\
412									\
413	_NOTE(CONSTANTCONDITION)					\
414	} while (B_FALSE)
415
416#define	EFSYS_MEM_READD(_esmp, _offset, _edp)				\
417	do {								\
418		uint32_t *addr;						\
419									\
420		_NOTE(CONSTANTCONDITION)				\
421		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),	\
422		    ("not power of 2 aligned"));			\
423									\
424		addr = (void *)((_esmp)->esm_base + (_offset));		\
425									\
426		(_edp)->ed_u32[0] = *addr;				\
427									\
428		EFSYS_PROBE2(mem_readd, unsigned int, (_offset),	\
429		    uint32_t, (_edp)->ed_u32[0]);			\
430									\
431	_NOTE(CONSTANTCONDITION)					\
432	} while (B_FALSE)
433
434#if defined(__x86_64__)
435#define	EFSYS_MEM_READQ(_esmp, _offset, _eqp)				\
436	do {								\
437		uint64_t *addr;						\
438									\
439		_NOTE(CONSTANTCONDITION)				\
440		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
441		    ("not power of 2 aligned"));			\
442									\
443		addr = (void *)((_esmp)->esm_base + (_offset));		\
444									\
445		(_eqp)->eq_u64[0] = *addr;				\
446									\
447		EFSYS_PROBE3(mem_readq, unsigned int, (_offset),	\
448		    uint32_t, (_eqp)->eq_u32[1],			\
449		    uint32_t, (_eqp)->eq_u32[0]);			\
450									\
451	_NOTE(CONSTANTCONDITION)					\
452	} while (B_FALSE)
453#else
454#define	EFSYS_MEM_READQ(_esmp, _offset, _eqp)				\
455	do {								\
456		uint32_t *addr;						\
457									\
458		_NOTE(CONSTANTCONDITION)				\
459		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
460		    ("not power of 2 aligned"));			\
461									\
462		addr = (void *)((_esmp)->esm_base + (_offset));		\
463									\
464		(_eqp)->eq_u32[0] = *addr++;				\
465		(_eqp)->eq_u32[1] = *addr;				\
466									\
467		EFSYS_PROBE3(mem_readq, unsigned int, (_offset),	\
468		    uint32_t, (_eqp)->eq_u32[1],			\
469		    uint32_t, (_eqp)->eq_u32[0]);			\
470									\
471	_NOTE(CONSTANTCONDITION)					\
472	} while (B_FALSE)
473#endif
474
475#if defined(__x86_64__)
476#define	EFSYS_MEM_READO(_esmp, _offset, _eop)				\
477	do {								\
478		uint64_t *addr;						\
479									\
480		_NOTE(CONSTANTCONDITION)				\
481		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
482		    ("not power of 2 aligned"));			\
483									\
484		addr = (void *)((_esmp)->esm_base + (_offset));		\
485									\
486		(_eop)->eo_u64[0] = *addr++;				\
487		(_eop)->eo_u64[1] = *addr;				\
488									\
489		EFSYS_PROBE5(mem_reado, unsigned int, (_offset),	\
490		    uint32_t, (_eop)->eo_u32[3],			\
491		    uint32_t, (_eop)->eo_u32[2],			\
492		    uint32_t, (_eop)->eo_u32[1],			\
493		    uint32_t, (_eop)->eo_u32[0]);			\
494									\
495	_NOTE(CONSTANTCONDITION)					\
496	} while (B_FALSE)
497#else
498#define	EFSYS_MEM_READO(_esmp, _offset, _eop)				\
499	do {								\
500		uint32_t *addr;						\
501									\
502		_NOTE(CONSTANTCONDITION)				\
503		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
504		    ("not power of 2 aligned"));			\
505									\
506		addr = (void *)((_esmp)->esm_base + (_offset));		\
507									\
508		(_eop)->eo_u32[0] = *addr++;				\
509		(_eop)->eo_u32[1] = *addr++;				\
510		(_eop)->eo_u32[2] = *addr++;				\
511		(_eop)->eo_u32[3] = *addr;				\
512									\
513		EFSYS_PROBE5(mem_reado, unsigned int, (_offset),	\
514		    uint32_t, (_eop)->eo_u32[3],			\
515		    uint32_t, (_eop)->eo_u32[2],			\
516		    uint32_t, (_eop)->eo_u32[1],			\
517		    uint32_t, (_eop)->eo_u32[0]);			\
518									\
519	_NOTE(CONSTANTCONDITION)					\
520	} while (B_FALSE)
521#endif
522
523#define	EFSYS_MEM_WRITED(_esmp, _offset, _edp)				\
524	do {								\
525		uint32_t *addr;						\
526									\
527		_NOTE(CONSTANTCONDITION)				\
528		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),	\
529		    ("not power of 2 aligned"));			\
530									\
531		EFSYS_PROBE2(mem_writed, unsigned int, (_offset),	\
532		    uint32_t, (_edp)->ed_u32[0]);			\
533									\
534		addr = (void *)((_esmp)->esm_base + (_offset));		\
535									\
536		*addr = (_edp)->ed_u32[0];				\
537									\
538	_NOTE(CONSTANTCONDITION)					\
539	} while (B_FALSE)
540
541#if defined(__x86_64__)
542#define	EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp)				\
543	do {								\
544		uint64_t *addr;						\
545									\
546		_NOTE(CONSTANTCONDITION)				\
547		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
548		    ("not power of 2 aligned"));			\
549									\
550		EFSYS_PROBE3(mem_writeq, unsigned int, (_offset),	\
551		    uint32_t, (_eqp)->eq_u32[1],			\
552		    uint32_t, (_eqp)->eq_u32[0]);			\
553									\
554		addr = (void *)((_esmp)->esm_base + (_offset));		\
555									\
556		*addr   = (_eqp)->eq_u64[0];				\
557									\
558	_NOTE(CONSTANTCONDITION)					\
559	} while (B_FALSE)
560
561#else
562#define	EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp)				\
563	do {								\
564		uint32_t *addr;						\
565									\
566		_NOTE(CONSTANTCONDITION)				\
567		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
568		    ("not power of 2 aligned"));			\
569									\
570		EFSYS_PROBE3(mem_writeq, unsigned int, (_offset),	\
571		    uint32_t, (_eqp)->eq_u32[1],			\
572		    uint32_t, (_eqp)->eq_u32[0]);			\
573									\
574		addr = (void *)((_esmp)->esm_base + (_offset));		\
575									\
576		*addr++ = (_eqp)->eq_u32[0];				\
577		*addr   = (_eqp)->eq_u32[1];				\
578									\
579	_NOTE(CONSTANTCONDITION)					\
580	} while (B_FALSE)
581#endif
582
583#if defined(__x86_64__)
584#define	EFSYS_MEM_WRITEO(_esmp, _offset, _eop)				\
585	do {								\
586		uint64_t *addr;						\
587									\
588		_NOTE(CONSTANTCONDITION)				\
589		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
590		    ("not power of 2 aligned"));			\
591									\
592		EFSYS_PROBE5(mem_writeo, unsigned int, (_offset),	\
593		    uint32_t, (_eop)->eo_u32[3],			\
594		    uint32_t, (_eop)->eo_u32[2],			\
595		    uint32_t, (_eop)->eo_u32[1],			\
596		    uint32_t, (_eop)->eo_u32[0]);			\
597									\
598		addr = (void *)((_esmp)->esm_base + (_offset));		\
599									\
600		*addr++ = (_eop)->eo_u64[0];				\
601		*addr   = (_eop)->eo_u64[1];				\
602									\
603	_NOTE(CONSTANTCONDITION)					\
604	} while (B_FALSE)
605#else
606#define	EFSYS_MEM_WRITEO(_esmp, _offset, _eop)				\
607	do {								\
608		uint32_t *addr;						\
609									\
610		_NOTE(CONSTANTCONDITION)				\
611		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
612		    ("not power of 2 aligned"));			\
613									\
614		EFSYS_PROBE5(mem_writeo, unsigned int, (_offset),	\
615		    uint32_t, (_eop)->eo_u32[3],			\
616		    uint32_t, (_eop)->eo_u32[2],			\
617		    uint32_t, (_eop)->eo_u32[1],			\
618		    uint32_t, (_eop)->eo_u32[0]);			\
619									\
620		addr = (void *)((_esmp)->esm_base + (_offset));		\
621									\
622		*addr++ = (_eop)->eo_u32[0];				\
623		*addr++ = (_eop)->eo_u32[1];				\
624		*addr++ = (_eop)->eo_u32[2];				\
625		*addr   = (_eop)->eo_u32[3];				\
626									\
627	_NOTE(CONSTANTCONDITION)					\
628	} while (B_FALSE)
629#endif
630
631#define	EFSYS_MEM_ADDR(_esmp)						\
632	((_esmp)->esm_addr)
633
634#define	EFSYS_MEM_IS_NULL(_esmp)					\
635	((_esmp)->esm_base == NULL)
636
637/* BAR */
638
639#define	SFXGE_LOCK_NAME_MAX	16
640
641typedef struct efsys_bar_s {
642	struct mtx		esb_lock;
643	char			esb_lock_name[SFXGE_LOCK_NAME_MAX];
644	bus_space_tag_t		esb_tag;
645	bus_space_handle_t	esb_handle;
646	int			esb_rid;
647	struct resource		*esb_res;
648} efsys_bar_t;
649
650#define	SFXGE_BAR_LOCK_INIT(_esbp, _ifname)				\
651	do {								\
652		snprintf((_esbp)->esb_lock_name,			\
653			 sizeof((_esbp)->esb_lock_name),		\
654			 "%s:bar", (_ifname));				\
655		mtx_init(&(_esbp)->esb_lock, (_esbp)->esb_lock_name,	\
656			 NULL, MTX_DEF);				\
657	_NOTE(CONSTANTCONDITION)					\
658	} while (B_FALSE)
659#define	SFXGE_BAR_LOCK_DESTROY(_esbp)					\
660	mtx_destroy(&(_esbp)->esb_lock)
661#define	SFXGE_BAR_LOCK(_esbp)						\
662	mtx_lock(&(_esbp)->esb_lock)
663#define	SFXGE_BAR_UNLOCK(_esbp)						\
664	mtx_unlock(&(_esbp)->esb_lock)
665
666#define	EFSYS_BAR_READD(_esbp, _offset, _edp, _lock)			\
667	do {								\
668		_NOTE(CONSTANTCONDITION)				\
669		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),	\
670		    ("not power of 2 aligned"));			\
671									\
672		_NOTE(CONSTANTCONDITION)				\
673		if (_lock)						\
674			SFXGE_BAR_LOCK(_esbp);				\
675									\
676		(_edp)->ed_u32[0] = bus_space_read_stream_4(		\
677		    (_esbp)->esb_tag, (_esbp)->esb_handle,		\
678		    (_offset));						\
679									\
680		EFSYS_PROBE2(bar_readd, unsigned int, (_offset),	\
681		    uint32_t, (_edp)->ed_u32[0]);			\
682									\
683		_NOTE(CONSTANTCONDITION)				\
684		if (_lock)						\
685			SFXGE_BAR_UNLOCK(_esbp);			\
686	_NOTE(CONSTANTCONDITION)					\
687	} while (B_FALSE)
688
689#if defined(SFXGE_USE_BUS_SPACE_8)
690#define	EFSYS_BAR_READQ(_esbp, _offset, _eqp)				\
691	do {								\
692		_NOTE(CONSTANTCONDITION)				\
693		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
694		    ("not power of 2 aligned"));			\
695									\
696		SFXGE_BAR_LOCK(_esbp);					\
697									\
698		(_eqp)->eq_u64[0] = bus_space_read_stream_8(		\
699		    (_esbp)->esb_tag, (_esbp)->esb_handle,		\
700		    (_offset));						\
701									\
702		EFSYS_PROBE3(bar_readq, unsigned int, (_offset),	\
703		    uint32_t, (_eqp)->eq_u32[1],			\
704		    uint32_t, (_eqp)->eq_u32[0]);			\
705									\
706		SFXGE_BAR_UNLOCK(_esbp);				\
707	_NOTE(CONSTANTCONDITION)					\
708	} while (B_FALSE)
709
710#define	EFSYS_BAR_READO(_esbp, _offset, _eop, _lock)			\
711	do {								\
712		_NOTE(CONSTANTCONDITION)				\
713		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
714		    ("not power of 2 aligned"));			\
715									\
716		_NOTE(CONSTANTCONDITION)				\
717		if (_lock)						\
718			SFXGE_BAR_LOCK(_esbp);				\
719									\
720		(_eop)->eo_u64[0] = bus_space_read_stream_8(		\
721		    (_esbp)->esb_tag, (_esbp)->esb_handle,		\
722		    (_offset));						\
723		(_eop)->eo_u64[1] = bus_space_read_stream_8(		\
724		    (_esbp)->esb_tag, (_esbp)->esb_handle,		\
725		    (_offset) + 8);					\
726									\
727		EFSYS_PROBE5(bar_reado, unsigned int, (_offset),	\
728		    uint32_t, (_eop)->eo_u32[3],			\
729		    uint32_t, (_eop)->eo_u32[2],			\
730		    uint32_t, (_eop)->eo_u32[1],			\
731		    uint32_t, (_eop)->eo_u32[0]);			\
732									\
733		_NOTE(CONSTANTCONDITION)				\
734		if (_lock)						\
735			SFXGE_BAR_UNLOCK(_esbp);			\
736	_NOTE(CONSTANTCONDITION)					\
737	} while (B_FALSE)
738
739#else
740#define	EFSYS_BAR_READQ(_esbp, _offset, _eqp)				\
741	do {								\
742		_NOTE(CONSTANTCONDITION)				\
743		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
744		    ("not power of 2 aligned"));			\
745									\
746		SFXGE_BAR_LOCK(_esbp);					\
747									\
748		(_eqp)->eq_u32[0] = bus_space_read_stream_4(		\
749		    (_esbp)->esb_tag, (_esbp)->esb_handle,		\
750		    (_offset));						\
751		(_eqp)->eq_u32[1] = bus_space_read_stream_4(		\
752		    (_esbp)->esb_tag, (_esbp)->esb_handle,		\
753		    (_offset) + 4);					\
754									\
755		EFSYS_PROBE3(bar_readq, unsigned int, (_offset),	\
756		    uint32_t, (_eqp)->eq_u32[1],			\
757		    uint32_t, (_eqp)->eq_u32[0]);			\
758									\
759		SFXGE_BAR_UNLOCK(_esbp);				\
760	_NOTE(CONSTANTCONDITION)					\
761	} while (B_FALSE)
762
763#define	EFSYS_BAR_READO(_esbp, _offset, _eop, _lock)			\
764	do {								\
765		_NOTE(CONSTANTCONDITION)				\
766		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
767		    ("not power of 2 aligned"));			\
768									\
769		_NOTE(CONSTANTCONDITION)				\
770		if (_lock)						\
771			SFXGE_BAR_LOCK(_esbp);				\
772									\
773		(_eop)->eo_u32[0] = bus_space_read_stream_4(		\
774		    (_esbp)->esb_tag, (_esbp)->esb_handle,		\
775		    (_offset));						\
776		(_eop)->eo_u32[1] = bus_space_read_stream_4(		\
777		    (_esbp)->esb_tag, (_esbp)->esb_handle,		\
778		    (_offset) + 4);					\
779		(_eop)->eo_u32[2] = bus_space_read_stream_4(		\
780		    (_esbp)->esb_tag, (_esbp)->esb_handle,		\
781		    (_offset) + 8);					\
782		(_eop)->eo_u32[3] = bus_space_read_stream_4(		\
783		    (_esbp)->esb_tag, (_esbp)->esb_handle,		\
784		    (_offset) + 12);					\
785									\
786		EFSYS_PROBE5(bar_reado, unsigned int, (_offset),	\
787		    uint32_t, (_eop)->eo_u32[3],			\
788		    uint32_t, (_eop)->eo_u32[2],			\
789		    uint32_t, (_eop)->eo_u32[1],			\
790		    uint32_t, (_eop)->eo_u32[0]);			\
791									\
792		_NOTE(CONSTANTCONDITION)				\
793		if (_lock)						\
794			SFXGE_BAR_UNLOCK(_esbp);			\
795	_NOTE(CONSTANTCONDITION)					\
796	} while (B_FALSE)
797#endif
798
799#define	EFSYS_BAR_WRITED(_esbp, _offset, _edp, _lock)			\
800	do {								\
801		_NOTE(CONSTANTCONDITION)				\
802		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),	\
803		    ("not power of 2 aligned"));			\
804									\
805		_NOTE(CONSTANTCONDITION)				\
806		if (_lock)						\
807			SFXGE_BAR_LOCK(_esbp);				\
808									\
809		EFSYS_PROBE2(bar_writed, unsigned int, (_offset),	\
810		    uint32_t, (_edp)->ed_u32[0]);			\
811									\
812		/*							\
813		 * Make sure that previous writes to the dword have	\
814		 * been done. It should be cheaper than barrier just	\
815		 * after the write below.				\
816		 */							\
817		bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
818		    (_offset), sizeof (efx_dword_t),			\
819		    BUS_SPACE_BARRIER_WRITE);				\
820		bus_space_write_stream_4((_esbp)->esb_tag,		\
821		    (_esbp)->esb_handle,				\
822		    (_offset), (_edp)->ed_u32[0]);			\
823									\
824		_NOTE(CONSTANTCONDITION)				\
825		if (_lock)						\
826			SFXGE_BAR_UNLOCK(_esbp);			\
827	_NOTE(CONSTANTCONDITION)					\
828	} while (B_FALSE)
829
830#if defined(SFXGE_USE_BUS_SPACE_8)
831#define	EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp)				\
832	do {								\
833		_NOTE(CONSTANTCONDITION)				\
834		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
835		    ("not power of 2 aligned"));			\
836									\
837		SFXGE_BAR_LOCK(_esbp);					\
838									\
839		EFSYS_PROBE3(bar_writeq, unsigned int, (_offset),	\
840		    uint32_t, (_eqp)->eq_u32[1],			\
841		    uint32_t, (_eqp)->eq_u32[0]);			\
842									\
843		/*							\
844		 * Make sure that previous writes to the qword have	\
845		 * been done. It should be cheaper than barrier just	\
846		 * after the write below.				\
847		 */							\
848		bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
849		    (_offset), sizeof (efx_qword_t),			\
850		    BUS_SPACE_BARRIER_WRITE);				\
851		bus_space_write_stream_8((_esbp)->esb_tag,		\
852		    (_esbp)->esb_handle,				\
853		    (_offset), (_eqp)->eq_u64[0]);			\
854									\
855		SFXGE_BAR_UNLOCK(_esbp);				\
856	_NOTE(CONSTANTCONDITION)					\
857	} while (B_FALSE)
858#else
859#define	EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp)				\
860	do {								\
861		_NOTE(CONSTANTCONDITION)				\
862		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
863		    ("not power of 2 aligned"));			\
864									\
865		SFXGE_BAR_LOCK(_esbp);					\
866									\
867		EFSYS_PROBE3(bar_writeq, unsigned int, (_offset),	\
868		    uint32_t, (_eqp)->eq_u32[1],			\
869		    uint32_t, (_eqp)->eq_u32[0]);			\
870									\
871		/*							\
872		 * Make sure that previous writes to the qword have	\
873		 * been done. It should be cheaper than barrier just	\
874		 * after the last write below.				\
875		 */							\
876		bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
877		    (_offset), sizeof (efx_qword_t),			\
878		    BUS_SPACE_BARRIER_WRITE);				\
879		bus_space_write_stream_4((_esbp)->esb_tag,		\
880		    (_esbp)->esb_handle,				\
881		    (_offset), (_eqp)->eq_u32[0]);			\
882		/*							\
883		 * It should be guaranteed that the last dword comes	\
884		 * the last, so barrier entire qword to be sure that	\
885		 * neither above nor below writes are reordered.	\
886		 */							\
887		bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
888		    (_offset), sizeof (efx_qword_t),			\
889		    BUS_SPACE_BARRIER_WRITE);				\
890		bus_space_write_stream_4((_esbp)->esb_tag,		\
891		    (_esbp)->esb_handle,				\
892		    (_offset) + 4, (_eqp)->eq_u32[1]);			\
893									\
894		SFXGE_BAR_UNLOCK(_esbp);				\
895	_NOTE(CONSTANTCONDITION)					\
896	} while (B_FALSE)
897#endif
898
899/*
900 * Guarantees 64bit aligned 64bit writes to write combined BAR mapping
901 * (required by PIO hardware)
902 */
903#define	EFSYS_BAR_WC_WRITEQ(_esbp, _offset, _eqp)			\
904	do {								\
905		_NOTE(CONSTANTCONDITION)				\
906		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
907		    ("not power of 2 aligned"));			\
908									\
909		(void) (_esbp);						\
910									\
911		/* FIXME: Perform a 64-bit write */			\
912		KASSERT(0, ("not implemented"));			\
913									\
914	_NOTE(CONSTANTCONDITION)					\
915	} while (B_FALSE)
916
917#if defined(SFXGE_USE_BUS_SPACE_8)
918#define	EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock)			\
919	do {								\
920		_NOTE(CONSTANTCONDITION)				\
921		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
922		    ("not power of 2 aligned"));			\
923									\
924		_NOTE(CONSTANTCONDITION)				\
925		if (_lock)						\
926			SFXGE_BAR_LOCK(_esbp);				\
927									\
928		EFSYS_PROBE5(bar_writeo, unsigned int, (_offset),	\
929		    uint32_t, (_eop)->eo_u32[3],			\
930		    uint32_t, (_eop)->eo_u32[2],			\
931		    uint32_t, (_eop)->eo_u32[1],			\
932		    uint32_t, (_eop)->eo_u32[0]);			\
933									\
934		/*							\
935		 * Make sure that previous writes to the oword have	\
936		 * been done. It should be cheaper than barrier just	\
937		 * after the last write below.				\
938		 */							\
939		bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
940		    (_offset), sizeof (efx_oword_t),			\
941		    BUS_SPACE_BARRIER_WRITE);				\
942		bus_space_write_stream_8((_esbp)->esb_tag,		\
943		    (_esbp)->esb_handle,				\
944		    (_offset), (_eop)->eo_u64[0]);			\
945		/*							\
946		 * It should be guaranteed that the last qword comes	\
947		 * the last, so barrier entire oword to be sure that	\
948		 * neither above nor below writes are reordered.	\
949		 */							\
950		bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
951		    (_offset), sizeof (efx_oword_t),			\
952		    BUS_SPACE_BARRIER_WRITE);				\
953		bus_space_write_stream_8((_esbp)->esb_tag,		\
954		    (_esbp)->esb_handle,				\
955		    (_offset) + 8, (_eop)->eo_u64[1]);			\
956									\
957		_NOTE(CONSTANTCONDITION)				\
958		if (_lock)						\
959			SFXGE_BAR_UNLOCK(_esbp);			\
960	_NOTE(CONSTANTCONDITION)					\
961	} while (B_FALSE)
962
963#else
964#define	EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock)			\
965	do {								\
966		_NOTE(CONSTANTCONDITION)				\
967		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
968		    ("not power of 2 aligned"));			\
969									\
970		_NOTE(CONSTANTCONDITION)				\
971		if (_lock)						\
972			SFXGE_BAR_LOCK(_esbp);				\
973									\
974		EFSYS_PROBE5(bar_writeo, unsigned int, (_offset),	\
975		    uint32_t, (_eop)->eo_u32[3],			\
976		    uint32_t, (_eop)->eo_u32[2],			\
977		    uint32_t, (_eop)->eo_u32[1],			\
978		    uint32_t, (_eop)->eo_u32[0]);			\
979									\
980		/*							\
981		 * Make sure that previous writes to the oword have	\
982		 * been done. It should be cheaper than barrier just	\
983		 * after the last write below.				\
984		 */							\
985		bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
986		    (_offset), sizeof (efx_oword_t),			\
987		    BUS_SPACE_BARRIER_WRITE);				\
988		bus_space_write_stream_4((_esbp)->esb_tag,		\
989		    (_esbp)->esb_handle,				\
990		    (_offset), (_eop)->eo_u32[0]);			\
991		bus_space_write_stream_4((_esbp)->esb_tag,		\
992		    (_esbp)->esb_handle,				\
993		    (_offset) + 4, (_eop)->eo_u32[1]);			\
994		bus_space_write_stream_4((_esbp)->esb_tag,		\
995		    (_esbp)->esb_handle,				\
996		    (_offset) + 8, (_eop)->eo_u32[2]);			\
997		/*							\
998		 * It should be guaranteed that the last dword comes	\
999		 * the last, so barrier entire oword to be sure that	\
1000		 * neither above nor below writes are reordered.	\
1001		 */							\
1002		bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
1003		    (_offset), sizeof (efx_oword_t),			\
1004		    BUS_SPACE_BARRIER_WRITE);				\
1005		bus_space_write_stream_4((_esbp)->esb_tag,		\
1006		    (_esbp)->esb_handle,				\
1007		    (_offset) + 12, (_eop)->eo_u32[3]);			\
1008									\
1009		_NOTE(CONSTANTCONDITION)				\
1010		if (_lock)						\
1011			SFXGE_BAR_UNLOCK(_esbp);			\
1012	_NOTE(CONSTANTCONDITION)					\
1013	} while (B_FALSE)
1014#endif
1015
1016/* Use the standard octo-word write for doorbell writes */
1017#define	EFSYS_BAR_DOORBELL_WRITEO(_esbp, _offset, _eop)			\
1018	do {								\
1019		EFSYS_BAR_WRITEO((_esbp), (_offset), (_eop), B_FALSE);	\
1020	_NOTE(CONSTANTCONDITION)					\
1021	} while (B_FALSE)
1022
1023/* SPIN */
1024
1025#define	EFSYS_SPIN(_us)							\
1026	do {								\
1027		DELAY(_us);						\
1028	_NOTE(CONSTANTCONDITION)					\
1029	} while (B_FALSE)
1030
1031#define	EFSYS_SLEEP	EFSYS_SPIN
1032
1033/* BARRIERS */
1034
1035#define	EFSYS_MEM_READ_BARRIER()	rmb()
1036#define	EFSYS_PIO_WRITE_BARRIER()
1037
1038/* DMA SYNC */
1039#define	EFSYS_DMA_SYNC_FOR_KERNEL(_esmp, _offset, _size)		\
1040	do {								\
1041		bus_dmamap_sync((_esmp)->esm_tag,			\
1042		    (_esmp)->esm_map,					\
1043		    BUS_DMASYNC_POSTREAD);				\
1044	_NOTE(CONSTANTCONDITION)					\
1045	} while (B_FALSE)
1046
1047#define	EFSYS_DMA_SYNC_FOR_DEVICE(_esmp, _offset, _size)		\
1048	do {								\
1049		bus_dmamap_sync((_esmp)->esm_tag,			\
1050		    (_esmp)->esm_map,					\
1051		    BUS_DMASYNC_PREWRITE);				\
1052	_NOTE(CONSTANTCONDITION)					\
1053	} while (B_FALSE)
1054
1055/* TIMESTAMP */
1056
1057typedef	clock_t	efsys_timestamp_t;
1058
1059#define	EFSYS_TIMESTAMP(_usp)						\
1060	do {								\
1061		clock_t now;						\
1062									\
1063		now = ticks;						\
1064		*(_usp) = now * hz / 1000000;				\
1065	_NOTE(CONSTANTCONDITION)					\
1066	} while (B_FALSE)
1067
1068/* KMEM */
1069
1070#define	EFSYS_KMEM_ALLOC(_esip, _size, _p)				\
1071	do {								\
1072		(_esip) = (_esip);					\
1073		/*							\
1074		 * The macro is used in non-sleepable contexts, for	\
1075		 * example, holding a mutex.				\
1076		 */							\
1077		(_p) = malloc((_size), M_SFXGE, M_NOWAIT|M_ZERO);	\
1078	_NOTE(CONSTANTCONDITION)					\
1079	} while (B_FALSE)
1080
1081#define	EFSYS_KMEM_FREE(_esip, _size, _p)				\
1082	do {								\
1083		(void) (_esip);						\
1084		(void) (_size);						\
1085		free((_p), M_SFXGE);					\
1086	_NOTE(CONSTANTCONDITION)					\
1087	} while (B_FALSE)
1088
1089/* LOCK */
1090
1091typedef struct efsys_lock_s {
1092	struct mtx	lock;
1093	char		lock_name[SFXGE_LOCK_NAME_MAX];
1094} efsys_lock_t;
1095
1096#define	SFXGE_EFSYS_LOCK_INIT(_eslp, _ifname, _label)			\
1097	do {								\
1098		efsys_lock_t *__eslp = (_eslp);				\
1099									\
1100		snprintf((__eslp)->lock_name,				\
1101			 sizeof((__eslp)->lock_name),			\
1102			 "%s:%s", (_ifname), (_label));			\
1103		mtx_init(&(__eslp)->lock, (__eslp)->lock_name,		\
1104			 NULL, MTX_DEF);				\
1105	} while (B_FALSE)
1106#define	SFXGE_EFSYS_LOCK_DESTROY(_eslp)					\
1107	mtx_destroy(&(_eslp)->lock)
1108#define	SFXGE_EFSYS_LOCK(_eslp)						\
1109	mtx_lock(&(_eslp)->lock)
1110#define	SFXGE_EFSYS_UNLOCK(_eslp)					\
1111	mtx_unlock(&(_eslp)->lock)
1112#define	SFXGE_EFSYS_LOCK_ASSERT_OWNED(_eslp)				\
1113	mtx_assert(&(_eslp)->lock, MA_OWNED)
1114
1115#define	EFSYS_LOCK_MAGIC	0x000010c4
1116
1117#define	EFSYS_LOCK(_lockp, _state)					\
1118	do {								\
1119		SFXGE_EFSYS_LOCK(_lockp);				\
1120		(_state) = EFSYS_LOCK_MAGIC;				\
1121	_NOTE(CONSTANTCONDITION)					\
1122	} while (B_FALSE)
1123
1124#define	EFSYS_UNLOCK(_lockp, _state)					\
1125	do {								\
1126		if ((_state) != EFSYS_LOCK_MAGIC)			\
1127			KASSERT(B_FALSE, ("not locked"));		\
1128		SFXGE_EFSYS_UNLOCK(_lockp);				\
1129	_NOTE(CONSTANTCONDITION)					\
1130	} while (B_FALSE)
1131
1132/* PREEMPT */
1133
1134#define	EFSYS_PREEMPT_DISABLE(_state)					\
1135	do {								\
1136		(_state) = (_state);					\
1137		critical_enter();					\
1138	_NOTE(CONSTANTCONDITION)					\
1139	} while (B_FALSE)
1140
1141#define	EFSYS_PREEMPT_ENABLE(_state)					\
1142	do {								\
1143		(_state) = (_state);					\
1144		critical_exit(_state);					\
1145	_NOTE(CONSTANTCONDITION)					\
1146	} while (B_FALSE)
1147
1148/* STAT */
1149
1150typedef uint64_t		efsys_stat_t;
1151
1152#define	EFSYS_STAT_INCR(_knp, _delta) 					\
1153	do {								\
1154		*(_knp) += (_delta);					\
1155	_NOTE(CONSTANTCONDITION)					\
1156	} while (B_FALSE)
1157
1158#define	EFSYS_STAT_DECR(_knp, _delta) 					\
1159	do {								\
1160		*(_knp) -= (_delta);					\
1161	_NOTE(CONSTANTCONDITION)					\
1162	} while (B_FALSE)
1163
1164#define	EFSYS_STAT_SET(_knp, _val)					\
1165	do {								\
1166		*(_knp) = (_val);					\
1167	_NOTE(CONSTANTCONDITION)					\
1168	} while (B_FALSE)
1169
1170#define	EFSYS_STAT_SET_QWORD(_knp, _valp)				\
1171	do {								\
1172		*(_knp) = le64toh((_valp)->eq_u64[0]);			\
1173	_NOTE(CONSTANTCONDITION)					\
1174	} while (B_FALSE)
1175
1176#define	EFSYS_STAT_SET_DWORD(_knp, _valp)				\
1177	do {								\
1178		*(_knp) = le32toh((_valp)->ed_u32[0]);			\
1179	_NOTE(CONSTANTCONDITION)					\
1180	} while (B_FALSE)
1181
1182#define	EFSYS_STAT_INCR_QWORD(_knp, _valp)				\
1183	do {								\
1184		*(_knp) += le64toh((_valp)->eq_u64[0]);			\
1185	_NOTE(CONSTANTCONDITION)					\
1186	} while (B_FALSE)
1187
1188#define	EFSYS_STAT_SUBR_QWORD(_knp, _valp)				\
1189	do {								\
1190		*(_knp) -= le64toh((_valp)->eq_u64[0]);			\
1191	_NOTE(CONSTANTCONDITION)					\
1192	} while (B_FALSE)
1193
1194/* ERR */
1195
1196extern void	sfxge_err(efsys_identifier_t *, unsigned int,
1197		    uint32_t, uint32_t);
1198
1199#if EFSYS_OPT_DECODE_INTR_FATAL
1200#define	EFSYS_ERR(_esip, _code, _dword0, _dword1)			\
1201	do {								\
1202		sfxge_err((_esip), (_code), (_dword0), (_dword1));	\
1203	_NOTE(CONSTANTCONDITION)					\
1204	} while (B_FALSE)
1205#endif
1206
1207/* ASSERT */
1208
1209#define	EFSYS_ASSERT(_exp) do {						\
1210	if (!(_exp))							\
1211		panic("%s", #_exp);					\
1212	} while (0)
1213
1214#define	EFSYS_ASSERT3(_x, _op, _y, _t) do {				\
1215	const _t __x = (_t)(_x);					\
1216	const _t __y = (_t)(_y);					\
1217	if (!(__x _op __y))						\
1218		panic("assertion failed at %s:%u", __FILE__, __LINE__);	\
1219	} while(0)
1220
1221#define	EFSYS_ASSERT3U(_x, _op, _y)	EFSYS_ASSERT3(_x, _op, _y, uint64_t)
1222#define	EFSYS_ASSERT3S(_x, _op, _y)	EFSYS_ASSERT3(_x, _op, _y, int64_t)
1223#define	EFSYS_ASSERT3P(_x, _op, _y)	EFSYS_ASSERT3(_x, _op, _y, uintptr_t)
1224
1225/* ROTATE */
1226
1227#define	EFSYS_HAS_ROTL_DWORD 0
1228
1229#ifdef	__cplusplus
1230}
1231#endif
1232
1233#endif	/* _SYS_EFSYS_H */
1234