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
30#ifndef	_SYS_EFSYS_H
31#define	_SYS_EFSYS_H
32
33//#include <sys/cdefs.h>
34//__FBSDID("$FreeBSD$");
35
36#include "bf_support.h"
37
38#ifdef	__cplusplus
39extern "C" {
40#endif
41
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
58#define	EFSYS_HAS_UINT64 1
59#define	EFSYS_USE_UINT64 0
60#if _BYTE_ORDER == _BIG_ENDIAN
61#define EFSYS_IS_BIG_ENDIAN 1
62#define EFSYS_IS_LITTLE_ENDIAN 0
63#elif _BYTE_ORDER == _LITTLE_ENDIAN
64#define EFSYS_IS_BIG_ENDIAN 0
65#define EFSYS_IS_LITTLE_ENDIAN 1
66#endif
67#include "efx_types.h"
68
69
70/* Common code requires this */
71#if __FreeBSD_version < 800068
72#define memmove(d, s, l) bcopy(s, d, l)
73#endif
74
75/* FreeBSD equivalents of Solaris things */
76#ifndef _NOTE
77#define _NOTE(s)
78#endif
79
80#ifndef B_FALSE
81#define B_FALSE FALSE
82#endif
83#ifndef B_TRUE
84#define B_TRUE TRUE
85#endif
86
87#ifndef IS_P2ALIGNED
88#define	IS_P2ALIGNED(v, a) ((((uintptr_t)(v)) & ((uintptr_t)(a) - 1)) == 0)
89#endif
90
91#ifndef P2ROUNDUP
92#define P2ROUNDUP(x, align)             (-(-(x) & -(align)))
93#endif
94
95#ifndef IS2P
96#define ISP2(x)         (((x) & ((x) - 1)) == 0)
97#endif
98
99#define ENOTACTIVE EINVAL
100
101/* Memory type to use on FreeBSD */
102// MALLOC_DECLARE(M_SFXGE);
103
104/* Machine dependend prefetch wrappers */
105#if defined(__i386) || defined(__amd64)
106static __inline void
107prefetch_read_many(void *addr)
108{
109	__asm__(
110	    "prefetcht0 (%0)"
111	    :
112	    : "r" (addr));
113}
114
115static __inline void
116prefetch_read_once(void *addr)
117{
118	__asm__(
119	    "prefetchnta (%0)"
120	    :
121	    : "r" (addr));
122}
123#endif
124
125#if 0
126#if defined(__i386__) || defined(__amd64__)
127#include <vm/vm.h>
128#include <vm/pmap.h>
129#endif
130static __inline void
131sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map,
132    struct mbuf *m, bus_dma_segment_t *seg)
133{
134#if defined(__i386__) || defined(__amd64__)
135	seg->ds_addr = pmap_kextract(mtod(m, vm_offset_t));
136	seg->ds_len = m->m_len;
137#else
138	int nsegstmp;
139
140	bus_dmamap_load_mbuf_sg(tag, map, m, seg, &nsegstmp, 0);
141#endif
142}
143#endif // 0
144
145/* Modifiers used for DOS builds */
146#define	__cs
147#define	__far
148
149/* Modifiers used for Windows builds */
150#define	__in
151#define	__in_opt
152#define	__in_ecount(_n)
153#define	__in_ecount_opt(_n)
154#define	__in_bcount(_n)
155#define	__in_bcount_opt(_n)
156
157#define	__out
158#define	__out_opt
159#define	__out_ecount(_n)
160#define	__out_ecount_opt(_n)
161#define	__out_bcount(_n)
162#define	__out_bcount_opt(_n)
163
164#define	__deref_out
165
166#define	__inout
167#define	__inout_opt
168#define	__inout_ecount(_n)
169#define	__inout_ecount_opt(_n)
170#define	__inout_bcount(_n)
171#define	__inout_bcount_opt(_n)
172#define	__inout_bcount_full_opt(_n)
173
174#define	__deref_out_bcount_opt(n)
175
176#define	__checkReturn
177
178#define	__drv_when(_p, _c)
179
180/* Code inclusion options */
181
182
183#define	EFSYS_OPT_NAMES 1
184
185#define	EFSYS_OPT_FALCON 0
186#define	EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE 0
187#define	EFSYS_OPT_SIENA 1
188#ifdef DEBUG
189#define	EFSYS_OPT_CHECK_REG 1
190#else
191#define	EFSYS_OPT_CHECK_REG 0
192#endif
193
194#define	EFSYS_OPT_MCDI 1
195
196#define	EFSYS_OPT_MAC_FALCON_GMAC 0
197#define	EFSYS_OPT_MAC_FALCON_XMAC 0
198#define	EFSYS_OPT_MAC_STATS 1
199
200#define	EFSYS_OPT_LOOPBACK 0
201
202#define	EFSYS_OPT_MON_NULL 0
203#define	EFSYS_OPT_MON_LM87 0
204#define	EFSYS_OPT_MON_MAX6647 0
205#define	EFSYS_OPT_MON_SIENA 0
206#define	EFSYS_OPT_MON_STATS 0
207
208#define	EFSYS_OPT_PHY_NULL 0
209#define	EFSYS_OPT_PHY_QT2022C2 0
210#define	EFSYS_OPT_PHY_SFX7101 0
211#define	EFSYS_OPT_PHY_TXC43128 0
212#define	EFSYS_OPT_PHY_PM8358 0
213#define	EFSYS_OPT_PHY_SFT9001 0
214#define	EFSYS_OPT_PHY_QT2025C 0
215#define	EFSYS_OPT_PHY_STATS 1
216#define	EFSYS_OPT_PHY_PROPS 0
217#define	EFSYS_OPT_PHY_BIST 1
218#define	EFSYS_OPT_PHY_LED_CONTROL 1
219#define EFSYS_OPT_PHY_FLAGS 0
220
221#define	EFSYS_OPT_VPD 1
222#define	EFSYS_OPT_NVRAM 1
223#define	EFSYS_OPT_NVRAM_FALCON_BOOTROM 0
224#define	EFSYS_OPT_NVRAM_SFT9001	0
225#define	EFSYS_OPT_NVRAM_SFX7101	0
226#define	EFSYS_OPT_BOOTCFG 0
227
228#define	EFSYS_OPT_PCIE_TUNE 0
229#define	EFSYS_OPT_DIAG 0
230#define	EFSYS_OPT_WOL 1
231#define	EFSYS_OPT_RX_SCALE 1
232#define	EFSYS_OPT_QSTATS 1
233#define EFSYS_OPT_FILTER 0
234#define EFSYS_OPT_RX_SCATTER 0
235#define	EFSYS_OPT_RX_HDR_SPLIT 0
236
237#define	EFSYS_OPT_EV_PREFETCH 0
238
239#define	EFSYS_OPT_DECODE_INTR_FATAL 1
240
241/* ID */
242
243typedef struct __efsys_identifier_s	efsys_identifier_t;
244
245/* PROBE */
246
247#ifndef KDTRACE_HOOKS
248
249#define EFSYS_PROBE(_name)
250
251#define	EFSYS_PROBE1(_name, _type1, _arg1)
252
253#define	EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)
254
255#define	EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2,		\
256	    _type3, _arg3)
257
258#define	EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2,		\
259	    _type3, _arg3, _type4, _arg4)
260
261#define	EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
262	    _type3, _arg3, _type4, _arg4, _type5, _arg5)
263
264#define	EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
265	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
266	    _type6, _arg6)
267
268#define	EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,		\
269	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
270	    _type6, _arg6, _type7, _arg7)
271
272#else /* KDTRACE_HOOKS */
273
274#define	EFSYS_PROBE(_name)						\
275	DTRACE_PROBE(_name)
276
277#define	EFSYS_PROBE1(_name, _type1, _arg1)				\
278	DTRACE_PROBE1(_name, _type1, _arg1)
279
280#define	EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)		\
281	DTRACE_PROBE2(_name, _type1, _arg1, _type2, _arg2)
282
283#define	EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2,		\
284	    _type3, _arg3)						\
285	DTRACE_PROBE3(_name, _type1, _arg1, _type2, _arg2,		\
286	    _type3, _arg3)
287
288#define	EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2,		\
289	    _type3, _arg3, _type4, _arg4)				\
290	DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2,		\
291	    _type3, _arg3, _type4, _arg4)
292
293#ifdef DTRACE_PROBE5
294#define	EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
295	    _type3, _arg3, _type4, _arg4, _type5, _arg5)		\
296	DTRACE_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
297	    _type3, _arg3, _type4, _arg4, _type5, _arg5)
298#else
299#define	EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
300	    _type3, _arg3, _type4, _arg4, _type5, _arg5)		\
301	DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2,		\
302	    _type3, _arg3, _type4, _arg4)
303#endif
304
305#ifdef DTRACE_PROBE6
306#define	EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
307	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
308	    _type6, _arg6)						\
309	DTRACE_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
310	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
311	    _type6, _arg6)
312#else
313#define	EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
314	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
315	    _type6, _arg6)						\
316	EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
317	    _type3, _arg3, _type4, _arg4, _type5, _arg5)
318#endif
319
320#ifdef DTRACE_PROBE7
321#define	EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,		\
322	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
323	    _type6, _arg6, _type7, _arg7)				\
324	DTRACE_PROBE7(_name, _type1, _arg1, _type2, _arg2,		\
325	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
326	    _type6, _arg6, _type7, _arg7)
327#else
328#define	EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,		\
329	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
330	    _type6, _arg6, _type7, _arg7)				\
331	EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
332	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
333	    _type6, _arg6)
334#endif
335
336#endif /* KDTRACE_HOOKS */
337
338/* DMA */
339
340typedef uint64_t		efsys_dma_addr_t;
341
342typedef struct efsys_mem_s {
343//    bus_dma_tag_t        esm_tag;
344//    bus_dmamap_t        esm_map;
345	caddr_t			esm_base;
346	efsys_dma_addr_t	esm_addr;
347	size_t			esm_size;
348} efsys_mem_t;
349
350
351#define	EFSYS_MEM_ZERO(_esmp, _size)					\
352	do {								\
353		(void) memset((_esmp)->esm_base, 0, (_size));		\
354									\
355	_NOTE(CONSTANTCONDITION)					\
356	} while (B_FALSE)
357
358#define	EFSYS_MEM_READD(_esmp, _offset, _edp)				\
359	do {								\
360		uint32_t *addr;						\
361									\
362		_NOTE(CONSTANTCONDITION)				\
363		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),	\
364		    ("not power of 2 aligned"));			\
365									\
366		addr = (void *)((_esmp)->esm_base + (_offset));		\
367									\
368		(_edp)->ed_u32[0] = *addr;				\
369									\
370		EFSYS_PROBE2(mem_readd, unsigned int, (_offset),	\
371		    uint32_t, (_edp)->ed_u32[0]);			\
372									\
373	_NOTE(CONSTANTCONDITION)					\
374	} while (B_FALSE)
375
376#define	EFSYS_MEM_READQ(_esmp, _offset, _eqp)				\
377	do {								\
378		uint32_t *addr;						\
379									\
380		_NOTE(CONSTANTCONDITION)				\
381		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
382		    ("not power of 2 aligned"));			\
383									\
384		addr = (void *)((_esmp)->esm_base + (_offset));		\
385									\
386		(_eqp)->eq_u32[0] = *addr++;				\
387		(_eqp)->eq_u32[1] = *addr;				\
388									\
389		EFSYS_PROBE3(mem_readq, unsigned int, (_offset),	\
390		    uint32_t, (_eqp)->eq_u32[1],			\
391		    uint32_t, (_eqp)->eq_u32[0]);			\
392									\
393	_NOTE(CONSTANTCONDITION)					\
394	} while (B_FALSE)
395
396#define	EFSYS_MEM_READO(_esmp, _offset, _eop)				\
397	do {								\
398		uint32_t *addr;						\
399									\
400		_NOTE(CONSTANTCONDITION)				\
401		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
402		    ("not power of 2 aligned"));			\
403									\
404		addr = (void *)((_esmp)->esm_base + (_offset));		\
405									\
406		(_eop)->eo_u32[0] = *addr++;				\
407		(_eop)->eo_u32[1] = *addr++;				\
408		(_eop)->eo_u32[2] = *addr++;				\
409		(_eop)->eo_u32[3] = *addr;				\
410									\
411		EFSYS_PROBE5(mem_reado, unsigned int, (_offset),	\
412		    uint32_t, (_eop)->eo_u32[3],			\
413		    uint32_t, (_eop)->eo_u32[2],			\
414		    uint32_t, (_eop)->eo_u32[1],			\
415		    uint32_t, (_eop)->eo_u32[0]);			\
416									\
417	_NOTE(CONSTANTCONDITION)					\
418	} while (B_FALSE)
419
420#define	EFSYS_MEM_WRITED(_esmp, _offset, _edp)				\
421	do {								\
422		uint32_t *addr;						\
423									\
424		_NOTE(CONSTANTCONDITION)				\
425		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),	\
426		    ("not power of 2 aligned"));			\
427									\
428		EFSYS_PROBE2(mem_writed, unsigned int, (_offset),	\
429		    uint32_t, (_edp)->ed_u32[0]);			\
430									\
431		addr = (void *)((_esmp)->esm_base + (_offset));		\
432									\
433		*addr = (_edp)->ed_u32[0];				\
434									\
435	_NOTE(CONSTANTCONDITION)					\
436	} while (B_FALSE)
437
438#define	EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp)				\
439	do {								\
440		uint32_t *addr;						\
441									\
442		_NOTE(CONSTANTCONDITION)				\
443		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
444		    ("not power of 2 aligned"));			\
445									\
446		EFSYS_PROBE3(mem_writeq, unsigned int, (_offset),	\
447		    uint32_t, (_eqp)->eq_u32[1],			\
448		    uint32_t, (_eqp)->eq_u32[0]);			\
449									\
450		addr = (void *)((_esmp)->esm_base + (_offset));		\
451									\
452		*addr++ = (_eqp)->eq_u32[0];				\
453		*addr   = (_eqp)->eq_u32[1];				\
454									\
455	_NOTE(CONSTANTCONDITION)					\
456	} while (B_FALSE)
457
458#define	EFSYS_MEM_WRITEO(_esmp, _offset, _eop)				\
459	do {								\
460		uint32_t *addr;						\
461									\
462		_NOTE(CONSTANTCONDITION)				\
463		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
464		    ("not power of 2 aligned"));			\
465									\
466		EFSYS_PROBE5(mem_writeo, unsigned int, (_offset),	\
467		    uint32_t, (_eop)->eo_u32[3],			\
468		    uint32_t, (_eop)->eo_u32[2],			\
469		    uint32_t, (_eop)->eo_u32[1],			\
470		    uint32_t, (_eop)->eo_u32[0]);			\
471									\
472		addr = (void *)((_esmp)->esm_base + (_offset));		\
473									\
474		*addr++ = (_eop)->eo_u32[0];				\
475		*addr++ = (_eop)->eo_u32[1];				\
476		*addr++ = (_eop)->eo_u32[2];				\
477		*addr   = (_eop)->eo_u32[3];				\
478									\
479	_NOTE(CONSTANTCONDITION)					\
480	} while (B_FALSE)
481
482#define	EFSYS_MEM_ADDR(_esmp)						\
483	((_esmp)->esm_addr)
484
485
486/* BAR */
487typedef struct efsys_bar_s {
488	struct mtx		esb_lock;
489	bus_space_tag_t		esb_tag;
490	bus_space_handle_t	esb_handle;
491	int			esb_rid;
492//    struct resource        *esb_res;
493} efsys_bar_t;
494
495#define	EFSYS_BAR_READD(_esbp, _offset, _edp, _lock)			\
496	do {								\
497		_NOTE(CONSTANTCONDITION)				\
498		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),	\
499		    ("not power of 2 aligned"));			\
500									\
501		_NOTE(CONSTANTCONDITION)				\
502		if (_lock)						\
503			mtx_lock(&((_esbp)->esb_lock));			\
504									\
505		(_edp)->ed_u32[0] = bus_space_read_4((_esbp)->esb_tag,	\
506		    (_esbp)->esb_handle, (_offset));			\
507									\
508		EFSYS_PROBE2(bar_readd, unsigned int, (_offset),	\
509		    uint32_t, (_edp)->ed_u32[0]);			\
510									\
511		_NOTE(CONSTANTCONDITION)				\
512		if (_lock)						\
513			mtx_unlock(&((_esbp)->esb_lock));		\
514	_NOTE(CONSTANTCONDITION)					\
515	} while (B_FALSE)
516
517#define	EFSYS_BAR_READQ(_esbp, _offset, _eqp)				\
518	do {								\
519		_NOTE(CONSTANTCONDITION)				\
520		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
521		    ("not power of 2 aligned"));			\
522									\
523		mtx_lock(&((_esbp)->esb_lock));				\
524									\
525		(_eqp)->eq_u32[0] = bus_space_read_4((_esbp)->esb_tag,	\
526		    (_esbp)->esb_handle, (_offset));			\
527		(_eqp)->eq_u32[1] = bus_space_read_4((_esbp)->esb_tag,	\
528		    (_esbp)->esb_handle, (_offset+4));			\
529									\
530		EFSYS_PROBE3(bar_readq, unsigned int, (_offset),	\
531		    uint32_t, (_eqp)->eq_u32[1],			\
532		    uint32_t, (_eqp)->eq_u32[0]);			\
533									\
534		mtx_unlock(&((_esbp)->esb_lock));			\
535	_NOTE(CONSTANTCONDITION)					\
536	} while (B_FALSE)
537
538#define	EFSYS_BAR_READO(_esbp, _offset, _eop, _lock)			\
539	do {								\
540		_NOTE(CONSTANTCONDITION)				\
541		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
542		    ("not power of 2 aligned"));			\
543									\
544		_NOTE(CONSTANTCONDITION)				\
545		if (_lock)						\
546			mtx_lock(&((_esbp)->esb_lock));			\
547									\
548		(_eop)->eo_u32[0] = bus_space_read_4((_esbp)->esb_tag,	\
549		    (_esbp)->esb_handle, (_offset));			\
550		(_eop)->eo_u32[1] = bus_space_read_4((_esbp)->esb_tag,	\
551		    (_esbp)->esb_handle, (_offset+4));			\
552		(_eop)->eo_u32[2] = bus_space_read_4((_esbp)->esb_tag,	\
553		    (_esbp)->esb_handle, (_offset+8));			\
554		(_eop)->eo_u32[3] = bus_space_read_4((_esbp)->esb_tag,	\
555		    (_esbp)->esb_handle, (_offset+12));			\
556									\
557		EFSYS_PROBE5(bar_reado, unsigned int, (_offset),	\
558		    uint32_t, (_eop)->eo_u32[3],			\
559		    uint32_t, (_eop)->eo_u32[2],			\
560		    uint32_t, (_eop)->eo_u32[1],			\
561		    uint32_t, (_eop)->eo_u32[0]);			\
562									\
563		_NOTE(CONSTANTCONDITION)				\
564		if (_lock)						\
565			mtx_unlock(&((_esbp)->esb_lock));		\
566	_NOTE(CONSTANTCONDITION)					\
567	} while (B_FALSE)
568
569#define	EFSYS_BAR_WRITED(_esbp, _offset, _edp, _lock)			\
570	do {								\
571		_NOTE(CONSTANTCONDITION)				\
572		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)),	\
573		    ("not power of 2 aligned"));			\
574									\
575		_NOTE(CONSTANTCONDITION)				\
576		if (_lock)						\
577			mtx_lock(&((_esbp)->esb_lock));			\
578									\
579		EFSYS_PROBE2(bar_writed, unsigned int, (_offset),	\
580		    uint32_t, (_edp)->ed_u32[0]);			\
581									\
582		bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
583		    (_offset), (_edp)->ed_u32[0]);			\
584									\
585		_NOTE(CONSTANTCONDITION)				\
586		if (_lock)						\
587			mtx_unlock(&((_esbp)->esb_lock));		\
588	_NOTE(CONSTANTCONDITION)					\
589	} while (B_FALSE)
590
591#define	EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp)				\
592	do {								\
593		_NOTE(CONSTANTCONDITION)				\
594		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)),	\
595		    ("not power of 2 aligned"));			\
596									\
597		mtx_lock(&((_esbp)->esb_lock));				\
598									\
599		EFSYS_PROBE3(bar_writeq, unsigned int, (_offset),	\
600		    uint32_t, (_eqp)->eq_u32[1],			\
601		    uint32_t, (_eqp)->eq_u32[0]);			\
602									\
603		bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
604		    (_offset), (_eqp)->eq_u32[0]);			\
605		bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
606		    (_offset+4), (_eqp)->eq_u32[1]);			\
607									\
608		mtx_unlock(&((_esbp)->esb_lock));			\
609	_NOTE(CONSTANTCONDITION)					\
610	} while (B_FALSE)
611
612#define	EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock)			\
613	do {								\
614		_NOTE(CONSTANTCONDITION)				\
615		KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)),	\
616		    ("not power of 2 aligned"));			\
617									\
618		_NOTE(CONSTANTCONDITION)				\
619		if (_lock)						\
620			mtx_lock(&((_esbp)->esb_lock));			\
621									\
622		EFSYS_PROBE5(bar_writeo, unsigned int, (_offset),	\
623		    uint32_t, (_eop)->eo_u32[3],			\
624		    uint32_t, (_eop)->eo_u32[2],			\
625		    uint32_t, (_eop)->eo_u32[1],			\
626		    uint32_t, (_eop)->eo_u32[0]);			\
627									\
628		bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
629		    (_offset), (_eop)->eo_u32[0]);			\
630		bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
631		    (_offset+4), (_eop)->eo_u32[1]);			\
632		bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
633		    (_offset+8), (_eop)->eo_u32[2]);			\
634		bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
635		    (_offset+12), (_eop)->eo_u32[3]);			\
636									\
637		_NOTE(CONSTANTCONDITION)				\
638		if (_lock)						\
639			mtx_unlock(&((_esbp)->esb_lock));		\
640	_NOTE(CONSTANTCONDITION)					\
641	} while (B_FALSE)
642
643/* SPIN */
644
645#define	EFSYS_SPIN(_us)							\
646	do {								\
647		DELAY(_us);						\
648	_NOTE(CONSTANTCONDITION)					\
649	} while (B_FALSE)
650
651#define	EFSYS_SLEEP	EFSYS_SPIN
652
653/* BARRIERS */
654
655/* Strict ordering guaranteed by devacc.devacc_attr_dataorder */
656#define	EFSYS_MEM_READ_BARRIER()
657#define	EFSYS_PIO_WRITE_BARRIER()
658
659/* TIMESTAMP */
660
661typedef	clock_t	efsys_timestamp_t;
662
663#define	EFSYS_TIMESTAMP(_usp)						\
664	do {								\
665		clock_t now;						\
666									\
667		now = ticks;						\
668		*(_usp) = now * hz / 1000000;				\
669	_NOTE(CONSTANTCONDITION)					\
670	} while (B_FALSE)
671
672/* KMEM */
673
674#define	EFSYS_KMEM_ALLOC(_esip, _size, _p)				\
675	do {								\
676        (void) (_esip);                                     \
677        (_p) = malloc((_size));                             \
678        if ((_p) != NULL) {                                 \
679            memset((_p), 0, (_size));                       \
680        }                                                   \
681	_NOTE(CONSTANTCONDITION)					\
682	} while (B_FALSE)
683
684#define	EFSYS_KMEM_FREE(_esip, _size, _p)				\
685	do {								\
686		(void) (_esip);						\
687		(void) (_size);						\
688        free((_p));                                         \
689	_NOTE(CONSTANTCONDITION)					\
690	} while (B_FALSE)
691
692/* LOCK */
693
694typedef struct mtx	efsys_lock_t;
695
696#define	EFSYS_LOCK_MAGIC	0x000010c4
697
698#define	EFSYS_LOCK(_lockp, _state)					\
699	do {								\
700		mtx_lock(_lockp);					\
701		(_state) = EFSYS_LOCK_MAGIC;				\
702	_NOTE(CONSTANTCONDITION)					\
703	} while (B_FALSE)
704
705#define	EFSYS_UNLOCK(_lockp, _state)					\
706	do {								\
707		if ((_state) != EFSYS_LOCK_MAGIC)			\
708			KASSERT(B_FALSE, ("not locked"));		\
709		mtx_unlock(_lockp);					\
710	_NOTE(CONSTANTCONDITION)					\
711	} while (B_FALSE)
712
713/* PREEMPT */
714
715#define	EFSYS_PREEMPT_DISABLE(_state)					\
716	do {								\
717		(_state) = (_state);					\
718		critical_enter();					\
719	_NOTE(CONSTANTCONDITION)					\
720	} while (B_FALSE)
721
722#define	EFSYS_PREEMPT_ENABLE(_state)					\
723	do {								\
724		(_state) = (_state);					\
725		critical_exit(_state);					\
726	_NOTE(CONSTANTCONDITION)					\
727	} while (B_FALSE)
728
729/* STAT */
730
731typedef uint64_t		efsys_stat_t;
732
733#define	EFSYS_STAT_INCR(_knp, _delta) 					\
734	do {								\
735		*(_knp) += (_delta);					\
736	_NOTE(CONSTANTCONDITION)					\
737	} while (B_FALSE)
738
739#define	EFSYS_STAT_DECR(_knp, _delta) 					\
740	do {								\
741		*(_knp) -= (_delta);					\
742	_NOTE(CONSTANTCONDITION)					\
743	} while (B_FALSE)
744
745#define	EFSYS_STAT_SET(_knp, _val)					\
746	do {								\
747		*(_knp) = (_val);					\
748	_NOTE(CONSTANTCONDITION)					\
749	} while (B_FALSE)
750
751#define	EFSYS_STAT_SET_QWORD(_knp, _valp)				\
752	do {								\
753		*(_knp) = le64toh((_valp)->eq_u64[0]);			\
754	_NOTE(CONSTANTCONDITION)					\
755	} while (B_FALSE)
756
757#define	EFSYS_STAT_SET_DWORD(_knp, _valp)				\
758	do {								\
759		*(_knp) = le32toh((_valp)->ed_u32[0]);			\
760	_NOTE(CONSTANTCONDITION)					\
761	} while (B_FALSE)
762
763#define	EFSYS_STAT_INCR_QWORD(_knp, _valp)				\
764	do {								\
765		*(_knp) += le64toh((_valp)->eq_u64[0]);			\
766	_NOTE(CONSTANTCONDITION)					\
767	} while (B_FALSE)
768
769#define	EFSYS_STAT_SUBR_QWORD(_knp, _valp)				\
770	do {								\
771		*(_knp) -= le64toh((_valp)->eq_u64[0]);			\
772	_NOTE(CONSTANTCONDITION)					\
773	} while (B_FALSE)
774
775/* ERR */
776
777extern void	sfxge_err(efsys_identifier_t *, unsigned int,
778		    uint32_t, uint32_t);
779
780#if EFSYS_OPT_DECODE_INTR_FATAL
781#define	EFSYS_ERR(_esip, _code, _dword0, _dword1)			\
782	do {								\
783		sfxge_err((_esip), (_code), (_dword0), (_dword1));	\
784	_NOTE(CONSTANTCONDITION)					\
785	} while (B_FALSE)
786#endif
787
788/* ASSERT */
789
790#define	EFSYS_ASSERT(_exp) do {						\
791	if (!(_exp))							\
792		panic(#_exp);						\
793	} while (0)
794
795#define EFSYS_ASSERT3(_x, _op, _y, _t) do {				\
796	const _t __x = (_t)(_x);					\
797	const _t __y = (_t)(_y);					\
798	if (!(__x _op __y))						\
799	        panic("assertion failed at %s:%u", __FILE__, __LINE__);	\
800	} while(0)
801
802#define EFSYS_ASSERT3U(_x, _op, _y)	EFSYS_ASSERT3(_x, _op, _y, uint64_t)
803#define EFSYS_ASSERT3S(_x, _op, _y)	EFSYS_ASSERT3(_x, _op, _y, int64_t)
804#define EFSYS_ASSERT3P(_x, _op, _y)	EFSYS_ASSERT3(_x, _op, _y, uintptr_t)
805
806#ifdef	__cplusplus
807}
808#endif
809
810#endif	/* _SYS_EFSYS_H */
811