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