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