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