1 /* Public domain. */ 2 3 #ifndef _LINUXKPI_LINUX_IOSYS_MAP_H 4 #define _LINUXKPI_LINUX_IOSYS_MAP_H 5 6 #include <linux/io.h> 7 #include <linux/string.h> 8 9 struct iosys_map { 10 union { 11 void *vaddr_iomem; 12 void *vaddr; 13 }; 14 bool is_iomem; 15 #ifdef __OpenBSD__ 16 bus_space_handle_t bsh; 17 bus_size_t size; 18 #endif 19 }; 20 21 #define IOSYS_MAP_INIT_OFFSET(_ism_src_p, _off) ({ \ 22 struct iosys_map ism_dst = *(_ism_src_p); \ 23 iosys_map_incr(&ism_dst, _off); \ 24 ism_dst; \ 25 }) 26 27 static inline void 28 iosys_map_incr(struct iosys_map *ism, size_t n) 29 { 30 if (ism->is_iomem) 31 ism->vaddr_iomem += n; 32 else 33 ism->vaddr += n; 34 } 35 36 static inline void 37 iosys_map_memcpy_to(struct iosys_map *ism, size_t off, const void *src, 38 size_t len) 39 { 40 if (ism->is_iomem) 41 memcpy_toio(ism->vaddr_iomem + off, src, len); 42 else 43 memcpy(ism->vaddr + off, src, len); 44 } 45 46 static inline bool 47 iosys_map_is_null(const struct iosys_map *ism) 48 { 49 if (ism->is_iomem) 50 return (ism->vaddr_iomem == NULL); 51 else 52 return (ism->vaddr == NULL); 53 } 54 55 static inline bool 56 iosys_map_is_set(const struct iosys_map *ism) 57 { 58 if (ism->is_iomem) 59 return (ism->vaddr_iomem != NULL); 60 else 61 return (ism->vaddr != NULL); 62 } 63 64 static inline bool 65 iosys_map_is_equal(const struct iosys_map *ism_a, 66 const struct iosys_map *ism_b) 67 { 68 if (ism_a->is_iomem != ism_b->is_iomem) 69 return (false); 70 71 if (ism_a->is_iomem) 72 return (ism_a->vaddr_iomem == ism_b->vaddr_iomem); 73 else 74 return (ism_a->vaddr == ism_b->vaddr); 75 } 76 77 static inline void 78 iosys_map_clear(struct iosys_map *ism) 79 { 80 if (ism->is_iomem) { 81 ism->vaddr_iomem = NULL; 82 ism->is_iomem = false; 83 } else { 84 ism->vaddr = NULL; 85 } 86 } 87 88 static inline void 89 iosys_map_set_vaddr_iomem(struct iosys_map *ism, void *addr) 90 { 91 ism->vaddr_iomem = addr; 92 ism->is_iomem = true; 93 } 94 95 static inline void 96 iosys_map_set_vaddr(struct iosys_map *ism, void *addr) 97 { 98 ism->vaddr = addr; 99 ism->is_iomem = false; 100 } 101 102 static inline void 103 iosys_map_memset(struct iosys_map *ism, size_t off, int value, size_t len) 104 { 105 if (ism->is_iomem) 106 memset_io(ism->vaddr_iomem + off, value, len); 107 else 108 memset(ism->vaddr + off, value, len); 109 } 110 111 #ifdef __LP64__ 112 #define _iosys_map_readq(_addr) readq(_addr) 113 #define _iosys_map_writeq(_val, _addr) writeq(_val, _addr) 114 #else 115 #define _iosys_map_readq(_addr) ({ \ 116 uint64_t val; \ 117 memcpy_fromio(&val, _addr, sizeof(uint64_t)); \ 118 val; \ 119 }) 120 #define _iosys_map_writeq(_val, _addr) \ 121 memcpy_toio(_addr, &(_val), sizeof(uint64_t)) 122 #endif 123 124 #define iosys_map_rd(_ism, _off, _type) ({ \ 125 _type val; \ 126 if ((_ism)->is_iomem) { \ 127 void *addr = (_ism)->vaddr_iomem + (_off); \ 128 val = _Generic(val, \ 129 uint8_t : readb(addr), \ 130 uint16_t: readw(addr), \ 131 uint32_t: readl(addr), \ 132 uint64_t: _iosys_map_readq(addr)); \ 133 } else \ 134 val = READ_ONCE(*(_type *)((_ism)->vaddr + (_off))); \ 135 val; \ 136 }) 137 #define iosys_map_wr(_ism, _off, _type, _val) ({ \ 138 _type val = (_val); \ 139 if ((_ism)->is_iomem) { \ 140 void *addr = (_ism)->vaddr_iomem + (_off); \ 141 _Generic(val, \ 142 uint8_t : writeb(val, addr), \ 143 uint16_t: writew(val, addr), \ 144 uint32_t: writel(val, addr), \ 145 uint64_t: _iosys_map_writeq(val, addr)); \ 146 } else \ 147 WRITE_ONCE(*(_type *)((_ism)->vaddr + (_off)), val); \ 148 }) 149 150 #define iosys_map_rd_field(_ism, _off, _type, _field) ({ \ 151 _type *s; \ 152 iosys_map_rd(_ism, (_off) + offsetof(_type, _field), \ 153 __typeof(s->_field)); \ 154 }) 155 #define iosys_map_wr_field(_ism, _off, _type, _field, _val) ({ \ 156 _type *s; \ 157 iosys_map_wr(_ism, (_off) + offsetof(_type, _field), \ 158 __typeof(s->_field), _val); \ 159 }) 160 161 #endif 162