2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2010-2016 Solarflare Communications Inc.
7 * This software was developed in part by Philip Paeps under contract for
8 * Solarflare Communications, Inc.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
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.
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.
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.
45 #include <sys/param.h>
47 #include <sys/endian.h>
49 #include <sys/malloc.h>
51 #include <sys/mutex.h>
52 #include <sys/rwlock.h>
54 #include <sys/systm.h>
56 #include <machine/bus.h>
57 #include <machine/endian.h>
59 #define EFSYS_HAS_UINT64 1
60 #if defined(__x86_64__)
61 #define EFSYS_USE_UINT64 1
63 #define EFSYS_USE_UINT64 0
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
73 #include "efx_types.h"
75 /* Common code requires this */
76 #if __FreeBSD_version < 800068
77 #define memmove(d, s, l) bcopy(s, d, l)
88 #define IS_P2ALIGNED(v, a) ((((uintptr_t)(v)) & ((uintptr_t)(a) - 1)) == 0)
92 #define P2ROUNDUP(x, align) (-(-(x) & -(align)))
96 #define P2ALIGN(_x, _a) ((_x) & -(_a))
100 #define ISP2(x) (((x) & ((x) - 1)) == 0)
103 #if defined(__x86_64__) && __FreeBSD_version >= 1000000
105 #define SFXGE_USE_BUS_SPACE_8 1
107 #if !defined(bus_space_read_stream_8)
109 #define bus_space_read_stream_8(t, h, o) \
110 bus_space_read_8((t), (h), (o))
112 #define bus_space_write_stream_8(t, h, o, v) \
113 bus_space_write_8((t), (h), (o), (v))
119 #define ENOTACTIVE EINVAL
121 /* Memory type to use on FreeBSD */
122 MALLOC_DECLARE(M_SFXGE);
124 /* Machine dependend prefetch wrappers */
125 #if defined(__i386__) || defined(__amd64__)
127 prefetch_read_many(void *addr)
137 prefetch_read_once(void *addr)
145 #elif defined(__sparc64__)
147 prefetch_read_many(void *addr)
157 prefetch_read_once(void *addr)
167 prefetch_read_many(void *addr)
173 prefetch_read_once(void *addr)
179 #if defined(__i386__) || defined(__amd64__)
184 sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map,
185 struct mbuf *m, bus_dma_segment_t *seg)
187 #if defined(__i386__) || defined(__amd64__)
188 seg->ds_addr = pmap_kextract(mtod(m, vm_offset_t));
189 seg->ds_len = m->m_len;
193 bus_dmamap_load_mbuf_sg(tag, map, m, seg, &nsegstmp, 0);
197 /* Code inclusion options */
200 #define EFSYS_OPT_NAMES 1
202 #define EFSYS_OPT_SIENA 1
203 #define EFSYS_OPT_HUNTINGTON 1
204 #define EFSYS_OPT_MEDFORD 1
205 #define EFSYS_OPT_MEDFORD2 0
207 #define EFSYS_OPT_CHECK_REG 1
209 #define EFSYS_OPT_CHECK_REG 0
212 #define EFSYS_OPT_MCDI 1
213 #define EFSYS_OPT_MCDI_LOGGING 0
214 #define EFSYS_OPT_MCDI_PROXY_AUTH 0
216 #define EFSYS_OPT_MAC_STATS 1
218 #define EFSYS_OPT_LOOPBACK 0
220 #define EFSYS_OPT_MON_MCDI 0
221 #define EFSYS_OPT_MON_STATS 0
223 #define EFSYS_OPT_PHY_STATS 1
224 #define EFSYS_OPT_BIST 1
225 #define EFSYS_OPT_PHY_LED_CONTROL 1
226 #define EFSYS_OPT_PHY_FLAGS 0
228 #define EFSYS_OPT_VPD 1
229 #define EFSYS_OPT_NVRAM 1
230 #define EFSYS_OPT_BOOTCFG 0
231 #define EFSYS_OPT_IMAGE_LAYOUT 0
233 #define EFSYS_OPT_DIAG 0
234 #define EFSYS_OPT_RX_SCALE 1
235 #define EFSYS_OPT_QSTATS 1
236 #define EFSYS_OPT_FILTER 1
237 #define EFSYS_OPT_RX_SCATTER 0
239 #define EFSYS_OPT_EV_PREFETCH 0
241 #define EFSYS_OPT_DECODE_INTR_FATAL 1
243 #define EFSYS_OPT_LICENSING 0
245 #define EFSYS_OPT_ALLOW_UNCONFIGURED_NIC 0
247 #define EFSYS_OPT_RX_PACKED_STREAM 0
249 #define EFSYS_OPT_RX_ES_SUPER_BUFFER 0
251 #define EFSYS_OPT_TUNNEL 0
253 #define EFSYS_OPT_FW_SUBVARIANT_AWARE 0
257 typedef struct __efsys_identifier_s efsys_identifier_t;
263 #define EFSYS_PROBE(_name)
265 #define EFSYS_PROBE1(_name, _type1, _arg1)
267 #define EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)
269 #define EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2, \
272 #define EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
273 _type3, _arg3, _type4, _arg4)
275 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
276 _type3, _arg3, _type4, _arg4, _type5, _arg5)
278 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
279 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
282 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
283 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
284 _type6, _arg6, _type7, _arg7)
286 #else /* DTRACE_PROBE */
288 #define EFSYS_PROBE(_name) \
291 #define EFSYS_PROBE1(_name, _type1, _arg1) \
292 DTRACE_PROBE1(_name, _type1, _arg1)
294 #define EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2) \
295 DTRACE_PROBE2(_name, _type1, _arg1, _type2, _arg2)
297 #define EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2, \
299 DTRACE_PROBE3(_name, _type1, _arg1, _type2, _arg2, \
302 #define EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
303 _type3, _arg3, _type4, _arg4) \
304 DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
305 _type3, _arg3, _type4, _arg4)
308 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
309 _type3, _arg3, _type4, _arg4, _type5, _arg5) \
310 DTRACE_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
311 _type3, _arg3, _type4, _arg4, _type5, _arg5)
313 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
314 _type3, _arg3, _type4, _arg4, _type5, _arg5) \
315 DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
316 _type3, _arg3, _type4, _arg4)
320 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
321 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
323 DTRACE_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
324 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
327 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
328 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
330 EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
331 _type3, _arg3, _type4, _arg4, _type5, _arg5)
335 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
336 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
337 _type6, _arg6, _type7, _arg7) \
338 DTRACE_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
339 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
340 _type6, _arg6, _type7, _arg7)
342 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
343 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
344 _type6, _arg6, _type7, _arg7) \
345 EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
346 _type3, _arg3, _type4, _arg4, _type5, _arg5, \
350 #endif /* DTRACE_PROBE */
354 typedef uint64_t efsys_dma_addr_t;
356 typedef struct efsys_mem_s {
357 bus_dma_tag_t esm_tag;
358 bus_dmamap_t esm_map;
360 efsys_dma_addr_t esm_addr;
364 #define EFSYS_MEM_SIZE(_esmp) \
367 #define EFSYS_MEM_ADDR(_esmp) \
370 #define EFSYS_MEM_IS_NULL(_esmp) \
371 ((_esmp)->esm_base == NULL)
374 #define EFSYS_MEM_ZERO(_esmp, _size) \
376 (void) memset((_esmp)->esm_base, 0, (_size)); \
378 _NOTE(CONSTANTCONDITION) \
381 #define EFSYS_MEM_READD(_esmp, _offset, _edp) \
385 _NOTE(CONSTANTCONDITION) \
386 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)), \
387 ("not power of 2 aligned")); \
389 addr = (void *)((_esmp)->esm_base + (_offset)); \
391 (_edp)->ed_u32[0] = *addr; \
393 EFSYS_PROBE2(mem_readd, unsigned int, (_offset), \
394 uint32_t, (_edp)->ed_u32[0]); \
396 _NOTE(CONSTANTCONDITION) \
399 #if defined(__x86_64__)
400 #define EFSYS_MEM_READQ(_esmp, _offset, _eqp) \
404 _NOTE(CONSTANTCONDITION) \
405 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
406 ("not power of 2 aligned")); \
408 addr = (void *)((_esmp)->esm_base + (_offset)); \
410 (_eqp)->eq_u64[0] = *addr; \
412 EFSYS_PROBE3(mem_readq, unsigned int, (_offset), \
413 uint32_t, (_eqp)->eq_u32[1], \
414 uint32_t, (_eqp)->eq_u32[0]); \
416 _NOTE(CONSTANTCONDITION) \
419 #define EFSYS_MEM_READQ(_esmp, _offset, _eqp) \
423 _NOTE(CONSTANTCONDITION) \
424 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
425 ("not power of 2 aligned")); \
427 addr = (void *)((_esmp)->esm_base + (_offset)); \
429 (_eqp)->eq_u32[0] = *addr++; \
430 (_eqp)->eq_u32[1] = *addr; \
432 EFSYS_PROBE3(mem_readq, unsigned int, (_offset), \
433 uint32_t, (_eqp)->eq_u32[1], \
434 uint32_t, (_eqp)->eq_u32[0]); \
436 _NOTE(CONSTANTCONDITION) \
440 #if defined(__x86_64__)
441 #define EFSYS_MEM_READO(_esmp, _offset, _eop) \
445 _NOTE(CONSTANTCONDITION) \
446 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
447 ("not power of 2 aligned")); \
449 addr = (void *)((_esmp)->esm_base + (_offset)); \
451 (_eop)->eo_u64[0] = *addr++; \
452 (_eop)->eo_u64[1] = *addr; \
454 EFSYS_PROBE5(mem_reado, unsigned int, (_offset), \
455 uint32_t, (_eop)->eo_u32[3], \
456 uint32_t, (_eop)->eo_u32[2], \
457 uint32_t, (_eop)->eo_u32[1], \
458 uint32_t, (_eop)->eo_u32[0]); \
460 _NOTE(CONSTANTCONDITION) \
463 #define EFSYS_MEM_READO(_esmp, _offset, _eop) \
467 _NOTE(CONSTANTCONDITION) \
468 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
469 ("not power of 2 aligned")); \
471 addr = (void *)((_esmp)->esm_base + (_offset)); \
473 (_eop)->eo_u32[0] = *addr++; \
474 (_eop)->eo_u32[1] = *addr++; \
475 (_eop)->eo_u32[2] = *addr++; \
476 (_eop)->eo_u32[3] = *addr; \
478 EFSYS_PROBE5(mem_reado, unsigned int, (_offset), \
479 uint32_t, (_eop)->eo_u32[3], \
480 uint32_t, (_eop)->eo_u32[2], \
481 uint32_t, (_eop)->eo_u32[1], \
482 uint32_t, (_eop)->eo_u32[0]); \
484 _NOTE(CONSTANTCONDITION) \
488 #define EFSYS_MEM_WRITED(_esmp, _offset, _edp) \
492 _NOTE(CONSTANTCONDITION) \
493 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)), \
494 ("not power of 2 aligned")); \
496 EFSYS_PROBE2(mem_writed, unsigned int, (_offset), \
497 uint32_t, (_edp)->ed_u32[0]); \
499 addr = (void *)((_esmp)->esm_base + (_offset)); \
501 *addr = (_edp)->ed_u32[0]; \
503 _NOTE(CONSTANTCONDITION) \
506 #if defined(__x86_64__)
507 #define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp) \
511 _NOTE(CONSTANTCONDITION) \
512 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
513 ("not power of 2 aligned")); \
515 EFSYS_PROBE3(mem_writeq, unsigned int, (_offset), \
516 uint32_t, (_eqp)->eq_u32[1], \
517 uint32_t, (_eqp)->eq_u32[0]); \
519 addr = (void *)((_esmp)->esm_base + (_offset)); \
521 *addr = (_eqp)->eq_u64[0]; \
523 _NOTE(CONSTANTCONDITION) \
527 #define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp) \
531 _NOTE(CONSTANTCONDITION) \
532 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
533 ("not power of 2 aligned")); \
535 EFSYS_PROBE3(mem_writeq, unsigned int, (_offset), \
536 uint32_t, (_eqp)->eq_u32[1], \
537 uint32_t, (_eqp)->eq_u32[0]); \
539 addr = (void *)((_esmp)->esm_base + (_offset)); \
541 *addr++ = (_eqp)->eq_u32[0]; \
542 *addr = (_eqp)->eq_u32[1]; \
544 _NOTE(CONSTANTCONDITION) \
548 #if defined(__x86_64__)
549 #define EFSYS_MEM_WRITEO(_esmp, _offset, _eop) \
553 _NOTE(CONSTANTCONDITION) \
554 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
555 ("not power of 2 aligned")); \
557 EFSYS_PROBE5(mem_writeo, unsigned int, (_offset), \
558 uint32_t, (_eop)->eo_u32[3], \
559 uint32_t, (_eop)->eo_u32[2], \
560 uint32_t, (_eop)->eo_u32[1], \
561 uint32_t, (_eop)->eo_u32[0]); \
563 addr = (void *)((_esmp)->esm_base + (_offset)); \
565 *addr++ = (_eop)->eo_u64[0]; \
566 *addr = (_eop)->eo_u64[1]; \
568 _NOTE(CONSTANTCONDITION) \
571 #define EFSYS_MEM_WRITEO(_esmp, _offset, _eop) \
575 _NOTE(CONSTANTCONDITION) \
576 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
577 ("not power of 2 aligned")); \
579 EFSYS_PROBE5(mem_writeo, unsigned int, (_offset), \
580 uint32_t, (_eop)->eo_u32[3], \
581 uint32_t, (_eop)->eo_u32[2], \
582 uint32_t, (_eop)->eo_u32[1], \
583 uint32_t, (_eop)->eo_u32[0]); \
585 addr = (void *)((_esmp)->esm_base + (_offset)); \
587 *addr++ = (_eop)->eo_u32[0]; \
588 *addr++ = (_eop)->eo_u32[1]; \
589 *addr++ = (_eop)->eo_u32[2]; \
590 *addr = (_eop)->eo_u32[3]; \
592 _NOTE(CONSTANTCONDITION) \
598 #define SFXGE_LOCK_NAME_MAX 16
600 typedef struct efsys_bar_s {
602 char esb_lock_name[SFXGE_LOCK_NAME_MAX];
603 bus_space_tag_t esb_tag;
604 bus_space_handle_t esb_handle;
606 struct resource *esb_res;
609 #define SFXGE_BAR_LOCK_INIT(_esbp, _ifname) \
611 snprintf((_esbp)->esb_lock_name, \
612 sizeof((_esbp)->esb_lock_name), \
613 "%s:bar", (_ifname)); \
614 mtx_init(&(_esbp)->esb_lock, (_esbp)->esb_lock_name, \
616 _NOTE(CONSTANTCONDITION) \
618 #define SFXGE_BAR_LOCK_DESTROY(_esbp) \
619 mtx_destroy(&(_esbp)->esb_lock)
620 #define SFXGE_BAR_LOCK(_esbp) \
621 mtx_lock(&(_esbp)->esb_lock)
622 #define SFXGE_BAR_UNLOCK(_esbp) \
623 mtx_unlock(&(_esbp)->esb_lock)
625 #define EFSYS_BAR_READD(_esbp, _offset, _edp, _lock) \
627 _NOTE(CONSTANTCONDITION) \
628 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)), \
629 ("not power of 2 aligned")); \
631 _NOTE(CONSTANTCONDITION) \
633 SFXGE_BAR_LOCK(_esbp); \
635 (_edp)->ed_u32[0] = bus_space_read_stream_4( \
636 (_esbp)->esb_tag, (_esbp)->esb_handle, \
639 EFSYS_PROBE2(bar_readd, unsigned int, (_offset), \
640 uint32_t, (_edp)->ed_u32[0]); \
642 _NOTE(CONSTANTCONDITION) \
644 SFXGE_BAR_UNLOCK(_esbp); \
645 _NOTE(CONSTANTCONDITION) \
648 #if defined(SFXGE_USE_BUS_SPACE_8)
649 #define EFSYS_BAR_READQ(_esbp, _offset, _eqp) \
651 _NOTE(CONSTANTCONDITION) \
652 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
653 ("not power of 2 aligned")); \
655 SFXGE_BAR_LOCK(_esbp); \
657 (_eqp)->eq_u64[0] = bus_space_read_stream_8( \
658 (_esbp)->esb_tag, (_esbp)->esb_handle, \
661 EFSYS_PROBE3(bar_readq, unsigned int, (_offset), \
662 uint32_t, (_eqp)->eq_u32[1], \
663 uint32_t, (_eqp)->eq_u32[0]); \
665 SFXGE_BAR_UNLOCK(_esbp); \
666 _NOTE(CONSTANTCONDITION) \
669 #define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock) \
671 _NOTE(CONSTANTCONDITION) \
672 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
673 ("not power of 2 aligned")); \
675 _NOTE(CONSTANTCONDITION) \
677 SFXGE_BAR_LOCK(_esbp); \
679 (_eop)->eo_u64[0] = bus_space_read_stream_8( \
680 (_esbp)->esb_tag, (_esbp)->esb_handle, \
682 (_eop)->eo_u64[1] = bus_space_read_stream_8( \
683 (_esbp)->esb_tag, (_esbp)->esb_handle, \
686 EFSYS_PROBE5(bar_reado, unsigned int, (_offset), \
687 uint32_t, (_eop)->eo_u32[3], \
688 uint32_t, (_eop)->eo_u32[2], \
689 uint32_t, (_eop)->eo_u32[1], \
690 uint32_t, (_eop)->eo_u32[0]); \
692 _NOTE(CONSTANTCONDITION) \
694 SFXGE_BAR_UNLOCK(_esbp); \
695 _NOTE(CONSTANTCONDITION) \
699 #define EFSYS_BAR_READQ(_esbp, _offset, _eqp) \
701 _NOTE(CONSTANTCONDITION) \
702 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
703 ("not power of 2 aligned")); \
705 SFXGE_BAR_LOCK(_esbp); \
707 (_eqp)->eq_u32[0] = bus_space_read_stream_4( \
708 (_esbp)->esb_tag, (_esbp)->esb_handle, \
710 (_eqp)->eq_u32[1] = bus_space_read_stream_4( \
711 (_esbp)->esb_tag, (_esbp)->esb_handle, \
714 EFSYS_PROBE3(bar_readq, unsigned int, (_offset), \
715 uint32_t, (_eqp)->eq_u32[1], \
716 uint32_t, (_eqp)->eq_u32[0]); \
718 SFXGE_BAR_UNLOCK(_esbp); \
719 _NOTE(CONSTANTCONDITION) \
722 #define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock) \
724 _NOTE(CONSTANTCONDITION) \
725 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
726 ("not power of 2 aligned")); \
728 _NOTE(CONSTANTCONDITION) \
730 SFXGE_BAR_LOCK(_esbp); \
732 (_eop)->eo_u32[0] = bus_space_read_stream_4( \
733 (_esbp)->esb_tag, (_esbp)->esb_handle, \
735 (_eop)->eo_u32[1] = bus_space_read_stream_4( \
736 (_esbp)->esb_tag, (_esbp)->esb_handle, \
738 (_eop)->eo_u32[2] = bus_space_read_stream_4( \
739 (_esbp)->esb_tag, (_esbp)->esb_handle, \
741 (_eop)->eo_u32[3] = bus_space_read_stream_4( \
742 (_esbp)->esb_tag, (_esbp)->esb_handle, \
745 EFSYS_PROBE5(bar_reado, unsigned int, (_offset), \
746 uint32_t, (_eop)->eo_u32[3], \
747 uint32_t, (_eop)->eo_u32[2], \
748 uint32_t, (_eop)->eo_u32[1], \
749 uint32_t, (_eop)->eo_u32[0]); \
751 _NOTE(CONSTANTCONDITION) \
753 SFXGE_BAR_UNLOCK(_esbp); \
754 _NOTE(CONSTANTCONDITION) \
758 #define EFSYS_BAR_WRITED(_esbp, _offset, _edp, _lock) \
760 _NOTE(CONSTANTCONDITION) \
761 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)), \
762 ("not power of 2 aligned")); \
764 _NOTE(CONSTANTCONDITION) \
766 SFXGE_BAR_LOCK(_esbp); \
768 EFSYS_PROBE2(bar_writed, unsigned int, (_offset), \
769 uint32_t, (_edp)->ed_u32[0]); \
772 * Make sure that previous writes to the dword have \
773 * been done. It should be cheaper than barrier just \
774 * after the write below. \
776 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
777 (_offset), sizeof (efx_dword_t), \
778 BUS_SPACE_BARRIER_WRITE); \
779 bus_space_write_stream_4((_esbp)->esb_tag, \
780 (_esbp)->esb_handle, \
781 (_offset), (_edp)->ed_u32[0]); \
783 _NOTE(CONSTANTCONDITION) \
785 SFXGE_BAR_UNLOCK(_esbp); \
786 _NOTE(CONSTANTCONDITION) \
789 #if defined(SFXGE_USE_BUS_SPACE_8)
790 #define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp) \
792 _NOTE(CONSTANTCONDITION) \
793 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
794 ("not power of 2 aligned")); \
796 SFXGE_BAR_LOCK(_esbp); \
798 EFSYS_PROBE3(bar_writeq, unsigned int, (_offset), \
799 uint32_t, (_eqp)->eq_u32[1], \
800 uint32_t, (_eqp)->eq_u32[0]); \
803 * Make sure that previous writes to the qword have \
804 * been done. It should be cheaper than barrier just \
805 * after the write below. \
807 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
808 (_offset), sizeof (efx_qword_t), \
809 BUS_SPACE_BARRIER_WRITE); \
810 bus_space_write_stream_8((_esbp)->esb_tag, \
811 (_esbp)->esb_handle, \
812 (_offset), (_eqp)->eq_u64[0]); \
814 SFXGE_BAR_UNLOCK(_esbp); \
815 _NOTE(CONSTANTCONDITION) \
818 #define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp) \
820 _NOTE(CONSTANTCONDITION) \
821 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
822 ("not power of 2 aligned")); \
824 SFXGE_BAR_LOCK(_esbp); \
826 EFSYS_PROBE3(bar_writeq, unsigned int, (_offset), \
827 uint32_t, (_eqp)->eq_u32[1], \
828 uint32_t, (_eqp)->eq_u32[0]); \
831 * Make sure that previous writes to the qword have \
832 * been done. It should be cheaper than barrier just \
833 * after the last write below. \
835 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
836 (_offset), sizeof (efx_qword_t), \
837 BUS_SPACE_BARRIER_WRITE); \
838 bus_space_write_stream_4((_esbp)->esb_tag, \
839 (_esbp)->esb_handle, \
840 (_offset), (_eqp)->eq_u32[0]); \
842 * It should be guaranteed that the last dword comes \
843 * the last, so barrier entire qword to be sure that \
844 * neither above nor below writes are reordered. \
846 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
847 (_offset), sizeof (efx_qword_t), \
848 BUS_SPACE_BARRIER_WRITE); \
849 bus_space_write_stream_4((_esbp)->esb_tag, \
850 (_esbp)->esb_handle, \
851 (_offset) + 4, (_eqp)->eq_u32[1]); \
853 SFXGE_BAR_UNLOCK(_esbp); \
854 _NOTE(CONSTANTCONDITION) \
859 * Guarantees 64bit aligned 64bit writes to write combined BAR mapping
860 * (required by PIO hardware)
862 #define EFSYS_BAR_WC_WRITEQ(_esbp, _offset, _eqp) \
864 _NOTE(CONSTANTCONDITION) \
865 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
866 ("not power of 2 aligned")); \
870 /* FIXME: Perform a 64-bit write */ \
871 KASSERT(0, ("not implemented")); \
873 _NOTE(CONSTANTCONDITION) \
876 #if defined(SFXGE_USE_BUS_SPACE_8)
877 #define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock) \
879 _NOTE(CONSTANTCONDITION) \
880 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
881 ("not power of 2 aligned")); \
883 _NOTE(CONSTANTCONDITION) \
885 SFXGE_BAR_LOCK(_esbp); \
887 EFSYS_PROBE5(bar_writeo, unsigned int, (_offset), \
888 uint32_t, (_eop)->eo_u32[3], \
889 uint32_t, (_eop)->eo_u32[2], \
890 uint32_t, (_eop)->eo_u32[1], \
891 uint32_t, (_eop)->eo_u32[0]); \
894 * Make sure that previous writes to the oword have \
895 * been done. It should be cheaper than barrier just \
896 * after the last write below. \
898 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
899 (_offset), sizeof (efx_oword_t), \
900 BUS_SPACE_BARRIER_WRITE); \
901 bus_space_write_stream_8((_esbp)->esb_tag, \
902 (_esbp)->esb_handle, \
903 (_offset), (_eop)->eo_u64[0]); \
905 * It should be guaranteed that the last qword comes \
906 * the last, so barrier entire oword to be sure that \
907 * neither above nor below writes are reordered. \
909 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
910 (_offset), sizeof (efx_oword_t), \
911 BUS_SPACE_BARRIER_WRITE); \
912 bus_space_write_stream_8((_esbp)->esb_tag, \
913 (_esbp)->esb_handle, \
914 (_offset) + 8, (_eop)->eo_u64[1]); \
916 _NOTE(CONSTANTCONDITION) \
918 SFXGE_BAR_UNLOCK(_esbp); \
919 _NOTE(CONSTANTCONDITION) \
923 #define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock) \
925 _NOTE(CONSTANTCONDITION) \
926 KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
927 ("not power of 2 aligned")); \
929 _NOTE(CONSTANTCONDITION) \
931 SFXGE_BAR_LOCK(_esbp); \
933 EFSYS_PROBE5(bar_writeo, unsigned int, (_offset), \
934 uint32_t, (_eop)->eo_u32[3], \
935 uint32_t, (_eop)->eo_u32[2], \
936 uint32_t, (_eop)->eo_u32[1], \
937 uint32_t, (_eop)->eo_u32[0]); \
940 * Make sure that previous writes to the oword have \
941 * been done. It should be cheaper than barrier just \
942 * after the last write below. \
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), (_eop)->eo_u32[0]); \
950 bus_space_write_stream_4((_esbp)->esb_tag, \
951 (_esbp)->esb_handle, \
952 (_offset) + 4, (_eop)->eo_u32[1]); \
953 bus_space_write_stream_4((_esbp)->esb_tag, \
954 (_esbp)->esb_handle, \
955 (_offset) + 8, (_eop)->eo_u32[2]); \
957 * It should be guaranteed that the last dword comes \
958 * the last, so barrier entire oword to be sure that \
959 * neither above nor below writes are reordered. \
961 bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
962 (_offset), sizeof (efx_oword_t), \
963 BUS_SPACE_BARRIER_WRITE); \
964 bus_space_write_stream_4((_esbp)->esb_tag, \
965 (_esbp)->esb_handle, \
966 (_offset) + 12, (_eop)->eo_u32[3]); \
968 _NOTE(CONSTANTCONDITION) \
970 SFXGE_BAR_UNLOCK(_esbp); \
971 _NOTE(CONSTANTCONDITION) \
975 /* Use the standard octo-word write for doorbell writes */
976 #define EFSYS_BAR_DOORBELL_WRITEO(_esbp, _offset, _eop) \
978 EFSYS_BAR_WRITEO((_esbp), (_offset), (_eop), B_FALSE); \
979 _NOTE(CONSTANTCONDITION) \
984 #define EFSYS_SPIN(_us) \
987 _NOTE(CONSTANTCONDITION) \
990 #define EFSYS_SLEEP EFSYS_SPIN
994 #define EFSYS_MEM_READ_BARRIER() rmb()
995 #define EFSYS_PIO_WRITE_BARRIER()
998 #define EFSYS_DMA_SYNC_FOR_KERNEL(_esmp, _offset, _size) \
1000 bus_dmamap_sync((_esmp)->esm_tag, \
1002 BUS_DMASYNC_POSTREAD); \
1003 _NOTE(CONSTANTCONDITION) \
1006 #define EFSYS_DMA_SYNC_FOR_DEVICE(_esmp, _offset, _size) \
1008 bus_dmamap_sync((_esmp)->esm_tag, \
1010 BUS_DMASYNC_PREWRITE); \
1011 _NOTE(CONSTANTCONDITION) \
1016 typedef clock_t efsys_timestamp_t;
1018 #define EFSYS_TIMESTAMP(_usp) \
1023 *(_usp) = now * hz / 1000000; \
1024 _NOTE(CONSTANTCONDITION) \
1029 #define EFSYS_KMEM_ALLOC(_esip, _size, _p) \
1031 (_esip) = (_esip); \
1033 * The macro is used in non-sleepable contexts, for \
1034 * example, holding a mutex. \
1036 (_p) = malloc((_size), M_SFXGE, M_NOWAIT|M_ZERO); \
1037 _NOTE(CONSTANTCONDITION) \
1040 #define EFSYS_KMEM_FREE(_esip, _size, _p) \
1044 free((_p), M_SFXGE); \
1045 _NOTE(CONSTANTCONDITION) \
1050 typedef struct efsys_lock_s {
1052 char lock_name[SFXGE_LOCK_NAME_MAX];
1055 #define SFXGE_EFSYS_LOCK_INIT(_eslp, _ifname, _label) \
1057 efsys_lock_t *__eslp = (_eslp); \
1059 snprintf((__eslp)->lock_name, \
1060 sizeof((__eslp)->lock_name), \
1061 "%s:%s", (_ifname), (_label)); \
1062 mtx_init(&(__eslp)->lock, (__eslp)->lock_name, \
1065 #define SFXGE_EFSYS_LOCK_DESTROY(_eslp) \
1066 mtx_destroy(&(_eslp)->lock)
1067 #define SFXGE_EFSYS_LOCK(_eslp) \
1068 mtx_lock(&(_eslp)->lock)
1069 #define SFXGE_EFSYS_UNLOCK(_eslp) \
1070 mtx_unlock(&(_eslp)->lock)
1071 #define SFXGE_EFSYS_LOCK_ASSERT_OWNED(_eslp) \
1072 mtx_assert(&(_eslp)->lock, MA_OWNED)
1074 typedef int efsys_lock_state_t;
1076 #define EFSYS_LOCK_MAGIC 0x000010c4
1078 #define EFSYS_LOCK(_lockp, _state) \
1080 SFXGE_EFSYS_LOCK(_lockp); \
1081 (_state) = EFSYS_LOCK_MAGIC; \
1082 _NOTE(CONSTANTCONDITION) \
1085 #define EFSYS_UNLOCK(_lockp, _state) \
1087 if ((_state) != EFSYS_LOCK_MAGIC) \
1088 KASSERT(B_FALSE, ("not locked")); \
1089 SFXGE_EFSYS_UNLOCK(_lockp); \
1090 _NOTE(CONSTANTCONDITION) \
1095 typedef uint64_t efsys_stat_t;
1097 #define EFSYS_STAT_INCR(_knp, _delta) \
1099 *(_knp) += (_delta); \
1100 _NOTE(CONSTANTCONDITION) \
1103 #define EFSYS_STAT_DECR(_knp, _delta) \
1105 *(_knp) -= (_delta); \
1106 _NOTE(CONSTANTCONDITION) \
1109 #define EFSYS_STAT_SET(_knp, _val) \
1112 _NOTE(CONSTANTCONDITION) \
1115 #define EFSYS_STAT_SET_QWORD(_knp, _valp) \
1117 *(_knp) = le64toh((_valp)->eq_u64[0]); \
1118 _NOTE(CONSTANTCONDITION) \
1121 #define EFSYS_STAT_SET_DWORD(_knp, _valp) \
1123 *(_knp) = le32toh((_valp)->ed_u32[0]); \
1124 _NOTE(CONSTANTCONDITION) \
1127 #define EFSYS_STAT_INCR_QWORD(_knp, _valp) \
1129 *(_knp) += le64toh((_valp)->eq_u64[0]); \
1130 _NOTE(CONSTANTCONDITION) \
1133 #define EFSYS_STAT_SUBR_QWORD(_knp, _valp) \
1135 *(_knp) -= le64toh((_valp)->eq_u64[0]); \
1136 _NOTE(CONSTANTCONDITION) \
1141 extern void sfxge_err(efsys_identifier_t *, unsigned int,
1142 uint32_t, uint32_t);
1144 #if EFSYS_OPT_DECODE_INTR_FATAL
1145 #define EFSYS_ERR(_esip, _code, _dword0, _dword1) \
1147 sfxge_err((_esip), (_code), (_dword0), (_dword1)); \
1148 _NOTE(CONSTANTCONDITION) \
1154 #define EFSYS_ASSERT(_exp) do { \
1156 panic("%s", #_exp); \
1159 #define EFSYS_ASSERT3(_x, _op, _y, _t) do { \
1160 const _t __x = (_t)(_x); \
1161 const _t __y = (_t)(_y); \
1162 if (!(__x _op __y)) \
1163 panic("assertion failed at %s:%u", __FILE__, __LINE__); \
1166 #define EFSYS_ASSERT3U(_x, _op, _y) EFSYS_ASSERT3(_x, _op, _y, uint64_t)
1167 #define EFSYS_ASSERT3S(_x, _op, _y) EFSYS_ASSERT3(_x, _op, _y, int64_t)
1168 #define EFSYS_ASSERT3P(_x, _op, _y) EFSYS_ASSERT3(_x, _op, _y, uintptr_t)
1172 #define EFSYS_HAS_ROTL_DWORD 0
1178 #endif /* _SYS_EFSYS_H */