1b02e3c0cf
The EFSYS_OPT_RX_HDR_SPLIT optional feature in the common code implemented the Lookahead Split feature of Windows. This split received packets at a preconfigured byte offset, and delivered the header and payload portions to separate receive queues. Now the common code interface has no callers, so remove it. Note that this should not be confused with the Header Data Split feature of Windows, which splits packets at a header boundary. Submitted by: Andy Moreton <amoreton at solarflare.com> Sponsored by: Solarflare Communications, Inc. MFC after: 2 days Differential Revision: https://reviews.freebsd.org/D4888
1230 lines
33 KiB
C
1230 lines
33 KiB
C
/*-
|
|
* Copyright (c) 2010-2015 Solarflare Communications Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This software was developed in part by Philip Paeps under contract for
|
|
* Solarflare Communications, Inc.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* The views and conclusions contained in the software and documentation are
|
|
* those of the authors and should not be interpreted as representing official
|
|
* policies, either expressed or implied, of the FreeBSD Project.
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
#ifndef _SYS_EFSYS_H
|
|
#define _SYS_EFSYS_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/bus.h>
|
|
#include <sys/endian.h>
|
|
#include <sys/lock.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/mbuf.h>
|
|
#include <sys/mutex.h>
|
|
#include <sys/rwlock.h>
|
|
#include <sys/sdt.h>
|
|
#include <sys/systm.h>
|
|
|
|
#include <machine/bus.h>
|
|
#include <machine/endian.h>
|
|
|
|
#define EFSYS_HAS_UINT64 1
|
|
#if defined(__x86_64__)
|
|
#define EFSYS_USE_UINT64 1
|
|
#else
|
|
#define EFSYS_USE_UINT64 0
|
|
#endif
|
|
#define EFSYS_HAS_SSE2_M128 0
|
|
#if _BYTE_ORDER == _BIG_ENDIAN
|
|
#define EFSYS_IS_BIG_ENDIAN 1
|
|
#define EFSYS_IS_LITTLE_ENDIAN 0
|
|
#elif _BYTE_ORDER == _LITTLE_ENDIAN
|
|
#define EFSYS_IS_BIG_ENDIAN 0
|
|
#define EFSYS_IS_LITTLE_ENDIAN 1
|
|
#endif
|
|
#include "efx_types.h"
|
|
|
|
/* Common code requires this */
|
|
#if __FreeBSD_version < 800068
|
|
#define memmove(d, s, l) bcopy(s, d, l)
|
|
#endif
|
|
|
|
/* FreeBSD equivalents of Solaris things */
|
|
#ifndef _NOTE
|
|
#define _NOTE(s)
|
|
#endif
|
|
|
|
#ifndef B_FALSE
|
|
#define B_FALSE FALSE
|
|
#endif
|
|
#ifndef B_TRUE
|
|
#define B_TRUE TRUE
|
|
#endif
|
|
|
|
#ifndef IS_P2ALIGNED
|
|
#define IS_P2ALIGNED(v, a) ((((uintptr_t)(v)) & ((uintptr_t)(a) - 1)) == 0)
|
|
#endif
|
|
|
|
#ifndef P2ROUNDUP
|
|
#define P2ROUNDUP(x, align) (-(-(x) & -(align)))
|
|
#endif
|
|
|
|
#ifndef P2ALIGN
|
|
#define P2ALIGN(_x, _a) ((_x) & -(_a))
|
|
#endif
|
|
|
|
#ifndef IS2P
|
|
#define ISP2(x) (((x) & ((x) - 1)) == 0)
|
|
#endif
|
|
|
|
#if defined(__x86_64__) && __FreeBSD_version >= 1000000
|
|
|
|
#define SFXGE_USE_BUS_SPACE_8 1
|
|
|
|
#if !defined(bus_space_read_stream_8)
|
|
|
|
#define bus_space_read_stream_8(t, h, o) \
|
|
bus_space_read_8((t), (h), (o))
|
|
|
|
#define bus_space_write_stream_8(t, h, o, v) \
|
|
bus_space_write_8((t), (h), (o), (v))
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#define ENOTACTIVE EINVAL
|
|
|
|
/* Memory type to use on FreeBSD */
|
|
MALLOC_DECLARE(M_SFXGE);
|
|
|
|
/* Machine dependend prefetch wrappers */
|
|
#if defined(__i386__) || defined(__amd64__)
|
|
static __inline void
|
|
prefetch_read_many(void *addr)
|
|
{
|
|
|
|
__asm__(
|
|
"prefetcht0 (%0)"
|
|
:
|
|
: "r" (addr));
|
|
}
|
|
|
|
static __inline void
|
|
prefetch_read_once(void *addr)
|
|
{
|
|
|
|
__asm__(
|
|
"prefetchnta (%0)"
|
|
:
|
|
: "r" (addr));
|
|
}
|
|
#elif defined(__sparc64__)
|
|
static __inline void
|
|
prefetch_read_many(void *addr)
|
|
{
|
|
|
|
__asm__(
|
|
"prefetch [%0], 0"
|
|
:
|
|
: "r" (addr));
|
|
}
|
|
|
|
static __inline void
|
|
prefetch_read_once(void *addr)
|
|
{
|
|
|
|
__asm__(
|
|
"prefetch [%0], 1"
|
|
:
|
|
: "r" (addr));
|
|
}
|
|
#else
|
|
static __inline void
|
|
prefetch_read_many(void *addr)
|
|
{
|
|
|
|
}
|
|
|
|
static __inline void
|
|
prefetch_read_once(void *addr)
|
|
{
|
|
|
|
}
|
|
#endif
|
|
|
|
#if defined(__i386__) || defined(__amd64__)
|
|
#include <vm/vm.h>
|
|
#include <vm/pmap.h>
|
|
#endif
|
|
static __inline void
|
|
sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map,
|
|
struct mbuf *m, bus_dma_segment_t *seg)
|
|
{
|
|
#if defined(__i386__) || defined(__amd64__)
|
|
seg->ds_addr = pmap_kextract(mtod(m, vm_offset_t));
|
|
seg->ds_len = m->m_len;
|
|
#else
|
|
int nsegstmp;
|
|
|
|
bus_dmamap_load_mbuf_sg(tag, map, m, seg, &nsegstmp, 0);
|
|
#endif
|
|
}
|
|
|
|
/* Modifiers used for Windows builds */
|
|
#define __in
|
|
#define __in_opt
|
|
#define __in_ecount(_n)
|
|
#define __in_ecount_opt(_n)
|
|
#define __in_bcount(_n)
|
|
#define __in_bcount_opt(_n)
|
|
|
|
#define __out
|
|
#define __out_opt
|
|
#define __out_ecount(_n)
|
|
#define __out_ecount_opt(_n)
|
|
#define __out_bcount(_n)
|
|
#define __out_bcount_opt(_n)
|
|
|
|
#define __deref_out
|
|
|
|
#define __inout
|
|
#define __inout_opt
|
|
#define __inout_ecount(_n)
|
|
#define __inout_ecount_opt(_n)
|
|
#define __inout_bcount(_n)
|
|
#define __inout_bcount_opt(_n)
|
|
#define __inout_bcount_full_opt(_n)
|
|
|
|
#define __deref_out_bcount_opt(n)
|
|
|
|
#define __checkReturn
|
|
#define __success(_x)
|
|
|
|
#define __drv_when(_p, _c)
|
|
|
|
/* Code inclusion options */
|
|
|
|
|
|
#define EFSYS_OPT_NAMES 1
|
|
|
|
#define EFSYS_OPT_FALCON 0
|
|
#define EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE 0
|
|
#define EFSYS_OPT_SIENA 1
|
|
#define EFSYS_OPT_HUNTINGTON 1
|
|
#define EFSYS_OPT_MEDFORD 0
|
|
#ifdef DEBUG
|
|
#define EFSYS_OPT_CHECK_REG 1
|
|
#else
|
|
#define EFSYS_OPT_CHECK_REG 0
|
|
#endif
|
|
|
|
#define EFSYS_OPT_MCDI 1
|
|
#define EFSYS_OPT_MCDI_LOGGING 0
|
|
#define EFSYS_OPT_MCDI_PROXY_AUTH 0
|
|
|
|
#define EFSYS_OPT_MAC_FALCON_GMAC 0
|
|
#define EFSYS_OPT_MAC_FALCON_XMAC 0
|
|
#define EFSYS_OPT_MAC_STATS 1
|
|
|
|
#define EFSYS_OPT_LOOPBACK 0
|
|
|
|
#define EFSYS_OPT_MON_NULL 0
|
|
#define EFSYS_OPT_MON_LM87 0
|
|
#define EFSYS_OPT_MON_MAX6647 0
|
|
#define EFSYS_OPT_MON_MCDI 0
|
|
#define EFSYS_OPT_MON_STATS 0
|
|
|
|
#define EFSYS_OPT_PHY_NULL 0
|
|
#define EFSYS_OPT_PHY_QT2022C2 0
|
|
#define EFSYS_OPT_PHY_SFX7101 0
|
|
#define EFSYS_OPT_PHY_TXC43128 0
|
|
#define EFSYS_OPT_PHY_SFT9001 0
|
|
#define EFSYS_OPT_PHY_QT2025C 0
|
|
#define EFSYS_OPT_PHY_STATS 1
|
|
#define EFSYS_OPT_PHY_PROPS 0
|
|
#define EFSYS_OPT_PHY_BIST 0
|
|
#define EFSYS_OPT_BIST 1
|
|
#define EFSYS_OPT_PHY_LED_CONTROL 1
|
|
#define EFSYS_OPT_PHY_FLAGS 0
|
|
|
|
#define EFSYS_OPT_VPD 1
|
|
#define EFSYS_OPT_NVRAM 1
|
|
#define EFSYS_OPT_NVRAM_FALCON_BOOTROM 0
|
|
#define EFSYS_OPT_NVRAM_SFT9001 0
|
|
#define EFSYS_OPT_NVRAM_SFX7101 0
|
|
#define EFSYS_OPT_BOOTCFG 0
|
|
|
|
#define EFSYS_OPT_PCIE_TUNE 0
|
|
#define EFSYS_OPT_DIAG 0
|
|
#define EFSYS_OPT_WOL 1
|
|
#define EFSYS_OPT_RX_SCALE 1
|
|
#define EFSYS_OPT_QSTATS 1
|
|
#define EFSYS_OPT_FILTER 1
|
|
#define EFSYS_OPT_RX_SCATTER 0
|
|
|
|
#define EFSYS_OPT_EV_PREFETCH 0
|
|
|
|
#define EFSYS_OPT_DECODE_INTR_FATAL 1
|
|
|
|
/* ID */
|
|
|
|
typedef struct __efsys_identifier_s efsys_identifier_t;
|
|
|
|
/* PROBE */
|
|
|
|
#ifndef DTRACE_PROBE
|
|
|
|
#define EFSYS_PROBE(_name)
|
|
|
|
#define EFSYS_PROBE1(_name, _type1, _arg1)
|
|
|
|
#define EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)
|
|
|
|
#define EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3)
|
|
|
|
#define EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4)
|
|
|
|
#define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5)
|
|
|
|
#define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5, \
|
|
_type6, _arg6)
|
|
|
|
#define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5, \
|
|
_type6, _arg6, _type7, _arg7)
|
|
|
|
#else /* DTRACE_PROBE */
|
|
|
|
#define EFSYS_PROBE(_name) \
|
|
DTRACE_PROBE(_name)
|
|
|
|
#define EFSYS_PROBE1(_name, _type1, _arg1) \
|
|
DTRACE_PROBE1(_name, _type1, _arg1)
|
|
|
|
#define EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2) \
|
|
DTRACE_PROBE2(_name, _type1, _arg1, _type2, _arg2)
|
|
|
|
#define EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3) \
|
|
DTRACE_PROBE3(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3)
|
|
|
|
#define EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4) \
|
|
DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4)
|
|
|
|
#ifdef DTRACE_PROBE5
|
|
#define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5) \
|
|
DTRACE_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5)
|
|
#else
|
|
#define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5) \
|
|
DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4)
|
|
#endif
|
|
|
|
#ifdef DTRACE_PROBE6
|
|
#define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5, \
|
|
_type6, _arg6) \
|
|
DTRACE_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5, \
|
|
_type6, _arg6)
|
|
#else
|
|
#define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5, \
|
|
_type6, _arg6) \
|
|
EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5)
|
|
#endif
|
|
|
|
#ifdef DTRACE_PROBE7
|
|
#define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5, \
|
|
_type6, _arg6, _type7, _arg7) \
|
|
DTRACE_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5, \
|
|
_type6, _arg6, _type7, _arg7)
|
|
#else
|
|
#define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5, \
|
|
_type6, _arg6, _type7, _arg7) \
|
|
EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2, \
|
|
_type3, _arg3, _type4, _arg4, _type5, _arg5, \
|
|
_type6, _arg6)
|
|
#endif
|
|
|
|
#endif /* DTRACE_PROBE */
|
|
|
|
/* DMA */
|
|
|
|
typedef uint64_t efsys_dma_addr_t;
|
|
|
|
typedef struct efsys_mem_s {
|
|
bus_dma_tag_t esm_tag;
|
|
bus_dmamap_t esm_map;
|
|
caddr_t esm_base;
|
|
efsys_dma_addr_t esm_addr;
|
|
} efsys_mem_t;
|
|
|
|
|
|
#define EFSYS_MEM_ZERO(_esmp, _size) \
|
|
do { \
|
|
(void) memset((_esmp)->esm_base, 0, (_size)); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_MEM_READD(_esmp, _offset, _edp) \
|
|
do { \
|
|
uint32_t *addr; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
|
\
|
|
(_edp)->ed_u32[0] = *addr; \
|
|
\
|
|
EFSYS_PROBE2(mem_readd, unsigned int, (_offset), \
|
|
uint32_t, (_edp)->ed_u32[0]); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#if defined(__x86_64__)
|
|
#define EFSYS_MEM_READQ(_esmp, _offset, _eqp) \
|
|
do { \
|
|
uint64_t *addr; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
|
\
|
|
(_eqp)->eq_u64[0] = *addr; \
|
|
\
|
|
EFSYS_PROBE3(mem_readq, unsigned int, (_offset), \
|
|
uint32_t, (_eqp)->eq_u32[1], \
|
|
uint32_t, (_eqp)->eq_u32[0]); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#else
|
|
#define EFSYS_MEM_READQ(_esmp, _offset, _eqp) \
|
|
do { \
|
|
uint32_t *addr; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
|
\
|
|
(_eqp)->eq_u32[0] = *addr++; \
|
|
(_eqp)->eq_u32[1] = *addr; \
|
|
\
|
|
EFSYS_PROBE3(mem_readq, unsigned int, (_offset), \
|
|
uint32_t, (_eqp)->eq_u32[1], \
|
|
uint32_t, (_eqp)->eq_u32[0]); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#endif
|
|
|
|
#if defined(__x86_64__)
|
|
#define EFSYS_MEM_READO(_esmp, _offset, _eop) \
|
|
do { \
|
|
uint64_t *addr; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
|
\
|
|
(_eop)->eo_u64[0] = *addr++; \
|
|
(_eop)->eo_u64[1] = *addr; \
|
|
\
|
|
EFSYS_PROBE5(mem_reado, unsigned int, (_offset), \
|
|
uint32_t, (_eop)->eo_u32[3], \
|
|
uint32_t, (_eop)->eo_u32[2], \
|
|
uint32_t, (_eop)->eo_u32[1], \
|
|
uint32_t, (_eop)->eo_u32[0]); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#else
|
|
#define EFSYS_MEM_READO(_esmp, _offset, _eop) \
|
|
do { \
|
|
uint32_t *addr; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
|
\
|
|
(_eop)->eo_u32[0] = *addr++; \
|
|
(_eop)->eo_u32[1] = *addr++; \
|
|
(_eop)->eo_u32[2] = *addr++; \
|
|
(_eop)->eo_u32[3] = *addr; \
|
|
\
|
|
EFSYS_PROBE5(mem_reado, unsigned int, (_offset), \
|
|
uint32_t, (_eop)->eo_u32[3], \
|
|
uint32_t, (_eop)->eo_u32[2], \
|
|
uint32_t, (_eop)->eo_u32[1], \
|
|
uint32_t, (_eop)->eo_u32[0]); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#endif
|
|
|
|
#define EFSYS_MEM_WRITED(_esmp, _offset, _edp) \
|
|
do { \
|
|
uint32_t *addr; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
EFSYS_PROBE2(mem_writed, unsigned int, (_offset), \
|
|
uint32_t, (_edp)->ed_u32[0]); \
|
|
\
|
|
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
|
\
|
|
*addr = (_edp)->ed_u32[0]; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#if defined(__x86_64__)
|
|
#define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp) \
|
|
do { \
|
|
uint64_t *addr; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
EFSYS_PROBE3(mem_writeq, unsigned int, (_offset), \
|
|
uint32_t, (_eqp)->eq_u32[1], \
|
|
uint32_t, (_eqp)->eq_u32[0]); \
|
|
\
|
|
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
|
\
|
|
*addr = (_eqp)->eq_u64[0]; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#else
|
|
#define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp) \
|
|
do { \
|
|
uint32_t *addr; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
EFSYS_PROBE3(mem_writeq, unsigned int, (_offset), \
|
|
uint32_t, (_eqp)->eq_u32[1], \
|
|
uint32_t, (_eqp)->eq_u32[0]); \
|
|
\
|
|
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
|
\
|
|
*addr++ = (_eqp)->eq_u32[0]; \
|
|
*addr = (_eqp)->eq_u32[1]; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#endif
|
|
|
|
#if defined(__x86_64__)
|
|
#define EFSYS_MEM_WRITEO(_esmp, _offset, _eop) \
|
|
do { \
|
|
uint64_t *addr; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
EFSYS_PROBE5(mem_writeo, unsigned int, (_offset), \
|
|
uint32_t, (_eop)->eo_u32[3], \
|
|
uint32_t, (_eop)->eo_u32[2], \
|
|
uint32_t, (_eop)->eo_u32[1], \
|
|
uint32_t, (_eop)->eo_u32[0]); \
|
|
\
|
|
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
|
\
|
|
*addr++ = (_eop)->eo_u64[0]; \
|
|
*addr = (_eop)->eo_u64[1]; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#else
|
|
#define EFSYS_MEM_WRITEO(_esmp, _offset, _eop) \
|
|
do { \
|
|
uint32_t *addr; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
EFSYS_PROBE5(mem_writeo, unsigned int, (_offset), \
|
|
uint32_t, (_eop)->eo_u32[3], \
|
|
uint32_t, (_eop)->eo_u32[2], \
|
|
uint32_t, (_eop)->eo_u32[1], \
|
|
uint32_t, (_eop)->eo_u32[0]); \
|
|
\
|
|
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
|
\
|
|
*addr++ = (_eop)->eo_u32[0]; \
|
|
*addr++ = (_eop)->eo_u32[1]; \
|
|
*addr++ = (_eop)->eo_u32[2]; \
|
|
*addr = (_eop)->eo_u32[3]; \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#endif
|
|
|
|
#define EFSYS_MEM_ADDR(_esmp) \
|
|
((_esmp)->esm_addr)
|
|
|
|
#define EFSYS_MEM_IS_NULL(_esmp) \
|
|
((_esmp)->esm_base == NULL)
|
|
|
|
/* BAR */
|
|
|
|
#define SFXGE_LOCK_NAME_MAX 16
|
|
|
|
typedef struct efsys_bar_s {
|
|
struct mtx esb_lock;
|
|
char esb_lock_name[SFXGE_LOCK_NAME_MAX];
|
|
bus_space_tag_t esb_tag;
|
|
bus_space_handle_t esb_handle;
|
|
int esb_rid;
|
|
struct resource *esb_res;
|
|
} efsys_bar_t;
|
|
|
|
#define SFXGE_BAR_LOCK_INIT(_esbp, _ifname) \
|
|
do { \
|
|
snprintf((_esbp)->esb_lock_name, \
|
|
sizeof((_esbp)->esb_lock_name), \
|
|
"%s:bar", (_ifname)); \
|
|
mtx_init(&(_esbp)->esb_lock, (_esbp)->esb_lock_name, \
|
|
NULL, MTX_DEF); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#define SFXGE_BAR_LOCK_DESTROY(_esbp) \
|
|
mtx_destroy(&(_esbp)->esb_lock)
|
|
#define SFXGE_BAR_LOCK(_esbp) \
|
|
mtx_lock(&(_esbp)->esb_lock)
|
|
#define SFXGE_BAR_UNLOCK(_esbp) \
|
|
mtx_unlock(&(_esbp)->esb_lock)
|
|
|
|
#define EFSYS_BAR_READD(_esbp, _offset, _edp, _lock) \
|
|
do { \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_LOCK(_esbp); \
|
|
\
|
|
(_edp)->ed_u32[0] = bus_space_read_stream_4( \
|
|
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
|
(_offset)); \
|
|
\
|
|
EFSYS_PROBE2(bar_readd, unsigned int, (_offset), \
|
|
uint32_t, (_edp)->ed_u32[0]); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_UNLOCK(_esbp); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#if defined(SFXGE_USE_BUS_SPACE_8)
|
|
#define EFSYS_BAR_READQ(_esbp, _offset, _eqp) \
|
|
do { \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
SFXGE_BAR_LOCK(_esbp); \
|
|
\
|
|
(_eqp)->eq_u64[0] = bus_space_read_stream_8( \
|
|
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
|
(_offset)); \
|
|
\
|
|
EFSYS_PROBE3(bar_readq, unsigned int, (_offset), \
|
|
uint32_t, (_eqp)->eq_u32[1], \
|
|
uint32_t, (_eqp)->eq_u32[0]); \
|
|
\
|
|
SFXGE_BAR_UNLOCK(_esbp); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock) \
|
|
do { \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_LOCK(_esbp); \
|
|
\
|
|
(_eop)->eo_u64[0] = bus_space_read_stream_8( \
|
|
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
|
(_offset)); \
|
|
(_eop)->eo_u64[1] = bus_space_read_stream_8( \
|
|
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
|
(_offset) + 8); \
|
|
\
|
|
EFSYS_PROBE5(bar_reado, unsigned int, (_offset), \
|
|
uint32_t, (_eop)->eo_u32[3], \
|
|
uint32_t, (_eop)->eo_u32[2], \
|
|
uint32_t, (_eop)->eo_u32[1], \
|
|
uint32_t, (_eop)->eo_u32[0]); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_UNLOCK(_esbp); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#else
|
|
#define EFSYS_BAR_READQ(_esbp, _offset, _eqp) \
|
|
do { \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
SFXGE_BAR_LOCK(_esbp); \
|
|
\
|
|
(_eqp)->eq_u32[0] = bus_space_read_stream_4( \
|
|
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
|
(_offset)); \
|
|
(_eqp)->eq_u32[1] = bus_space_read_stream_4( \
|
|
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
|
(_offset) + 4); \
|
|
\
|
|
EFSYS_PROBE3(bar_readq, unsigned int, (_offset), \
|
|
uint32_t, (_eqp)->eq_u32[1], \
|
|
uint32_t, (_eqp)->eq_u32[0]); \
|
|
\
|
|
SFXGE_BAR_UNLOCK(_esbp); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock) \
|
|
do { \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_LOCK(_esbp); \
|
|
\
|
|
(_eop)->eo_u32[0] = bus_space_read_stream_4( \
|
|
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
|
(_offset)); \
|
|
(_eop)->eo_u32[1] = bus_space_read_stream_4( \
|
|
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
|
(_offset) + 4); \
|
|
(_eop)->eo_u32[2] = bus_space_read_stream_4( \
|
|
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
|
(_offset) + 8); \
|
|
(_eop)->eo_u32[3] = bus_space_read_stream_4( \
|
|
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
|
(_offset) + 12); \
|
|
\
|
|
EFSYS_PROBE5(bar_reado, unsigned int, (_offset), \
|
|
uint32_t, (_eop)->eo_u32[3], \
|
|
uint32_t, (_eop)->eo_u32[2], \
|
|
uint32_t, (_eop)->eo_u32[1], \
|
|
uint32_t, (_eop)->eo_u32[0]); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_UNLOCK(_esbp); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#endif
|
|
|
|
#define EFSYS_BAR_WRITED(_esbp, _offset, _edp, _lock) \
|
|
do { \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_LOCK(_esbp); \
|
|
\
|
|
EFSYS_PROBE2(bar_writed, unsigned int, (_offset), \
|
|
uint32_t, (_edp)->ed_u32[0]); \
|
|
\
|
|
/* \
|
|
* Make sure that previous writes to the dword have \
|
|
* been done. It should be cheaper than barrier just \
|
|
* after the write below. \
|
|
*/ \
|
|
bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
|
(_offset), sizeof (efx_dword_t), \
|
|
BUS_SPACE_BARRIER_WRITE); \
|
|
bus_space_write_stream_4((_esbp)->esb_tag, \
|
|
(_esbp)->esb_handle, \
|
|
(_offset), (_edp)->ed_u32[0]); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_UNLOCK(_esbp); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#if defined(SFXGE_USE_BUS_SPACE_8)
|
|
#define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp) \
|
|
do { \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
SFXGE_BAR_LOCK(_esbp); \
|
|
\
|
|
EFSYS_PROBE3(bar_writeq, unsigned int, (_offset), \
|
|
uint32_t, (_eqp)->eq_u32[1], \
|
|
uint32_t, (_eqp)->eq_u32[0]); \
|
|
\
|
|
/* \
|
|
* Make sure that previous writes to the qword have \
|
|
* been done. It should be cheaper than barrier just \
|
|
* after the write below. \
|
|
*/ \
|
|
bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
|
(_offset), sizeof (efx_qword_t), \
|
|
BUS_SPACE_BARRIER_WRITE); \
|
|
bus_space_write_stream_8((_esbp)->esb_tag, \
|
|
(_esbp)->esb_handle, \
|
|
(_offset), (_eqp)->eq_u64[0]); \
|
|
\
|
|
SFXGE_BAR_UNLOCK(_esbp); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#else
|
|
#define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp) \
|
|
do { \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
SFXGE_BAR_LOCK(_esbp); \
|
|
\
|
|
EFSYS_PROBE3(bar_writeq, unsigned int, (_offset), \
|
|
uint32_t, (_eqp)->eq_u32[1], \
|
|
uint32_t, (_eqp)->eq_u32[0]); \
|
|
\
|
|
/* \
|
|
* Make sure that previous writes to the qword have \
|
|
* been done. It should be cheaper than barrier just \
|
|
* after the last write below. \
|
|
*/ \
|
|
bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
|
(_offset), sizeof (efx_qword_t), \
|
|
BUS_SPACE_BARRIER_WRITE); \
|
|
bus_space_write_stream_4((_esbp)->esb_tag, \
|
|
(_esbp)->esb_handle, \
|
|
(_offset), (_eqp)->eq_u32[0]); \
|
|
/* \
|
|
* It should be guaranteed that the last dword comes \
|
|
* the last, so barrier entire qword to be sure that \
|
|
* neither above nor below writes are reordered. \
|
|
*/ \
|
|
bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
|
(_offset), sizeof (efx_qword_t), \
|
|
BUS_SPACE_BARRIER_WRITE); \
|
|
bus_space_write_stream_4((_esbp)->esb_tag, \
|
|
(_esbp)->esb_handle, \
|
|
(_offset) + 4, (_eqp)->eq_u32[1]); \
|
|
\
|
|
SFXGE_BAR_UNLOCK(_esbp); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#endif
|
|
|
|
/*
|
|
* Guarantees 64bit aligned 64bit writes to write combined BAR mapping
|
|
* (required by PIO hardware)
|
|
*/
|
|
#define EFSYS_BAR_WC_WRITEQ(_esbp, _offset, _eqp) \
|
|
do { \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
(void) (_esbp); \
|
|
\
|
|
/* FIXME: Perform a 64-bit write */ \
|
|
KASSERT(0, ("not implemented")); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#if defined(SFXGE_USE_BUS_SPACE_8)
|
|
#define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock) \
|
|
do { \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_LOCK(_esbp); \
|
|
\
|
|
EFSYS_PROBE5(bar_writeo, unsigned int, (_offset), \
|
|
uint32_t, (_eop)->eo_u32[3], \
|
|
uint32_t, (_eop)->eo_u32[2], \
|
|
uint32_t, (_eop)->eo_u32[1], \
|
|
uint32_t, (_eop)->eo_u32[0]); \
|
|
\
|
|
/* \
|
|
* Make sure that previous writes to the oword have \
|
|
* been done. It should be cheaper than barrier just \
|
|
* after the last write below. \
|
|
*/ \
|
|
bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
|
(_offset), sizeof (efx_oword_t), \
|
|
BUS_SPACE_BARRIER_WRITE); \
|
|
bus_space_write_stream_8((_esbp)->esb_tag, \
|
|
(_esbp)->esb_handle, \
|
|
(_offset), (_eop)->eo_u64[0]); \
|
|
/* \
|
|
* It should be guaranteed that the last qword comes \
|
|
* the last, so barrier entire oword to be sure that \
|
|
* neither above nor below writes are reordered. \
|
|
*/ \
|
|
bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
|
(_offset), sizeof (efx_oword_t), \
|
|
BUS_SPACE_BARRIER_WRITE); \
|
|
bus_space_write_stream_8((_esbp)->esb_tag, \
|
|
(_esbp)->esb_handle, \
|
|
(_offset) + 8, (_eop)->eo_u64[1]); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_UNLOCK(_esbp); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#else
|
|
#define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock) \
|
|
do { \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
|
("not power of 2 aligned")); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_LOCK(_esbp); \
|
|
\
|
|
EFSYS_PROBE5(bar_writeo, unsigned int, (_offset), \
|
|
uint32_t, (_eop)->eo_u32[3], \
|
|
uint32_t, (_eop)->eo_u32[2], \
|
|
uint32_t, (_eop)->eo_u32[1], \
|
|
uint32_t, (_eop)->eo_u32[0]); \
|
|
\
|
|
/* \
|
|
* Make sure that previous writes to the oword have \
|
|
* been done. It should be cheaper than barrier just \
|
|
* after the last write below. \
|
|
*/ \
|
|
bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
|
(_offset), sizeof (efx_oword_t), \
|
|
BUS_SPACE_BARRIER_WRITE); \
|
|
bus_space_write_stream_4((_esbp)->esb_tag, \
|
|
(_esbp)->esb_handle, \
|
|
(_offset), (_eop)->eo_u32[0]); \
|
|
bus_space_write_stream_4((_esbp)->esb_tag, \
|
|
(_esbp)->esb_handle, \
|
|
(_offset) + 4, (_eop)->eo_u32[1]); \
|
|
bus_space_write_stream_4((_esbp)->esb_tag, \
|
|
(_esbp)->esb_handle, \
|
|
(_offset) + 8, (_eop)->eo_u32[2]); \
|
|
/* \
|
|
* It should be guaranteed that the last dword comes \
|
|
* the last, so barrier entire oword to be sure that \
|
|
* neither above nor below writes are reordered. \
|
|
*/ \
|
|
bus_space_barrier((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
|
(_offset), sizeof (efx_oword_t), \
|
|
BUS_SPACE_BARRIER_WRITE); \
|
|
bus_space_write_stream_4((_esbp)->esb_tag, \
|
|
(_esbp)->esb_handle, \
|
|
(_offset) + 12, (_eop)->eo_u32[3]); \
|
|
\
|
|
_NOTE(CONSTANTCONDITION) \
|
|
if (_lock) \
|
|
SFXGE_BAR_UNLOCK(_esbp); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#endif
|
|
|
|
/* Use the standard octo-word write for doorbell writes */
|
|
#define EFSYS_BAR_DOORBELL_WRITEO(_esbp, _offset, _eop) \
|
|
do { \
|
|
EFSYS_BAR_WRITEO((_esbp), (_offset), (_eop), B_FALSE); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
/* SPIN */
|
|
|
|
#define EFSYS_SPIN(_us) \
|
|
do { \
|
|
DELAY(_us); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_SLEEP EFSYS_SPIN
|
|
|
|
/* BARRIERS */
|
|
|
|
#define EFSYS_MEM_READ_BARRIER() rmb()
|
|
#define EFSYS_PIO_WRITE_BARRIER()
|
|
|
|
/* DMA SYNC */
|
|
#define EFSYS_DMA_SYNC_FOR_KERNEL(_esmp, _offset, _size) \
|
|
do { \
|
|
bus_dmamap_sync((_esmp)->esm_tag, \
|
|
(_esmp)->esm_map, \
|
|
BUS_DMASYNC_POSTREAD); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_DMA_SYNC_FOR_DEVICE(_esmp, _offset, _size) \
|
|
do { \
|
|
bus_dmamap_sync((_esmp)->esm_tag, \
|
|
(_esmp)->esm_map, \
|
|
BUS_DMASYNC_PREWRITE); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
/* TIMESTAMP */
|
|
|
|
typedef clock_t efsys_timestamp_t;
|
|
|
|
#define EFSYS_TIMESTAMP(_usp) \
|
|
do { \
|
|
clock_t now; \
|
|
\
|
|
now = ticks; \
|
|
*(_usp) = now * hz / 1000000; \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
/* KMEM */
|
|
|
|
#define EFSYS_KMEM_ALLOC(_esip, _size, _p) \
|
|
do { \
|
|
(_esip) = (_esip); \
|
|
/* \
|
|
* The macro is used in non-sleepable contexts, for \
|
|
* example, holding a mutex. \
|
|
*/ \
|
|
(_p) = malloc((_size), M_SFXGE, M_NOWAIT|M_ZERO); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_KMEM_FREE(_esip, _size, _p) \
|
|
do { \
|
|
(void) (_esip); \
|
|
(void) (_size); \
|
|
free((_p), M_SFXGE); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
/* LOCK */
|
|
|
|
typedef struct efsys_lock_s {
|
|
struct mtx lock;
|
|
char lock_name[SFXGE_LOCK_NAME_MAX];
|
|
} efsys_lock_t;
|
|
|
|
#define SFXGE_EFSYS_LOCK_INIT(_eslp, _ifname, _label) \
|
|
do { \
|
|
efsys_lock_t *__eslp = (_eslp); \
|
|
\
|
|
snprintf((__eslp)->lock_name, \
|
|
sizeof((__eslp)->lock_name), \
|
|
"%s:%s", (_ifname), (_label)); \
|
|
mtx_init(&(__eslp)->lock, (__eslp)->lock_name, \
|
|
NULL, MTX_DEF); \
|
|
} while (B_FALSE)
|
|
#define SFXGE_EFSYS_LOCK_DESTROY(_eslp) \
|
|
mtx_destroy(&(_eslp)->lock)
|
|
#define SFXGE_EFSYS_LOCK(_eslp) \
|
|
mtx_lock(&(_eslp)->lock)
|
|
#define SFXGE_EFSYS_UNLOCK(_eslp) \
|
|
mtx_unlock(&(_eslp)->lock)
|
|
#define SFXGE_EFSYS_LOCK_ASSERT_OWNED(_eslp) \
|
|
mtx_assert(&(_eslp)->lock, MA_OWNED)
|
|
|
|
#define EFSYS_LOCK_MAGIC 0x000010c4
|
|
|
|
#define EFSYS_LOCK(_lockp, _state) \
|
|
do { \
|
|
SFXGE_EFSYS_LOCK(_lockp); \
|
|
(_state) = EFSYS_LOCK_MAGIC; \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_UNLOCK(_lockp, _state) \
|
|
do { \
|
|
if ((_state) != EFSYS_LOCK_MAGIC) \
|
|
KASSERT(B_FALSE, ("not locked")); \
|
|
SFXGE_EFSYS_UNLOCK(_lockp); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
/* PREEMPT */
|
|
|
|
#define EFSYS_PREEMPT_DISABLE(_state) \
|
|
do { \
|
|
(_state) = (_state); \
|
|
critical_enter(); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_PREEMPT_ENABLE(_state) \
|
|
do { \
|
|
(_state) = (_state); \
|
|
critical_exit(_state); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
/* STAT */
|
|
|
|
typedef uint64_t efsys_stat_t;
|
|
|
|
#define EFSYS_STAT_INCR(_knp, _delta) \
|
|
do { \
|
|
*(_knp) += (_delta); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_STAT_DECR(_knp, _delta) \
|
|
do { \
|
|
*(_knp) -= (_delta); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_STAT_SET(_knp, _val) \
|
|
do { \
|
|
*(_knp) = (_val); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_STAT_SET_QWORD(_knp, _valp) \
|
|
do { \
|
|
*(_knp) = le64toh((_valp)->eq_u64[0]); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_STAT_SET_DWORD(_knp, _valp) \
|
|
do { \
|
|
*(_knp) = le32toh((_valp)->ed_u32[0]); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_STAT_INCR_QWORD(_knp, _valp) \
|
|
do { \
|
|
*(_knp) += le64toh((_valp)->eq_u64[0]); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
#define EFSYS_STAT_SUBR_QWORD(_knp, _valp) \
|
|
do { \
|
|
*(_knp) -= le64toh((_valp)->eq_u64[0]); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
|
|
/* ERR */
|
|
|
|
extern void sfxge_err(efsys_identifier_t *, unsigned int,
|
|
uint32_t, uint32_t);
|
|
|
|
#if EFSYS_OPT_DECODE_INTR_FATAL
|
|
#define EFSYS_ERR(_esip, _code, _dword0, _dword1) \
|
|
do { \
|
|
sfxge_err((_esip), (_code), (_dword0), (_dword1)); \
|
|
_NOTE(CONSTANTCONDITION) \
|
|
} while (B_FALSE)
|
|
#endif
|
|
|
|
/* ASSERT */
|
|
|
|
#define EFSYS_ASSERT(_exp) do { \
|
|
if (!(_exp)) \
|
|
panic("%s", #_exp); \
|
|
} while (0)
|
|
|
|
#define EFSYS_ASSERT3(_x, _op, _y, _t) do { \
|
|
const _t __x = (_t)(_x); \
|
|
const _t __y = (_t)(_y); \
|
|
if (!(__x _op __y)) \
|
|
panic("assertion failed at %s:%u", __FILE__, __LINE__); \
|
|
} while(0)
|
|
|
|
#define EFSYS_ASSERT3U(_x, _op, _y) EFSYS_ASSERT3(_x, _op, _y, uint64_t)
|
|
#define EFSYS_ASSERT3S(_x, _op, _y) EFSYS_ASSERT3(_x, _op, _y, int64_t)
|
|
#define EFSYS_ASSERT3P(_x, _op, _y) EFSYS_ASSERT3(_x, _op, _y, uintptr_t)
|
|
|
|
/* ROTATE */
|
|
|
|
#define EFSYS_HAS_ROTL_DWORD 0
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _SYS_EFSYS_H */
|