git: f8ab2f5bae1d - main - LinuxKPI: Add linux/iosys-map.h header

From: Vladimir Kondratyev <wulf_at_FreeBSD.org>
Date: Sun, 24 Dec 2023 08:23:02 UTC
The branch main has been updated by wulf:

URL: https://cgit.FreeBSD.org/src/commit/?id=f8ab2f5bae1d4e4e13f95f4738c9bb49fcda6261

commit f8ab2f5bae1d4e4e13f95f4738c9bb49fcda6261
Author:     Vladimir Kondratyev <wulf@FreeBSD.org>
AuthorDate: 2023-12-24 08:19:58 +0000
Commit:     Vladimir Kondratyev <wulf@FreeBSD.org>
CommitDate: 2023-12-24 08:19:58 +0000

    LinuxKPI: Add linux/iosys-map.h header
    
    Sponsored by:   Serenity Cyber Security, LLC
    Obtained from:  OpenBSD
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D42799
---
 .../linuxkpi/common/include/linux/iosys-map.h      | 161 +++++++++++++++++++++
 1 file changed, 161 insertions(+)

diff --git a/sys/compat/linuxkpi/common/include/linux/iosys-map.h b/sys/compat/linuxkpi/common/include/linux/iosys-map.h
new file mode 100644
index 000000000000..66c442b8668f
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/linux/iosys-map.h
@@ -0,0 +1,161 @@
+/* Public domain. */
+
+#ifndef _LINUXKPI_LINUX_IOSYS_MAP_H
+#define _LINUXKPI_LINUX_IOSYS_MAP_H
+
+#include <linux/io.h>
+#include <linux/string.h>
+
+struct iosys_map {
+	union {
+		void *vaddr_iomem;
+		void *vaddr;
+	};
+	bool is_iomem;
+#ifdef __OpenBSD__
+	bus_space_handle_t bsh;
+	bus_size_t size;
+#endif
+};
+
+#define IOSYS_MAP_INIT_OFFSET(_ism_src_p, _off) ({			\
+	struct iosys_map ism_dst = *(_ism_src_p);			\
+	iosys_map_incr(&ism_dst, _off);					\
+	ism_dst;							\
+})
+
+static inline void
+iosys_map_incr(struct iosys_map *ism, size_t n)
+{
+	if (ism->is_iomem)
+		ism->vaddr_iomem += n;
+	else
+		ism->vaddr += n;
+}
+
+static inline void
+iosys_map_memcpy_to(struct iosys_map *ism, size_t off, const void *src,
+    size_t len)
+{
+	if (ism->is_iomem)
+		memcpy_toio(ism->vaddr_iomem + off, src, len);
+	else
+		memcpy(ism->vaddr + off, src, len);
+}
+
+static inline bool
+iosys_map_is_null(const struct iosys_map *ism)
+{
+	if (ism->is_iomem)
+		return (ism->vaddr_iomem == NULL);
+	else
+		return (ism->vaddr == NULL);
+}
+
+static inline bool
+iosys_map_is_set(const struct iosys_map *ism)
+{
+	if (ism->is_iomem)
+		return (ism->vaddr_iomem != NULL);
+	else
+		return (ism->vaddr != NULL);
+}
+
+static inline bool
+iosys_map_is_equal(const struct iosys_map *ism_a,
+    const struct iosys_map *ism_b)
+{
+	if (ism_a->is_iomem != ism_b->is_iomem)
+		return (false);
+
+	if (ism_a->is_iomem)
+		return (ism_a->vaddr_iomem == ism_b->vaddr_iomem);
+	else
+		return (ism_a->vaddr == ism_b->vaddr);
+}
+
+static inline void
+iosys_map_clear(struct iosys_map *ism)
+{
+	if (ism->is_iomem) {
+		ism->vaddr_iomem = NULL;
+		ism->is_iomem = false;
+	} else {
+		ism->vaddr = NULL;
+	}
+}
+
+static inline void
+iosys_map_set_vaddr_iomem(struct iosys_map *ism, void *addr)
+{
+	ism->vaddr_iomem = addr;
+	ism->is_iomem = true;
+}
+
+static inline void
+iosys_map_set_vaddr(struct iosys_map *ism, void *addr)
+{
+	ism->vaddr = addr;
+	ism->is_iomem = false;
+}
+
+static inline void
+iosys_map_memset(struct iosys_map *ism, size_t off, int value, size_t len)
+{
+	if (ism->is_iomem)
+		memset_io(ism->vaddr_iomem + off, value, len);
+	else
+		memset(ism->vaddr + off, value, len);
+}
+
+#ifdef __LP64__
+#define	_iosys_map_readq(_addr)			readq(_addr)
+#define	_iosys_map_writeq(_val, _addr)		writeq(_val, _addr)
+#else
+#define	_iosys_map_readq(_addr) ({					\
+	uint64_t val;							\
+	memcpy_fromio(&val, _addr, sizeof(uint64_t));			\
+	val;								\
+})
+#define	_iosys_map_writeq(_val, _addr)					\
+	memcpy_toio(_addr, &(_val), sizeof(uint64_t))
+#endif
+
+#define	iosys_map_rd(_ism, _off, _type) ({				\
+	_type val;							\
+	if ((_ism)->is_iomem) {						\
+		void *addr = (_ism)->vaddr_iomem + (_off);		\
+		val = _Generic(val,					\
+		    uint8_t : readb(addr),				\
+		    uint16_t: readw(addr),				\
+		    uint32_t: readl(addr),				\
+		    uint64_t: _iosys_map_readq(addr));			\
+	} else								\
+		val = READ_ONCE(*(_type *)((_ism)->vaddr + (_off)));	\
+	val;								\
+})
+#define	iosys_map_wr(_ism, _off, _type, _val) ({			\
+	_type val = (_val);						\
+	if ((_ism)->is_iomem) {						\
+		void *addr = (_ism)->vaddr_iomem + (_off);		\
+		_Generic(val,						\
+		    uint8_t : writeb(val, addr),			\
+		    uint16_t: writew(val, addr),			\
+		    uint32_t: writel(val, addr),			\
+		    uint64_t: _iosys_map_writeq(val, addr));		\
+	} else								\
+		WRITE_ONCE(*(_type *)((_ism)->vaddr + (_off)), val);	\
+})
+
+#define	iosys_map_rd_field(_ism, _off, _type, _field) ({		\
+	_type *s;							\
+	iosys_map_rd(_ism, (_off) + offsetof(_type, _field),		\
+	    __typeof(s->_field));					\
+})
+#define	iosys_map_wr_field(_ism, _off, _type, _field, _val) ({		\
+	_type *s;							\
+	iosys_map_wr(_ism, (_off) + offsetof(_type, _field),		\
+	    __typeof(s->_field), _val);					\
+})
+
+#endif